From 836aefc6c3ee39b7bb6ee6abfc996643284bf175 Mon Sep 17 00:00:00 2001 From: Jeff French Date: Wed, 20 Nov 2013 15:22:08 -0600 Subject: [PATCH] Initial commit --- .gitignore | 4 ++ .jshintrc | 13 ++++++ Gruntfile.js | 64 ++++++++++++++++++++++++++++ LICENSE-MIT | 22 ++++++++++ README.md | 86 ++++++++++++++++++++++++++++++++++++++ package.json | 47 +++++++++++++++++++++ tasks/ripple.js | 49 ++++++++++++++++++++++ test/fixtures/testing.html | 1 + test/lib/get.js | 21 ++++++++++ test/ripple_test.js | 35 ++++++++++++++++ 10 files changed, 342 insertions(+) create mode 100644 .gitignore create mode 100644 .jshintrc create mode 100644 Gruntfile.js create mode 100644 LICENSE-MIT create mode 100644 README.md create mode 100644 package.json create mode 100644 tasks/ripple.js create mode 100644 test/fixtures/testing.html create mode 100644 test/lib/get.js create mode 100644 test/ripple_test.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9a1b41a --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules +npm-debug.log +tmp +.idea diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..f57a8ff --- /dev/null +++ b/.jshintrc @@ -0,0 +1,13 @@ +{ + "curly": true, + "eqeqeq": true, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "sub": true, + "undef": true, + "boss": true, + "eqnull": true, + "node": true +} diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..06aab97 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,64 @@ +/* + * grunt-ripple-emulator + * https://github.com/jeff-french/grunt-ripple-emulator + * + * Copyright (c) 2013 Jeff French + * Licensed under the MIT license. + */ + +'use strict'; + +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + jshint: { + all: [ + 'Gruntfile.js', + 'tasks/*.js', + '<%= nodeunit.tests %>' + ], + options: { + jshintrc: '.jshintrc' + } + }, + + // Before generating any new files, remove any previously-created files. + clean: { + tests: ['tmp'] + }, + + // Configuration to be run (and then tested). + ripple: { + test: { + options: { + path: 'test/fixtures', + open: false, + keepAlive: false + } + } + }, + + // Unit tests. + nodeunit: { + tests: ['test/*_test.js'] + } + + }); + + // Actually load this plugin's task(s). + grunt.loadTasks('tasks'); + + // These plugins provide necessary tasks. + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-nodeunit'); + + // Whenever the "test" task is run, first clean the "tmp" dir, then run this + // plugin's task(s), then test the result. + grunt.registerTask('test', ['clean', 'ripple', 'nodeunit']); + + // By default, lint and run all tests. + grunt.registerTask('default', ['jshint', 'test']); + +}; diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..00b4dfe --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2013 Jeff French + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..071a522 --- /dev/null +++ b/README.md @@ -0,0 +1,86 @@ +# grunt-ripple-emulator + +> Grunt task for the ripple emulator for Cordova/PhoneGap projects. + +## Getting Started +This plugin requires Grunt `~0.4.0` + +If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command: + +```shell +npm install grunt-ripple-emulator --save-dev +``` + +Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript: + +```js +grunt.loadNpmTasks('grunt-ripple-emulator'); +``` + +## The "ripple_emulator" task + +### Overview +In your project's Gruntfile, add a section named `ripple` to the data object passed into `grunt.initConfig()`. + +```js +grunt.initConfig({ + ripple: { + options: { + // Task-specific options go here. + }, + your_target: { + // Target-specific file lists and/or options go here. + }, + }, +}) +``` + +### Options + +#### options.path +Type: `String` +Default value: `'www'` + +Path to your your Cordova / PhoneGap's main `www` directory (relative to your Gruntfile). + +#### options.port +Type: `Integer` +Default value: `4400` + +Port that ripple will server your application on. + +#### options.open +Type: `Boolean` +Default value: `true` + +If `true` opens your app in the browser with ripple enabled. + +#### options.keepAlive +Type: `Boolean` +Default value: `false` + +If `true` the task will keep running (keep your ripple server running). + +**NOTE** If you are using [grunt-contrib-watch](https://github.com/gruntjs/grunt-contrib-watch) (or something similar) then you'll want to set `keepAlive: false`. + +### Usage Examples + +Serve the application from `dist` folder on port `9005` and keep the ripple server running. + +```js +grunt.initConfig({ + ripple: { + options: { + path: 'dist', + port: '9005', + keepAlive: true + } + }, +}) +``` + +## Contributing +In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/). + +## Release History +[v0.1.0](https://github.com/jeff-french/grunt-ripple-emulator/releases/tag/v0.1.0) - Initial release diff --git a/package.json b/package.json new file mode 100644 index 0000000..600c426 --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "grunt-ripple-emulator", + "description": "Grunt task for the ripple emulator for Cordova/PhoneGap projects.", + "version": "0.1.0", + "homepage": "https://github.com/jeff-french/grunt-ripple-emulator", + "author": { + "name": "Jeff French", + "email": "jeff.french@moonswitch.com", + "url": "http://geekindulgence.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/jeff-french/grunt-ripple-emulator.git" + }, + "bugs": { + "url": "https://github.com/jeff-french/grunt-ripple-emulator/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/jeff-french/grunt-ripple-emulator/blob/master/LICENSE-MIT" + } + ], + "main": "Gruntfile.js", + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "grunt test" + }, + "devDependencies": { + "grunt-contrib-jshint": "~0.6.0", + "grunt-contrib-clean": "~0.4.0", + "grunt-contrib-nodeunit": "~0.2.0", + "grunt": "~0.4.1" + }, + "peerDependencies": { + "grunt": "~0.4.0" + }, + "keywords": [ + "gruntplugin" + ], + "dependencies": { + "ripple-emulator": "~0.9.19", + "open": "0.0.4" + } +} diff --git a/tasks/ripple.js b/tasks/ripple.js new file mode 100644 index 0000000..6e8f24e --- /dev/null +++ b/tasks/ripple.js @@ -0,0 +1,49 @@ +/* + * grunt-ripple-emulator + * https://github.com/jeff-french/grunt-ripple-emulator + * + * Copyright (c) 2013 Jeff French + * Licensed under the MIT license. + */ + +'use strict'; +var ripple = require('ripple-emulator'), + path = require('path'), + open = require('open'); + +module.exports = function(grunt) { + + // Please see the Grunt documentation for more information regarding task + // creation: http://gruntjs.com/creating-tasks + + grunt.registerMultiTask('ripple', 'Grunt task for the ripple emulator for Cordova/PhoneGap projects.', function() { + // Merge task-specific and/or target-specific options with these defaults. + var options = this.options({ + path: 'www', + keepAlive: false, + open: true, + port: 4400 + }); + + var paths = []; + paths.push(options.path); + delete options.path; + options.path = paths; + + var done = this.async(); + + ripple.emulate.start(options); + + if(options.open){ + open('http://localhost:' + options.port + '?enableripple=cordova-3.0.0'); + } + + if(!options.keepAlive){ + done(); + } else { + grunt.log.writeln('Waiting...'); + grunt.log.writeln('(Press Ctrl+C to exit)'); + } + }); + +}; diff --git a/test/fixtures/testing.html b/test/fixtures/testing.html new file mode 100644 index 0000000..0a90125 --- /dev/null +++ b/test/fixtures/testing.html @@ -0,0 +1 @@ +Testing \ No newline at end of file diff --git a/test/lib/get.js b/test/lib/get.js new file mode 100644 index 0000000..c69441c --- /dev/null +++ b/test/lib/get.js @@ -0,0 +1,21 @@ +'use strict'; + +var http = require('http'); + +module.exports = function get(url, callback, error) { + var req = http.get(url, function(res) { + var body = ''; + + res.on('data', function(chunk) { + body += chunk; + }).on('end', function() { + callback(res, body); + }); + }); + + if (error) { + req.on('error', error) + }; + + req.end(); +} \ No newline at end of file diff --git a/test/ripple_test.js b/test/ripple_test.js new file mode 100644 index 0000000..fec4040 --- /dev/null +++ b/test/ripple_test.js @@ -0,0 +1,35 @@ +'use strict'; + +var get = require('./lib/get'); + +exports.ripple = { + serves_static_file_from_custom_dir: function(test) { + test.expect(2); + + get('http://localhost:4400/testing.html', function(res, body){ + test.equal(res.statusCode, 200, 'should return 200'); + test.equal(body, 'Testing', 'should return static page'); + test.done(); + }, function(err){ + test.done(); + }); + }, + start_xhr_proxy_server: function(test){ + test.expect(2); + + get('http://localhost:4400/ripple/xhr_proxy', function(res, body){ + test.equal(res.statusCode, 200, 'should return 200'); + test.equal(body, 'You shall not pass!'); + test.done(); + }); + }, + start_jsonp_xhr_proxy_server: function(test){ + test.expect(2); + + get('http://localhost:4400/ripple/jsonp_xhr_proxy', function(res, body){ + test.equal(res.statusCode, 200, 'should return 200'); + test.equal(body, 'You shall not pass!'); + test.done(); + }); + } +};