cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sgreb...@apache.org
Subject [3/3] cordova-paramedic git commit: Paramedic real time logging and other improvements
Date Tue, 12 Apr 2016 06:48:55 GMT
Paramedic real time logging and other improvements

github close #3


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

Branch: refs/heads/master
Commit: 9655060c7a27371b72f5da16050a8b1b25f37bd3
Parents: 1458451
Author: sgrebnov <sergei.grebnov@gmail.com>
Authored: Tue Apr 12 09:44:42 2016 +0300
Committer: sgrebnov <sergei.grebnov@gmail.com>
Committed: Tue Apr 12 09:48:39 2016 +0300

----------------------------------------------------------------------
 .jshintrc                                 |  14 ++
 .travis.yml                               |   2 +
 README.md                                 | 142 ++++++++++--
 appveyor.yml                              |   3 -
 lib/LocalServer.js                        | 154 +++++++++++++
 lib/ParamedicConfig.js                    | 107 +++++++++
 lib/PluginsManager.js                     |  71 ++++++
 lib/Reporters.js                          |  31 +++
 lib/paramedic.js                          | 231 +++++++++++++++++++
 lib/utils/execWrapper.js                  |  39 ++++
 lib/utils/index.js                        |  23 ++
 main.js                                   |  69 +++---
 package.json                              |  26 ++-
 paramedic-plugin/JasmineParamedicProxy.js |  86 +++++++
 paramedic-plugin/paramedic.js             |  95 ++++++++
 paramedic-plugin/plugin.xml               |  37 +++
 paramedic-plugin/socket.io.js             |   4 +
 paramedic.js                              | 305 -------------------------
 sample-config/.paramedic.config.js        |  30 +++
 19 files changed, 1107 insertions(+), 362 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/.jshintrc
