Skip to content

Commit

Permalink
Paramedic real time logging and other improvements
Browse files Browse the repository at this point in the history
github close #3
  • Loading branch information
sgrebnov committed Apr 12, 2016
1 parent 1458451 commit 9655060
Show file tree
Hide file tree
Showing 19 changed files with 1,107 additions and 362 deletions.
14 changes: 14 additions & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -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": {
}
}
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
142 changes: 128 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
```


3 changes: 0 additions & 3 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
154 changes: 154 additions & 0 deletions lib/LocalServer.js
Original file line number Diff line number Diff line change
@@ -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;
Loading

0 comments on commit 9655060

Please sign in to comment.