Permalink
Browse files

include preliminary support for grunt

  • Loading branch information...
1 parent 3e1fb71 commit bbddcda8f411eef3ba7b59ea295d65b03f96a3ae @tkellen committed Aug 14, 2012
View
@@ -3,14 +3,42 @@
This template is a starting point for developing modern javascript modules and libraries. Dependency management is handled by the [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) loader [RequireJS](https://github.com/jrburke/requirejs). Unit testing is implemented with the BDD framework [Jasmine](https://github.com/pivotal/jasmine). Compilation is handled with [r.js](https://github.com/jrburke/r.js) and [almond](https://github.com/jrburke/almond)--the result is a single file with no external dependencies that runs in Node or the browser (with AMD, or as an inline script).
-### How to build ([node.js](http://nodejs.org/) is required):
+### How to build with RequireJS directly ([node.js](http://nodejs.org/) is required):
```console
node vendor/r.js -o build.js
```
-This generates a minified/optimized file under build/app.js.
+
+### How to build and test using [grunt](https://github.com/cowboy/grunt) *new*
+
+First, install grunt and required tasks:
+```console
+npm install -g grunt
+npm install grunt-contrib
+npm install grunt-jasmine-task
+```
+
+Then, use grunt to run your tests in a headless browser, or kick off the RequireJS optimizer with the following commands:
+```console
+grunt test
+grunt requirejs
+```
+
+### Installing PhantomJS
+
+In order for the jasmine task to work properly, [PhantomJS](http://www.phantomjs.org/) must be installed. Unfortunately, PhantomJS cannot be installed automatically via npm or grunt, so you need to install it yourself. There are a number of ways to install PhantomJS.
+
+* [PhantomJS and Mac OS X](http://ariya.ofilabs.com/2012/02/phantomjs-and-mac-os-x.html)
+* [PhantomJS Installation](http://code.google.com/p/phantomjs/wiki/Installation) (PhantomJS wiki)
+
+Note that the `phantomjs` executable needs to be in the system `PATH` for grunt to see it (if you can run "phantomjs" at the command line, this task should work).
+
+* [How to set the path and environment variables in Windows](http://www.computerhope.com/issues/ch000549.htm)
+* [Where does $PATH get set in OS X 10.6 Snow Leopard?](http://superuser.com/questions/69130/where-does-path-get-set-in-os-x-10-6-snow-leopard)
+* [How do I change the PATH variable in Linux](https://www.google.com/search?q=How+do+I+change+the+PATH+variable+in+Linux)
## Thanks to
- @jrburke for the fantastic tools RequireJS/r.js & almond.
+- @cowboy for all of his hard work on Grunt.
- @pivotal for the intuitive testing framework Jasmine.
View
@@ -1,6 +1,6 @@
// see a complete list of options here:
// https://github.com/jrburke/r.js/blob/master/build/example.build.js
-({
+requirejs.config({
// all modules loaded are relative to this path
// e.g. require(["grid/core"]) would grab /lib/grid/core.js
baseUrl: "./lib",
@@ -48,5 +48,5 @@
stubModules: ["cs","coffee-script"],
// build file destination, relative to the build file itself
- out: "./build/skeleton.js"
+ out: "./dist/skeleton.js"
})
View
@@ -6,7 +6,7 @@
</head>
<body>
<script>
-require(['../build/skeleton'],function(skeleton){
+require(['../dist/skeleton'],function(skeleton){
console.log("Look, skeleton's feature is "+skeleton.feature());
});
</script>
View
@@ -2,7 +2,7 @@
<html>
<head>
<title>Demo</title>
- <script src="../build/skeleton.js"></script>
+ <script src="../dist/skeleton.js"></script>
</head>
<body>
Look, skeletons's feature is: <script>document.write(skeleton.feature())</script>
View
@@ -1,3 +1,3 @@
-skeleton = require('../build/skeleton');
+var skeleton = require('../dist/skeleton');
console.log("Look, skeletons's feature is: "+skeleton.feature());
@@ -336,7 +336,7 @@ define("../vendor/almond", function(){});
define('skeleton/core',[],function() {
var skeleton = {
- VERSION: '0.0.1'
+ VERSION: '0.1.5'
};
return skeleton;
Oops, something went wrong.
View
@@ -0,0 +1,36 @@
+module.exports = function(grunt) {
+
+ // Configure Grunt
+ grunt.initConfig({
+
+ requirejs: {
+ compile: {
+ options: {
+ mainConfigFile: "build.js"
+ }
+ }
+ },
+ // minify the optimized library file
+ min: {
+ "dist/skeleton.min.js": "dist/skeleton.js"
+ },
+ // kick off jasmine, showing results at the cli
+ jasmine: {
+ all: ['test/runner.html']
+ },
+ // run jasmine tests any time watched files change
+ watch: {
+ files: ['lib/**/*','test/spec/**/*'],
+ tasks: ['jasmine']
+ }
+ });
+
+ // Load external tasks
+ grunt.loadNpmTasks('grunt-contrib');
+ grunt.loadNpmTasks('grunt-jasmine-task');
+
+ // Make task shortcuts
+ grunt.registerTask('default', 'jasmine requirejs min');
+ grunt.registerTask('test', 'jasmine');
+
+};
@@ -1,6 +1,6 @@
define(function() {
var skeleton = {
- VERSION: '0.0.1'
+ VERSION: '0.1.5'
};
return skeleton;
View
@@ -1,7 +1,7 @@
{
"name": "requirejs-library-skeleton",
"description": "RequireJS skeleton for modern JS libraries.",
- "version": "0.1.0",
+ "version": "0.1.5",
"homepage": "http://github.com/tkellen/requirejs-library-skeleton",
"author": "Tyler Kellen",
"licenses": [
@@ -16,7 +16,7 @@
},
"main": "build/skeleton.js",
"engines": {
- "node": ">=0.4.2"
+ "node": ">=0.6.0"
},
"keywords": [
"requirejs",
@@ -26,11 +26,11 @@
"dependencies": {
},
"scripts": {
- "test": "phantomjs test/runner-phantom.js http://localhost:8000/test/runner.html"
+ "test": "grunt test"
},
"devDependencies": {
- "system": "*",
- "requirejs": "*",
- "servedir": "*"
+ "grunt": "~3.0.10",
+ "grunt-contrib": "*",
+ "grunt-jasmine-task": "*"
}
}
@@ -1,79 +0,0 @@
-var system = require('system');
-
-/**
- * Wait until the test condition is true or a timeout occurs. Useful for waiting
- * on a server response or for a ui change (fadeIn, etc.) to occur.
- *
- * @param testFx javascript condition that evaluates to a boolean,
- * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
- * as a callback function.
- * @param onReady what to do when testFx condition is fulfilled,
- * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
- * as a callback function.
- * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
- */
-function waitFor(testFx, onReady, timeOutMillis) {
- var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s
- start = new Date().getTime(),
- condition = false,
- interval = setInterval(function() {
- if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
- // If not time-out yet and condition not yet fulfilled
- condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
- } else {
- if(!condition) {
- // If condition still not fulfilled (timeout but condition is 'false')
- console.log("'waitFor()' timeout");
- phantom.exit(1);
- } else {
- // Condition fulfilled (timeout and/or condition is 'true')
- console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
- typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
- clearInterval(interval); //< Stop this interval
- }
- }
- }, 100); //< repeat check every 100ms
-};
-
-
-if (system.args.length !== 2) {
- console.log('Usage: runner-phantom.js URL');
- phantom.exit();
-}
-
-var page = require('webpage').create();
-
-// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
-page.onConsoleMessage = function(msg) {
- console.log(msg);
-};
-
-page.open(system.args[1], function(status){
- if (status !== "success") {
- console.log("Unable to access network");
- phantom.exit();
- } else {
- waitFor(function(){
- return page.evaluate(function(){
- if (document.body.querySelector('.runner .description')) {
- return true;
- }
- return false;
- });
- }, function(){
- page.evaluate(function(){
- console.log(document.body.querySelector('.description').innerText);
- list = document.body.querySelectorAll('div.jasmine_reporter > div.suite.failed');
- for (i = 0; i < list.length; ++i) {
- el = list[i];
- desc = el.querySelectorAll('.description');
- console.log('');
- for (j = 0; j < desc.length; ++j) {
- console.log(desc[j].innerText);
- }
- }
- });
- phantom.exit();
- });
- }
-});
View
@@ -2,9 +2,10 @@
<html>
<head>
<title>Test Runner</title>
- <link rel="stylesheet" type="text/css" href="../vendor/jasmine-1.2.0/jasmine.css">
- <script src="../vendor/jasmine-1.2.0/jasmine.js"></script>
- <script src="../vendor/jasmine-1.2.0/jasmine-html.js"></script>
+ <link rel="stylesheet" type="text/css" href="../vendor/jasmine/jasmine.css">
+ <script src="../vendor/jasmine/jasmine.js"></script>
+ <script src="../vendor/jasmine/jasmine-html.js"></script>
+ <script src="../vendor/jasmine/jasmine-grunt.js"></script>
<!--
default path for modules beginning with 'app' before loading requireJS
File renamed without changes.
@@ -0,0 +1,54 @@
+/*
+ * Is injected into the spec runner file
+
+ * Copyright (c) 2012 Camille Reynders
+ * Copyright (c) 2012 "Cowboy" Ben Alman
+ * Licensed under the MIT license.
+ * http://benalman.com/about/license/
+ */
+
+/*global jasmine:true, alert:true*/
+
+// Send messages to the parent phantom.js process via alert! Good times!!
+function sendMessage(){
+ var args = [].slice.call( arguments );
+ alert( JSON.stringify( args ) );
+}
+
+var GruntReporter = function(){
+ this._started = this._getTime();
+};
+GruntReporter.prototype = {
+ _getTime : function(){
+ return new Date().getTime();
+ },
+ /**
+ * @param {jasmine.Suite} suite
+ */
+ _getSuitesToRoot : function( suite ){
+ var result = [];
+ do{
+ result.unshift( suite.description );
+ suite = suite.parentSuite;
+ }while( suite );
+ return result;
+ },
+ /**
+ * @param {jasmine.Suite} suite
+ */
+ reportRunnerResults : function( runner ){
+ var elapsed = this._getTime() - this._started;
+ sendMessage( 'done', elapsed );
+ },
+ /**
+ *
+ * @param {jasmine.Spec} spec
+ */
+ reportSpecResults : function( spec ){
+ var results = spec.results();
+ var suites = this._getSuitesToRoot( spec.suite );
+ sendMessage( 'testDone', suites.join( ' ' ), spec.description, results.totalCount, results.passedCount, results.failedCount, results.skipped );
+ }
+};
+
+jasmine.getEnv().addReporter( new GruntReporter() );
File renamed without changes.
File renamed without changes.
@@ -1,52 +0,0 @@
-/*
-Thanks to @geddesign (https://github.com/geddesign) for this awesome jasmine/console hack.
-https://github.com/geddesign/amd-testing
-*/
-
-(function(){
-
- var jasmine = require('./jasmine-1.2.0/jasmine').jasmine;
-
- function red(s) { return ["\033[31m", s, "\033[0m"].join(''); }
- function green(s) { return ["\033[32m", s, "\033[0m"].join(''); }
- function cyan(s) { return ["\033[36m", s, "\033[0m"].join(''); }
- function yellow(s) { return ["\033[33m", s, "\033[0m"].join(''); }
- function blue(s) { return ["\033[34m", s, "\033[0m"].join(''); }
- function jasmine_console(){}
- jasmine_console.prototype.reportRunnerResults = function(runner) {
- var output = [],
- results = runner.results(),
- specs = runner.specs();
- var msg = [specs.length, 'specs,', results.failedCount, 'failures.'].join(' ');
- if(results.failedCount > 0) {
- msg = red(msg);
- } else {
- msg = green(msg);
- }
- output.push(msg);
-
- for(var i = 0; i < specs.length; i++) {
- var spec = specs[i];
- results = spec.results();
- if(results.failedCount > 0) {
- var items = results.getItems();
- var numItems = items.length;
-
- for(var j = 0; j < numItems; j++) {
- var result = items[j];
- if(result.type == 'log') {
- output.push(' LOG: ' + result.toString());
- }
- else
- if(result.type == 'expect' && result.passed && !result.passed()) {
- output.push(spec.getFullName());
- output.push(' ' + red(result.message));
- }
- }
- }
- }
- console.log(output.join('\n'));
- };
-
- exports.jasmine_console = jasmine_console;
-}());

0 comments on commit bbddcda

Please sign in to comment.