----------------------------------------------------------------------
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..e11705f
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,14 @@
+{
+    "node" : true
+  , "devel": true
+  , "bitwise": true
+  , "undef": true
+  , "trailing": true
+  , "quotmark": false
+  , "indent": 4
+  , "unused": "vars"
+  , "expr": true
+  , "latedef": "nofunc"
+  , "globals": {
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 3c02467..2b205db 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,6 +5,8 @@ install:
   - echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config 
   - npm install cordova
   - npm install ios-sim
+# w/o ios-deploy ios requirements check fails
+  - npm install ios-deploy
   - npm install
   - npm link
 script:

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 305feeb..3ad4a90 100644
--- a/README.md
+++ b/README.md
@@ -7,31 +7,145 @@ Runs cordova medic/buildbot tests locally.
 
 ... provides advanced levels of care at the point of illness or injury, including out of
hospital treatment, and diagnostic services
 
-To install :
+# To install :
 ``` $npm install cordova-paramedic ```
 
-Usage :
+## Supported Cordova Platforms
 
+- Android
+- iOS
+- Windows Phone 8
+- Windows (Windows 8.1, Windows Phone 8.1, Windows 10 Tablet/PC)
+- Browser
+
+# Usage
+
+Paramedic parameters could be passed via command line arguments or via separate configuration
file:
+
+```
+cordova-paramedic --platform PLATFORM --plugin PATH <other parameters>
+cordova-paramedic --config ./sample-config/.paramedic.config.js
+```
+
+## Command Line Interface
+
+####`--platform` (required)
+
+Specifies target cordova platform (could refer to local directory, npm or git)
+
+```
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser
+cordova-paramedic --platform ios@4.0 --plugin cordova-plugin-inappbrowser
+cordova-paramedic --platform ios@../cordova-ios --plugin cordova-plugin-inappbrowser
+cordova-paramedic --platform ios@https://github.com/apache/cordova-ios.git#4.1.0 --plugin
cordova-plugin-inappbrowser
+```
+
+####`--plugin` (required)
+
+Specifies test plugin, you may specify multiple --plugin flags and they will all be installed
and tested together. Similat to `platform` parameter you can refer to local (or absolute)
path, npm registry or git repo.
+
+```
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser
+cordova-paramedic --platform ios --plugin ../cordova-plugin-inappbrowser
+cordova-paramedic --platform ios --plugin https://github.com/apache/cordova-plugin-inappbrowser
+// several plugins
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser --plugin cordova-plugin-contacts
 ```
-cordova-paramedic --platform PLATFORM --plugin PATH [--justbuild --timeout MSECS --port PORTNUM
--browserify --verbose ]`PLATFORM` : the platform id, currently only supports 'ios'
-`PATH` : the relative or absolute path to a plugin folder
-	expected to have a 'tests' folder.
-	You may specify multiple --plugin flags and they will all
-	be installed and tested together.
-`MSECS` : (optional) time in millisecs to wait for tests to pass|fail 
-	(defaults to 10 minutes) 
-`PORTNUM` : (optional) port to use for posting results from emulator back to paramedic server
---justbuild : (optional) just builds the project, without running the tests 
---browserify : (optional) plugins are browserified into cordova.js 
---verbose : (optional) verbose mode. Display more information output
+####--justbuild (optional)
+
+Just builds the project, without running the tests.
+
+```
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser --justbuild
+```
+
+####--device (optional)
+
+Tests must be run on connected device instead of emulator.
 
 ```
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser --device
+```
+
+####--externalServerUrl (optional)
+
+Useful when testing on real device (`--device` parameter) so that tests results from device
could be posted back to paramedic server.
+
+```
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser --externalServerUrl
http://10.0.8.254
+```
+
+####--useTunnel (optional)
+
+Use [tunneling](https://www.npmjs.com/package/localtunnel) instead of local address (default
is false).
+Useful when testing on real devices and don't want to specify external ip address (see `--externalServerUrl`
above) of paramedic server.
+
+```
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser --useTunnel
+```
+
+####--browserify (optional)
+
+Plugins are browserified into cordova.js.
+
+```
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser --browserify
+```
+
+####--port (optional)
+
+Port to use for posting results from emulator back to paramedic server (default is from `8008`).
You can also specify a range using `--startport` and `endport` and paramedic will select the
first available.
+
+```
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser --port 8010
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser --startport 8000 endport
8020
+```
+
+####--verbose (optional)
+
+Verbose mode. Display more information output
+
+```
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser --verbose
+```
+
+####--timeout (optional)
+
+Time in millisecs to wait for tests to pass|fail (defaults to 10 minutes). 
+
+```
+cordova-paramedic --platform ios --plugin cordova-plugin-inappbrowser --timeout 30000
+```
+
+## Paramedic configuration file
+
+Configuration file is used when no parameters are passed to `cordova-paramedic` call or explicitly
specified via `--config` parameter:
+```
+cordova-paramedic  <- paramedic will attempt to find .paramedic.config.js in working directory
+cordova-paramedic --config ./sample-config/.paramedic.config.js
+```
+Example configuration file is showed below.
+```
+module.exports = {
+    // "externalServerUrl": "http://10.0.8.254",
+    "useTunnel": true,
+    "plugins": [
+        "https://github.com/apache/cordova-plugin-inappbrowser"
+    ],
+    "platform": "windows",
+    "action": "run",
+    "args": "--archs=x64 -- --appx=uap"
+}
+```
+More configuration file examples could be found in `sample-config` folder.
+
+## API Interface
 
 You can also use cordova-paramedic as a module directly :
 
 ```
   var paramedic = require('cordova-paramedic');
-  paramedic.run('ios', '../cordova-plugin-device', onCompleteCallback,justBuild,portNum,msTimeout,
useBrowserify, beSilent, beVerbose);
+  paramedic.run(config);
 ```
 
 

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/appveyor.yml
----------------------------------------------------------------------
diff --git a/appveyor.yml b/appveyor.yml
index 8a8cd0f..e4e7a1c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,9 +5,6 @@ install:
   - npm install cordova
   - npm install
   - npm link
-  - cd ..
-  - git clone https://github.com/apache/cordova-plugin-test-framework
-  - cd cordova-paramedic
 
 build: off
 

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/lib/LocalServer.js
----------------------------------------------------------------------
diff --git a/lib/LocalServer.js b/lib/LocalServer.js
new file mode 100644
index 0000000..0da48ac
--- /dev/null
+++ b/lib/LocalServer.js
@@ -0,0 +1,154 @@
+/**
+    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.
+*/
+
+var Q = require('q'),
+    io = require('socket.io'),
+    logger = require('./utils').logger,
+    exec = require('./utils').exec,
+    path = require('path'),
+    util = require('util'),
+    portChecker = require('tcp-port-used'),
+    EventEmitter = require('events').EventEmitter,
+    localtunnel = require('localtunnel');
+
+
+// how many ms without a pong packet to consider the connection closed
+var CONNECTION_HEARBEAT_PING_TIMEOUT = 60000,
+// how many ms before sending a new ping packet
+    CONNECTION_HEARBEAT_PING_INTERVAL = 25000;
+
+function LocalServer(port, externalServerUrl) {
+    this.port = port;
+    this.externalServerUrl = externalServerUrl;
+}
+
+util.inherits(LocalServer, EventEmitter);
+
+LocalServer.startServer = function(ports, externalServerUrl, useTunnel) {
+    logger.normal("local-server: scanning ports from " + ports.start + " to " + ports.end);
+
+    return LocalServer.getFirstAvailablePort(ports.start, ports.end)
+        .then(function(port) {
+            logger.normal("local-server: port " + port + " is available");
+            logger.info("local-server: starting local medic server");
+
+            var localServer = new LocalServer(port, externalServerUrl);
+            localServer.createSocketListener();
+
+            if (useTunnel) {
+                return localServer.createTunnel();
+            }
+
+            return localServer;
+        });
+};
+
+LocalServer.getFirstAvailablePort = function(startPort, endPort) {
+    return portChecker.check(startPort).then(function (isInUse) {
+        if (!isInUse) {
+            return startPort;
+        }
+        if (startPort < endPort) {
+            return LocalServer.getFirstAvailablePort(startPort + 1, endPort);
+        }
+        throw new Error('Unable to find available port');
+    });
+};
+
+LocalServer.prototype.createTunnel = function() {
+    logger.info('cordova-paramedic: attempt to create local tunnel');
+    var self = this;
+
+    return Q.Promise(function(resolve, reject) {
+
+        var tunnel = localtunnel(self.port, function(err, tunnel) {
+            if (err) {
+                reject('Unable to create local tunnel: ' + err);
+                return;
+            }
+
+            self.tunneledUrl = tunnel.url;
+            logger.info('cordova-paramedic: using tunneled url ' + self.tunneledUrl);
+
+            resolve(self);
+        });
+
+        // this trace is useful to debug test run timeout issue
+        tunnel.on('close', function() {
+             logger.normal('local-server: local tunnel has been closed');
+        });
+    });
+};
+
+LocalServer.prototype.createSocketListener = function() {
+    var listener = io.listen(this.port, {
+        pingTimeout: CONNECTION_HEARBEAT_PING_TIMEOUT,
+        pingInterval: CONNECTION_HEARBEAT_PING_INTERVAL
+    });
+
+    var self  = this;
+
+    listener.on('connection', function(socket) {
+        logger.info('local-server: new socket connection');
+        self.connection = socket;
+
+        // server methods 
+        ['deviceLog', 'disconnect', 'deviceInfo',
+        'jasmineStarted', 'specStarted', 'specDone',
+        'suiteStarted', 'suiteDone', 'jasmineDone'].forEach(function(route) {
+            socket.on(route, function(data) {
+                self.emit(route, data);
+            });
+        });
+    });
+};
+
+// Connection url could be platform specific so we pass platform as param here
+LocalServer.prototype.getConnectionUrl = function(platformId) {
+    // --useTunnel option
+    if (this.tunneledUrl) {
+        return this.tunneledUrl;
+    }
+    // --externalServerUrl option / we know ip or dns name
+    if (this.externalServerUrl) {
+        return this.externalServerUrl + ":" + this.port;
+    }
+    // build connection uri for localhost based on platform
+    var connectionUrl;
+
+    switch(platformId) {
+        case "android" :
+            connectionUrl = "http://10.0.2.2";
+            break;
+        case "ios"     :
+        case "browser" :
+        case "windows" :
+        /* falls through */
+        default:
+            connectionUrl = "http://127.0.0.1";
+    }
+
+    return connectionUrl + ":" + this.port;
+};
+
+LocalServer.prototype.isDeviceConnected = function() {
+    return !!this.connection;
+};
+
+module.exports = LocalServer;

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/lib/ParamedicConfig.js
----------------------------------------------------------------------
diff --git a/lib/ParamedicConfig.js b/lib/ParamedicConfig.js
new file mode 100644
index 0000000..11b5c0c
--- /dev/null
+++ b/lib/ParamedicConfig.js
@@ -0,0 +1,107 @@
+/**
+    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.
+*/
+
+var DEFAULT_START_PORT = 8008;
+var DEFAULT_END_PORT = 8018;
+var DEFAULT_TIMEOUT = 10 * 60 * 1000; // 10 minutes in msec - this will become a param
+
+function ParamedicConfig(json) {
+    this._config = json;
+}
+
+ParamedicConfig.parseFromArguments = function (argv) {
+    return new ParamedicConfig({
+        platform:          argv.platform,
+        action:            !!argv.justbuild ? 'build' : 'run',
+        args:              (!!argv.browserify ? '--browserify ' : '') + (!!argv.device ?
'--device' : ''),
+        plugins:           Array.isArray(argv.plugin) ? argv.plugin : [argv.plugin],
+        useTunnel:         !!argv.useTunnel,
+        verbose:           !!argv.verbose,
+        startPort:         argv.startport || argv.port,
+        endPort:           argv.endport || argv.port,
+        externalServerUrl: argv.externalServerUrl,
+        reportSavePath:    !!argv.reportSavePath? argv.reportSavePath: undefined,
+        cleanUpAfterRun:   !!argv.cleanUpAfterRun? true: false
+    });
+};
+
+ParamedicConfig.parseFromFile = function (paramedicConfigPath) {
+    return new ParamedicConfig(require(paramedicConfigPath));
+};
+
+ParamedicConfig.prototype.getUseTunnel = function () {
+    return this._config.useTunnel;
+};
+
+ParamedicConfig.prototype.getReportSavePath = function () {
+    return this._config.reportSavePath;
+};
+
+ParamedicConfig.prototype.getShouldCleanUpAfterRun = function () {
+    return this._config.cleanUpAfterRun;
+};
+
+ParamedicConfig.prototype.getPlatform = function() {
+    return this._config.platform;
+};
+
+ParamedicConfig.prototype.getAction = function() {
+    return this._config.action;
+};
+
+ParamedicConfig.prototype.getArgs = function() {
+    return this._config.args;
+};
+
+ParamedicConfig.prototype.getPlatformId = function() {
+    return this._config.platform.split("@")[0];
+};
+
+ParamedicConfig.prototype.getPlugins = function () {
+    return this._config.plugins;
+};
+
+ParamedicConfig.prototype.getExternalServerUrl= function () {
+    return this._config.externalServerUrl;
+};
+
+ParamedicConfig.prototype.isVerbose = function() {
+    return this._config.verbose;
+};
+
+ParamedicConfig.prototype.isJustBuild = function() {
+    return this._config.justbuild;
+};
+
+ParamedicConfig.prototype.isBrowserify = function() {
+    return this._config.browserify;
+};
+
+ParamedicConfig.prototype.getPorts = function() {
+    return {
+        start: this._config.startPort || DEFAULT_START_PORT,
+        end: this._config.endPort || DEFAULT_END_PORT
+    };
+};
+
+ParamedicConfig.prototype.getTimeout = function() {
+    return DEFAULT_TIMEOUT;
+};
+
+module.exports = ParamedicConfig;

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/lib/PluginsManager.js
----------------------------------------------------------------------
diff --git a/lib/PluginsManager.js b/lib/PluginsManager.js
new file mode 100644
index 0000000..b7d6a17
--- /dev/null
+++ b/lib/PluginsManager.js
@@ -0,0 +1,71 @@
+/**
+    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.
+*/
+
+var path = require('path');
+var fs = require('fs');
+var logger = require('./utils').logger;
+var exec = require('./utils').exec;
+var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
+
+function PluginsManager(appRoot, storedCWD) {
+    this.appRoot = appRoot;
+    this.storedCWD = storedCWD;
+}
+
+PluginsManager.prototype.installPlugins = function(plugins) {
+    for(var n = 0; n < plugins.length; n++) {
+        var plugin = plugins[n];
+        this.installSinglePlugin(plugin);
+    }
+};
+
+PluginsManager.prototype.installTestsForExistingPlugins = function() {
+    var installedPlugins = new PluginInfoProvider().getAllWithinSearchPath(path.join(this.appRoot,
'plugins'));
+    var me = this;
+    installedPlugins.forEach(function(plugin) {
+        // there is test plugin available
+        if (fs.existsSync(path.join(plugin.dir, 'tests', 'plugin.xml'))) {
+            me.installSinglePlugin(path.join(plugin.dir, 'tests'));
+        }
+    });
+    // this will list installed plugins and their versions
+    this.showPluginsVersions();
+};
+
+PluginsManager.prototype.installSinglePlugin = function(plugin) {
+    if (fs.existsSync(path.resolve(this.storedCWD, plugin))) {
+        plugin = path.resolve(this.storedCWD, plugin);
+    }
+
+    logger.normal("cordova-paramedic: installing " + plugin);
+    // var pluginPath = path.resolve(this.storedCWD, plugin);
+
+    var plugAddCmd = exec('cordova plugin add ' + plugin);
+    if(plugAddCmd.code !== 0) {
+        logger.error('Failed to install plugin : ' + plugin);
+        throw new Error('Failed to install plugin : ' + plugin);
+    }
+};
+
+PluginsManager.prototype.showPluginsVersions = function() {
+    logger.verbose("cordova-paramedic: versions of installed plugins: ");
+    exec('cordova plugins');
+};
+
+module.exports = PluginsManager;

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/lib/Reporters.js
----------------------------------------------------------------------
diff --git a/lib/Reporters.js b/lib/Reporters.js
new file mode 100644
index 0000000..9c012c8
--- /dev/null
+++ b/lib/Reporters.js
@@ -0,0 +1,31 @@
+/**
+    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.
+*/
+
+var JasmineSpecReporter = require('jasmine-spec-reporter'),
+    jasmineReporters    = require('jasmine-reporters');
+
+module.exports = function(reportSavePath) {
+    var reporters = [new JasmineSpecReporter({displayPendingSummary: false, displaySuiteNumber:
true})];
+
+    if (reportSavePath) {
+        reporters.push(new jasmineReporters.JUnitXmlReporter({savePath: reportSavePath, consolidateAll:
false}));
+    }
+
+    return reporters;
+};

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/lib/paramedic.js
----------------------------------------------------------------------
diff --git a/lib/paramedic.js b/lib/paramedic.js
new file mode 100644
index 0000000..be50f90
--- /dev/null
+++ b/lib/paramedic.js
@@ -0,0 +1,231 @@
+/**
+    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.
+*/
+
+var exec = require('./utils').exec,
+    shell = require('shelljs'),
+    Server = require('./LocalServer'),
+    Q = require('q'),
+    tmp = require('tmp'),
+    PluginsManager = require('./PluginsManager'),
+    path = require('path'),
+    Q = require('q'),
+    fs = require('fs'),
+    getReporters = require('./Reporters'),
+    logger = require('./utils').logger;
+
+// Time to wait for initial device connection.
+// If device has not connected within this interval the tests are stopped.
+var INITIAL_CONNECTION_TIMEOUT = 300000; // 5mins
+
+function ParamedicRunner(config, _callback) {
+    this.tempFolder = null;
+    this.pluginsManager = null;
+
+    this.config = config;
+
+    exec.setVerboseLevel(config.isVerbose());
+}
+
+ParamedicRunner.prototype.run = function() {
+    var self = this;
+
+    return Q().then(function() {
+        self.createTempProject();
+        self.prepareProjectToRunTests();
+        return Server.startServer(self.config.getPorts(), self.config.getExternalServerUrl(),
self.config.getUseTunnel());
+    })
+    .then(function(server) {
+        self.server = server;
+
+        self.injectReporters();
+        self.subcribeForEvents();
+
+        var connectionUrl = server.getConnectionUrl(self.config.getPlatformId());
+        self.writeMedicConnectionUrl(connectionUrl);
+
+        return self.runTests();
+    })
+    .fin(function() {
+        self.cleanUpProject();
+    });
+};
+
+ParamedicRunner.prototype.createTempProject = function() {
+    this.tempFolder = tmp.dirSync();
+    tmp.setGracefulCleanup();
+    logger.info("cordova-paramedic: creating temp project at " + this.tempFolder.name);
+    exec('cordova create ' + this.tempFolder.name);
+    shell.pushd(this.tempFolder.name);
+};
+
+ParamedicRunner.prototype.prepareProjectToRunTests = function() {
+    this.installPlugins();
+    this.setUpStartPage();
+    this.installPlatform();
+    this.checkPlatformRequirements();
+};
+
+ParamedicRunner.prototype.installPlugins = function() {
+    logger.info("cordova-paramedic: installing plugins");
+    this.pluginsManager = new PluginsManager(this.tempFolder.name, this.storedCWD);
+    this.pluginsManager.installPlugins(this.config.getPlugins());
+    this.pluginsManager.installTestsForExistingPlugins();
+    this.pluginsManager.installSinglePlugin('cordova-plugin-test-framework');
+    this.pluginsManager.installSinglePlugin('cordova-plugin-device');
+    this.pluginsManager.installSinglePlugin(path.join(__dirname, '../paramedic-plugin'));
+};
+
+ParamedicRunner.prototype.setUpStartPage = function() {
+    logger.normal("cordova-paramedic: setting app start page to test page");
+    shell.sed('-i', 'src="index.html"', 'src="cdvtests/index.html"', 'config.xml');
+};
+
+ParamedicRunner.prototype.installPlatform = function() {
+    logger.info("cordova-paramedic: adding platform : " + this.config.getPlatform());
+    exec('cordova platform add ' + this.config.getPlatform());
+};
+
+ParamedicRunner.prototype.checkPlatformRequirements = function() {
+    logger.normal("cordova-paramedic: checking requirements for platform " + this.config.getPlatformId());
+    var result = exec('cordova requirements ' + this.config.getPlatformId());
+
+    if (result.code !== 0) 
+        throw new Error('Platform requirements check has failed!');
+};
+
+ParamedicRunner.prototype.injectReporters = function() {
+    var self = this;
+    var reporters = getReporters(self.config.getReportSavePath());
+
+    ['jasmineStarted', 'specStarted', 'specDone',
+    'suiteStarted', 'suiteDone', 'jasmineDone'].forEach(function(route) {
+        reporters.forEach(function(reporter) {
+            if (reporter[route] instanceof Function)
+                self.server.on(route, reporter[route].bind(reporter));
+        });
+    });
+};
+
+ParamedicRunner.prototype.subcribeForEvents = function() {
+    this.server.on('deviceLog', function(data) {
+        logger.verbose('device|console.' + data.type + ': '  + data.msg[0]);
+    });
+
+    this.server.on('deviceInfo', function(data) {
+        logger.normal('cordova-paramedic: Device info: ' + JSON.stringify(data));
+    });
+};
+
+ParamedicRunner.prototype.writeMedicConnectionUrl = function(url) {
+    logger.normal("cordova-paramedic: writing medic log url to project " + url);
+    fs.writeFileSync(path.join("www","medic.json"), JSON.stringify({logurl:url}));
+};
+
+ParamedicRunner.prototype.runTests = function() {
+    var self = this;
+
+    return Q.promise(function(resolve, reject) {
+        self.server.on('jasmineDone', function(data) {
+            logger.info('cordova-paramedic: tests have been completed');
+
+            var isTestPassed = (data.specResults.specFailed === 0);
+
+            resolve(isTestPassed);
+        });
+
+        self.server.on('disconnect', function() {
+            reject(new Error('device is disconnected before passing the tests'));
+        });
+
+        var command = self.getCommandForStartingTests();
+        logger.normal('cordova-paramedic: running command ' + command);
+
+        exec(command, function(code, output) {
+            if(code) {
+                // this trace is automatically available in verbose mode
+                // so we check for this flag to not trace twice
+                if (!self.config.verbose) {
+                    logger.normal(output);
+                }
+                logger.normal('cordova-paramedic: unable to run tests; command log is available
above');
+                return reject(new Error(command + " returned error code " + code));
+            }
+
+            // skip tests if it was just build
+            if (!self.shouldWaitForTestResult()) {
+                return resolve(true);
+            }
+
+            // reject if device not connected in pending time
+            self.waitForConnection().catch(reject);
+        });
+    });
+};
+
+ParamedicRunner.prototype.getCommandForStartingTests = function() {
+    var cmd = "cordova " + this.config.getAction() + " " + this.config.getPlatformId();
+
+    if (this.config.getArgs()) {
+        cmd += " " + this.config.getArgs();
+    }
+
+    return cmd;
+};
+
+ParamedicRunner.prototype.shouldWaitForTestResult = function() {
+    var action = this.config.getAction();
+    return action === 'run' || action  === 'emulate';
+};
+
+ParamedicRunner.prototype.waitForConnection = function() {
+    var self = this;
+
+    var ERR_MSG = 'Seems like device not connected to local server in ' + INITIAL_CONNECTION_TIMEOUT
/ 1000 + ' secs';
+
+    return Q.promise(function(resolve, reject) {
+        setTimeout(function() {
+            if (!self.server.isDeviceConnected()) {
+                reject(new Error(ERR_MSG));
+            } else {
+                resolve();
+            }
+        }, INITIAL_CONNECTION_TIMEOUT);
+    });
+};
+
+ParamedicRunner.prototype.cleanUpProject = function() {
+    if(this.config.getShouldCleanUpAfterRun()) {
+        logger.info("cordova-paramedic: Deleting the application: " + this.tempFolder.name);
+        shell.popd();
+        shell.rm('-rf', this.tempFolder.name);
+    }
+};
+
+var storedCWD =  null;
+
+exports.run = function(paramedicConfig) {
+
+    storedCWD = storedCWD || process.cwd();
+
+    var runner = new ParamedicRunner(paramedicConfig, null);
+    runner.storedCWD = storedCWD;
+
+    return runner.run()
+    .timeout(paramedicConfig.getTimeout(), "This test seems to be blocked :: timeout exceeded.
Exiting ...");
+};

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/lib/utils/execWrapper.js
----------------------------------------------------------------------
diff --git a/lib/utils/execWrapper.js b/lib/utils/execWrapper.js
new file mode 100644
index 0000000..d1e012d
--- /dev/null
+++ b/lib/utils/execWrapper.js
@@ -0,0 +1,39 @@
+/**
+    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.
+*/
+
+var shelljs = require('shelljs');
+var verbose;
+
+function exec(cmd, onFinish, onData) {
+    if (onFinish instanceof Function || onFinish === null) {
+        var result = shelljs.exec(cmd, {async: true, silent: !verbose}, onFinish);
+
+        if (onData instanceof Function) {
+            result.stdout.on('data', onData);
+        }
+    } else {
+        return shelljs.exec(cmd, {silent: !verbose});
+    }
+}
+
+exec.setVerboseLevel = function(_verbose) {
+    verbose = _verbose;
+};
+
+module.exports = exec;

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/lib/utils/index.js
----------------------------------------------------------------------
diff --git a/lib/utils/index.js b/lib/utils/index.js
new file mode 100644
index 0000000..38ad5f4
--- /dev/null
+++ b/lib/utils/index.js
@@ -0,0 +1,23 @@
+/**
+    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.
+*/
+
+module.exports = {
+    exec: require('./execWrapper'),
+    logger: require('cordova-common').CordovaLogger.get()
+};

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/main.js
----------------------------------------------------------------------
diff --git a/main.js b/main.js
index b772665..db49a49 100755
--- a/main.js
+++ b/main.js
@@ -1,43 +1,52 @@
 #!/usr/bin/env node
 
 var parseArgs = require('minimist'),
-    paramedic = require('./paramedic');
-
-var plugins,
-    platformId;
+    path = require('path'),
+    paramedic = require('./lib/paramedic'),
+    ParamedicConfig = require('./lib/ParamedicConfig');
 
 var USAGE = "Error missing args. \n" +
-	"cordova-paramedic --platform PLATFORM --plugin PATH [--justbuild --timeout MSECS --port
PORTNUM --browserify]\n" +
-	"`PLATFORM` : the platform id, currently only supports 'ios'\n" +
-	"`PATH` : the relative or absolute path to a plugin folder\n" +
-					"\texpected to have a 'tests' folder.\n" +  
-					"\tYou may specify multiple --plugin flags and they will all\n" + 
-					"\tbe installed and tested together.\n" +
-	"`MSECS` : (optional) time in millisecs to wait for tests to pass|fail \n" +
-			  "\t(defaults to 10 minutes) \n" +
-	"`PORTNUM` : (optional) port to use for posting results from emulator back to paramedic
server\n" +
-	"--justbuild : (optional) just builds the project, without running the tests \n" +
+    "cordova-paramedic --platform PLATFORM --plugin PATH [--justbuild --timeout MSECS --startport
PORTNUM --endport PORTNUM --browserify]\n" +
+    "`PLATFORM` : the platform id. Currently supports 'ios', 'browser', 'windows', 'android',
'wp8'.\n" +
+                    "\tPath to platform can be specified as link to git repo like:\n" +
+                    "\twindows@https://github.com/apache/cordova-windows.git\n" +
+                    "\tor path to local copied git repo like:\n" +
+                    "\twindows@../cordova-windows/\n" +
+    "`PATH` : the relative or absolute path to a plugin folder\n" +
+                    "\texpected to have a 'tests' folder.\n" +
+                    "\tYou may specify multiple --plugin flags and they will all\n" +
+                    "\tbe installed and tested together.\n" +
+    "`MSECS` : (optional) time in millisecs to wait for tests to pass|fail \n" +
+              "\t(defaults to 10 minutes) \n" +
+    "`PORTNUM` : (optional) ports to find available and use for posting results from emulator
back to paramedic server(default is from 8008 to 8009)\n" +
+    "--justbuild : (optional) just builds the project, without running the tests \n" +
     "--browserify : (optional) plugins are browserified into cordova.js \n" +
     "--verbose : (optional) verbose mode. Display more information output\n" +
-    "--platformPath : (optional) path to install platform from, git or local file uri";
+    "--useTunnel : (optional) use tunneling instead of local address. default is false\n"
+
+    "--config : (optional) read configuration from paramedic configuration file\n" +
+    "--reportSavePath: (optional) path to save Junit results file\n" +
+    "--cleanUpAfterRun: (optional) cleans up the application after the run.";
 
 var argv = parseArgs(process.argv.slice(2));
+var pathToParamedicConfig = argv.config && path.resolve(argv.config);
 
-if(!argv.platform) {
-    console.log(USAGE);
-    process.exit(1);
-}
+if (pathToParamedicConfig || // --config
+    argv.platform && argv.plugin) { // or --platform and --plugin
 
-var onComplete = function(resCode,resObj,logStr) {
-	console.log("result code is : " + resCode);
-	if(resObj) {
-		console.log(JSON.stringify(resObj));
-	}
-	if(logStr) {
-		console.log(logStr);
-	}
-	process.exit(resCode);
-};
+    var paramedicConfig = pathToParamedicConfig ?
+        ParamedicConfig.parseFromFile(pathToParamedicConfig):
+        ParamedicConfig.parseFromArguments(argv);
 
-paramedic.run(argv.platform, argv.plugin, onComplete, argv.justbuild, argv.port, argv.timeout,
argv.browserify, false, argv.verbose, argv.platformPath);
+    paramedic.run(paramedicConfig)
+    .catch(function (error) {
+        console.error(error.message);
+        process.exit(1);
+    })
+    .done(function(isTestPassed) {
+        process.exit(isTestPassed ? 0 : 1);
+    });
 
+} else {
+    console.log(USAGE);
+    process.exit(1);
+}

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index 8eddb4f..011f5d1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,7 @@
 {
   "name": "cordova-paramedic",
   "version": "0.5.0",
+  "license": "Apache 2.0",
   "description": "Use medic to test a cordova plugin locally",
   "main": "paramedic.js",
   "bin": {
@@ -11,15 +12,14 @@
     "url": "git://github.com/apache/cordova-paramedic.git"
   },
   "scripts": {
-    "test":"npm run jshint & npm run test-ios",
-    "jshint":"node node_modules/jshint/bin/jshint *.js",
-    "test-appveyor":"npm run test-windows",
-    "test-travis":"npm run test-ios",
-    "test-android":"node main.js --platform android --plugin ./spec/testable-plugin/",
+    "test": "npm run jshint & npm run test-ios",
+    "jshint": "node node_modules/jshint/bin/jshint lib/",
+    "test-appveyor": "npm run test-windows",
+    "test-travis": "npm run test-ios",
+    "test-android": "node main.js --platform android --plugin ./spec/testable-plugin/",
     "test-ios": "node main.js --platform ios --plugin ./spec/testable-plugin/ --verbose",
-    "test-windows" : "node main.js --platform windows --plugin ./spec/testable-plugin/",
+    "test-windows": "node main.js --platform windows --plugin ./spec/testable-plugin/",
     "test-wp8": "node main.js --platform wp8 --plugin ./spec/testable-plugin/"
-
   },
   "keywords": [
     "cordova",
@@ -27,16 +27,22 @@
     "test"
   ],
   "author": "Jesse MacFadyen",
-  "license": "Apache 2.0",
   "dependencies": {
+    "ansi": "^0.3.1",
+    "cordova-common": "^1.1.0",
+    "jasmine-reporters": "^2.1.1",
+    "jasmine-spec-reporter": "^2.4.0",
     "localtunnel": "~1.5.0",
     "minimist": "~1.1.0",
+    "q": "^1.4.1",
     "request": "^2.53.0",
     "shelljs": "~0.3.0",
+    "socket.io": "^1.4.5",
+    "tcp-port-used": "^0.1.2",
     "tmp": "0.0.25"
   },
   "devDependencies": {
-        "jasmine-node": "~1",
-        "jshint": "^2.6.0"
+    "jasmine-node": "~1",
+    "jshint": "^2.6.0"
   }
 }

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/paramedic-plugin/JasmineParamedicProxy.js
----------------------------------------------------------------------
diff --git a/paramedic-plugin/JasmineParamedicProxy.js b/paramedic-plugin/JasmineParamedicProxy.js
new file mode 100644
index 0000000..a75135a
--- /dev/null
+++ b/paramedic-plugin/JasmineParamedicProxy.js
@@ -0,0 +1,86 @@
+/**
+    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.
+*/
+
+function JasmineParamedicProxy(socket) {
+    this.socket = socket;
+    this.specExecuted = 0;
+    this.specFailed = 0;
+}
+
+JasmineParamedicProxy.prototype.jasmineStarted = function (o) {
+    this.socket.emit('jasmineStarted', o);
+};
+
+JasmineParamedicProxy.prototype.specStarted = function (o) {
+    this.socket.emit('specStarted', o);
+};
+
+JasmineParamedicProxy.prototype.specDone = function (o) {
+    if (o.status !== 'disabled') {
+        this.specExecuted++;
+    }
+    if (o.status === 'failed') {
+        this.specFailed++;
+    }
+
+    this.socket.emit('specDone', o);
+};
+
+JasmineParamedicProxy.prototype.suiteStarted = function (o) {
+    this.socket.emit('suiteStarted', o);
+};
+
+JasmineParamedicProxy.prototype.suiteDone = function (o) {
+    this.socket.emit('suiteDone', o);
+};
+
+JasmineParamedicProxy.prototype.jasmineDone = function (o) {
+    var p = 'Desktop';
+    var devmodel='none';
+    var version = cordova.version;
+    if(typeof device != 'undefined') {
+        p = device.platform.toLowerCase();
+        devmodel=device.model || device.name;
+        version = device.version.toLowerCase();
+    }
+
+    o = o || {};
+
+    // include platform info
+    o.cordova = {
+        platform:(platformMap.hasOwnProperty(p) ? platformMap[p] : p),
+        version:version,
+        model:devmodel
+    }
+
+    // include common spec results
+    o.specResults = {
+        specExecuted : this.specExecuted,
+        specFailed   : this.specFailed
+    }
+
+    this.socket.emit('jasmineDone', o);
+};
+
+var platformMap = {
+    'ipod touch':'ios',
+    'iphone':'ios'
+};
+
+module.exports = JasmineParamedicProxy;

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/paramedic-plugin/paramedic.js
----------------------------------------------------------------------
diff --git a/paramedic-plugin/paramedic.js b/paramedic-plugin/paramedic.js
new file mode 100644
index 0000000..d2c6930
--- /dev/null
+++ b/paramedic-plugin/paramedic.js
@@ -0,0 +1,95 @@
+/**
+    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.
+*/
+
+var io = cordova.require('cordova-plugin-paramedic.socket.io');
+
+var PARAMEDIC_SERVER_DEFAULT_URL = 'http://127.0.0.1:8008';
+
+function Paramedic() {
+
+}
+
+Paramedic.prototype.initialize = function() {
+    var me = this;
+    var connectionUri = loadParamedicServerUrl();
+    this.socket = io.connect(connectionUri);
+
+    this.socket.on('connect', function () {
+        console.log('Paramedic has been susccessfully connected to server');
+        if (typeof device != 'undefined') me.socket.emit('deviceInfo', device);
+    });
+
+    this.overrideConsole();
+    this.injectJasmineReporter();
+};
+
+
+Paramedic.prototype.overrideConsole = function () {
+
+    var origConsole = window.console;
+    var me = this;
+
+    function createCustomLogger(type) {
+        return function () {
+            origConsole[type].apply(origConsole, arguments);
+
+            me.socket.emit('deviceLog', { type: type, msg: Array.prototype.slice.apply(arguments)
});
+        };
+    }
+    window.console = {
+        log: createCustomLogger('log'),
+        warn: createCustomLogger('warn'),
+        error: createCustomLogger('error'),
+    };
+    console.log('Paramedic console has been installed.');
+};
+
+Paramedic.prototype.injectJasmineReporter = function () {
+    var JasmineParamedicProxy = require('cordova-plugin-paramedic.JasmineParamedicProxy');
+    var jasmineProxy = new JasmineParamedicProxy(this.socket);
+    var testsModule = cordova.require("cordova-plugin-test-framework.cdvtests");
+    var defineAutoTestsOriginal = testsModule.defineAutoTests;
+
+    testsModule.defineAutoTests = function () {
+        defineAutoTestsOriginal();
+        jasmine.getEnv().addReporter(jasmineProxy);
+    };
+};
+
+new Paramedic().initialize();
+
+function loadParamedicServerUrl() {
+
+    try {
+        // attempt to synchronously load medic config
+        var xhr = new XMLHttpRequest();
+        xhr.open("GET", "../medic.json", false);
+        xhr.send(null);
+        var cfg = JSON.parse(xhr.responseText);
+
+        return cfg.logurl || PARAMEDIC_SERVER_DEFAULT_URL;
+
+    } catch (ex) {
+        console.log('Unable to load paramedic server url: ' + ex);
+    }
+
+    return PARAMEDIC_SERVER_DEFAULT_URL;
+}
+
+module.exports = Paramedic;

http://git-wip-us.apache.org/repos/asf/cordova-paramedic/blob/9655060c/paramedic-plugin/plugin.xml
----------------------------------------------------------------------
diff --git a/paramedic-plugin/plugin.xml b/paramedic-plugin/plugin.xml
new file mode 100644
index 0000000..af4d54a
--- /dev/null
+++ b/paramedic-plugin/plugin.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+           id="cordova-plugin-paramedic"
+      version="1.2.1-dev">
+
+    <name>Paramedic</name>
+    <description>Cordova Paramedic Plugin</description>
+    <license>Apache 2.0</license>
+
+    <js-module src="socket.io.js" name="socket.io" />
+
+    <js-module src="JasmineParamedicProxy.js" name="JasmineParamedicProxy" />
+
+    <js-module src="paramedic.js" name="paramedic">
+        <runs/>
+    </js-module>
+
+</plugin>


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


Mime
View raw message