Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds in-browser testing and Saucelabs CI #681

Merged
merged 12 commits into from
Dec 23, 2013
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ node_modules
*.sublime-project
*.sublime-workspace
npm-debug.log
sauce_connect.log*
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ dist/components/*
spec/*
src/*
tasks/*
tmp/*
publish/*
vendor/*
23 changes: 13 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
language: node_js
node_js:
- "0.8"
- "0.10"

before_install:
- npm install -g grunt-cli

script:
- grunt --stack default metrics publish:latest
- grunt --stack travis

email:
on_failure: change
on_success: never
env:
global:
- S3_BUCKET_NAME=builds.handlebarsjs.com
- secure: ! 'PJaukuvkBBsSDOqbIcNSSMgb96VVEaIt/eq9GPjXPeFbSd3hXgwhwVE62Lrq
- secure: PJaukuvkBBsSDOqbIcNSSMgb96VVEaIt/eq9GPjXPeFbSd3hXgwhwVE62LrqtJO8BaUfX+PzpiQjEl4D5/KBmvlFZ057Hqmy0zmPOT5mDZfJe8Ja5zyvTMb+KkCWN/tjAp8kawHojE04pn6jIpPdwXFnAYwPhaHbATFrmdt9fdg=
- secure: mBcGL2tnmiRujJdV/4fxrVd8E8wn6AW9IQKVcMv8tvOc7i5dOzZ39rpBKLuTMRXDtMV1LyLiuKYb1pHj1IyeadEahcLYFfGygF4LG7Yzp4NWHtRzQ7Q8LXaJV7dXDboYCFkn2a8/Rtx1YSVh/sCONf5UoRC+MUIqrj4UiHN9r3s=

tJO8BaUfX+PzpiQjEl4D5/KBmvlFZ057Hqmy0zmPOT5mDZfJe8Ja5zyvTMb+
matrix:
include:
- node_js: "0.10"
env:
- PUBLISH=true
- secure: pLTzghtVll9yGKJI0AaB0uI8GypfWxLTaIB0ZL8//yN3nAEIKMhf/RRilYTsn/rKj2NUa7vt2edYILi3lttOUlCBOwTc9amiRms1W8Lwr/3IdWPeBLvLuH1zNJRm2lBAwU4LBSqaOwhGaxOQr6KHTnWudhNhgOucxpZfvfI/dFw=
- secure: yERYCf7AwL11D9uMtacly/THGV8BlzsMmrt+iQVvGA3GaY6QMmfYqf6P6cCH98sH5etd1Y+1e6YrPeMjqI6lyRllT7FptoyOdHulazQe86VQN4sc0EpqMlH088kB7gGjTut9Z+X9ViooT5XEh9WA5jXEI9pXhQJNoIHkWPuwGuY=

KkCWN/tjAp8kawHojE04pn6jIpPdwXFnAYwPhaHbATFrmdt9fdg='
- secure: ! 'mBcGL2tnmiRujJdV/4fxrVd8E8wn6AW9IQKVcMv8tvOc7i5dOzZ39rpBKLuT
MRXDtMV1LyLiuKYb1pHj1IyeadEahcLYFfGygF4LG7Yzp4NWHtRzQ7Q8LXaJ
V7dXDboYCFkn2a8/Rtx1YSVh/sCONf5UoRC+MUIqrj4UiHN9r3s='
cache:
directories:
- node_modules
49 changes: 48 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module.exports = function(grunt) {
]
},

clean: ["dist", "lib/handlebars/compiler/parser.js"],
clean: ['tmp', 'dist', 'lib/handlebars/compiler/parser.js'],

copy: {
dist: {
Expand Down Expand Up @@ -110,6 +110,46 @@ module.exports = function(grunt) {
}
}]
}
},

concat: {
tests: {
src: ['spec/!(require).js'],
dest: 'tmp/tests.js'
}
},

connect: {
server: {
options: {
base: '.',
hostname: '*',
port: 9999
}
}
},
'saucelabs-mocha': {
all: {
options: {
build: process.env.TRAVIS_JOB_ID,
urls: ['http://localhost:9999/spec/?headless=true'],
detailedError: true,
concurrency: 2,
browsers: [
{browserName: 'chrome'},
{browserName: 'firefox'},
{browserName: 'firefox', version: '3.6'},
{browserName: 'safari', version: 7, platform: 'OS X 10.9'},
{browserName: 'safari', version: 6, platform: 'OS X 10.8'},
{browserName: 'opera'},
{browserName: 'internet explorer', version: 11, platform: 'Windows 8.1'},
{browserName: 'internet explorer', version: 10, platform: 'Windows 8'},
{browserName: 'internet explorer', version: 9, platform: 'Windows 7'},
{browserName: 'internet explorer', version: 8, platform: 'XP'},
{browserName: 'internet explorer', version: 7, platform: 'XP'}
]
}
}
}
});

Expand All @@ -124,20 +164,27 @@ module.exports = function(grunt) {
this.registerTask('amd', ['packager:amd', 'requirejs']);
this.registerTask('node', ['packager:cjs']);
this.registerTask('globals', ['packager:global']);
this.registerTask('tests', ['concat:tests']);

this.registerTask('release', 'Build final packages', ['amd', 'jshint', 'uglify', 'copy:dist', 'copy:components', 'copy:cdnjs']);

// Load tasks from npm
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-saucelabs');
grunt.loadNpmTasks('es6-module-packager');

grunt.task.loadTasks('tasks');

grunt.registerTask('bench', ['metrics']);
grunt.registerTask('sauce', process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : []);

grunt.registerTask('travis', process.env.PUBLISH ? ['default', 'sauce', 'metrics', 'publish:latest'] : ['default']);

grunt.registerTask('default', ['build', 'test', 'release']);
};
4 changes: 2 additions & 2 deletions README.markdown
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[![Build Status](https://travis-ci.org/wycats/handlebars.js.png?branch=master)](https://travis-ci.org/wycats/handlebars.js)

[![Travis Build Status](https://travis-ci.org/wycats/handlebars.js.png?branch=master)](https://travis-ci.org/wycats/handlebars.js)
[![Selenium Test Status](https://saucelabs.com/buildstatus/handlebars)](https://saucelabs.com/u/handlebars)

Handlebars.js
=============
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,19 @@
"grunt": "~0.4.1",
"grunt-cli": "~0.1.10",
"grunt-contrib-clean": "~0.4.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-connect": "~0.5.0",
"grunt-contrib-copy": "~0.4.1",
"grunt-contrib-jshint": "~0.7.2",
"grunt-contrib-requirejs": "~0.4.1",
"grunt-contrib-uglify": "~0.2.2",
"grunt-saucelabs": "~4.1.2",
"es6-module-packager": "0.x",
"jison": "~0.3.0",
"keen.io": "0.0.3",
"mocha": "*",
"mustache": "~0.7.2",
"semver": "~2.1.0",
"should": "~1.2.2",
"underscore": "~1.5.1"
},
"main": "lib/index.js",
Expand Down
9 changes: 5 additions & 4 deletions spec/basic.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/*global CompilerContext, Handlebars, beforeEach, shouldCompileTo */
global.handlebarsEnv = null;

beforeEach(function() {
Expand Down Expand Up @@ -160,9 +161,9 @@ describe("basic context", function() {

it("this keyword nested inside path", function() {
var string = "{{#hellos}}{{text/this/foo}}{{/hellos}}";
(function() {
shouldThrow(function() {
CompilerContext.compile(string);
}).should.throw(Error);
}, Error);
});

it("this keyword in helpers", function() {
Expand All @@ -181,8 +182,8 @@ describe("basic context", function() {

it("this keyword nested inside helpers param", function() {
var string = "{{#hellos}}{{foo text/this/foo}}{{/hellos}}";
(function() {
shouldThrow(function() {
CompilerContext.compile(string);
}).should.throw(Error);
}, Error);
});
});
4 changes: 2 additions & 2 deletions spec/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ describe('blocks', function() {
it("block with complex lookup using nested context", function() {
var string = "{{#goodbyes}}{{text}} cruel {{foo/../name}}! {{/goodbyes}}";

(function() {
shouldThrow(function() {
CompilerContext.compile(string);
}).should.throw(Error);
}, Error);
});

it("block with deep nested complex lookup", function() {
Expand Down
2 changes: 1 addition & 1 deletion spec/builtins.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe('builtin helpers', function() {
var expected1 = "<b>#1</b>. goodbye! 2. GOODBYE! cruel world!";
var expected2 = "2. GOODBYE! <b>#1</b>. goodbye! cruel world!";

(actual === expected1 || actual === expected2).should.equal(true, "each with object argument iterates over the contents when not empty");
equals(actual === expected1 || actual === expected2, true, "each with object argument iterates over the contents when not empty");
shouldCompileTo(string, {goodbyes: [], world: "world"}, "cruel world!",
"each with object argument ignores the contents when empty");
});
Expand Down
14 changes: 7 additions & 7 deletions spec/data.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*global CompilerContext */
/*global CompilerContext, Handlebars, handlebarsEnv, shouldThrow */
describe('data', function() {
it("passing in data to a compiled function that expects data - works with helpers", function() {
var template = CompilerContext.compile("{{hello}}", {data: true});
Expand Down Expand Up @@ -88,25 +88,25 @@ describe('data', function() {
it("parameter data throws when using this scope references", function() {
var string = "{{#goodbyes}}{{text}} cruel {{@./name}}! {{/goodbyes}}";

(function() {
shouldThrow(function() {
CompilerContext.compile(string);
}).should.throw(Error);
}, Error);
});

it("parameter data throws when using parent scope references", function() {
var string = "{{#goodbyes}}{{text}} cruel {{@../name}}! {{/goodbyes}}";

(function() {
shouldThrow(function() {
CompilerContext.compile(string);
}).should.throw(Error);
}, Error);
});

it("parameter data throws when using complex scope references", function() {
var string = "{{#goodbyes}}{{text}} cruel {{@foo/../name}}! {{/goodbyes}}";

(function() {
shouldThrow(function() {
CompilerContext.compile(string);
}).should.throw(Error);
}, Error);
});

it("data is inherited downstream", function() {
Expand Down
28 changes: 24 additions & 4 deletions spec/env/common.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
global.should = require('should');

global.shouldCompileTo = function(string, hashOrArray, expected, message) {
shouldCompileToWithPartials(string, hashOrArray, false, expected, message);
};

global.shouldCompileToWithPartials = function(string, hashOrArray, partials, expected, message) {
var result = compileWithPartials(string, hashOrArray, partials);
result.should.equal(expected, "'" + expected + "' should === '" + result + "': " + message);
if (result !== expected) {
throw new Error("'" + expected + "' should === '" + result + "': " + message);
}
};

global.compileWithPartials = function(string, hashOrArray, partials) {
Expand All @@ -24,5 +24,25 @@ global.compileWithPartials = function(string, hashOrArray, partials) {


global.equals = global.equal = function(a, b, msg) {
a.should.equal(b, msg || '');
if (a !== b) {
throw new Error("'" + b + "' should === '" + a + "'" + (msg ? ": " + msg : ''));
}
};

global.shouldThrow = function(callback, type, msg) {
var failed;
try {
callback();
failed = true;
} catch (err) {
if (type && !(err instanceof type)) {
throw new Error('Type failure');
}
if (msg && !(msg.test ? msg.test(err.message) : msg === err.message)) {
throw new Error('Message failure');
}
}
if (failed) {
throw new Error('It failed to throw');
}
};
20 changes: 10 additions & 10 deletions spec/helpers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*global CompilerContext, shouldCompileTo, shouldCompileToWithPartials */
/*global CompilerContext, Handlebars, shouldCompileTo, shouldCompileToWithPartials, shouldThrow, handlebarsEnv */
describe('helpers', function() {
it("helper with complex lookup$", function() {
var string = "{{#goodbyes}}{{{link ../prefix}}}{{/goodbyes}}";
Expand Down Expand Up @@ -212,10 +212,10 @@ describe('helpers', function() {
});

it("using a quote in the middle of a parameter raises an error", function() {
(function() {
var string = 'Message: {{hello wo"rld"}}';
var string = 'Message: {{hello wo"rld"}}';
shouldThrow(function() {
CompilerContext.compile(string);
}).should.throw(Error);
}, Error);
});

it("escaping a String is possible", function(){
Expand Down Expand Up @@ -351,10 +351,10 @@ describe('helpers', function() {

describe("helperMissing", function() {
it("if a context is not found, helperMissing is used", function() {
(function() {
shouldThrow(function() {
var template = CompilerContext.compile("{{hello}} {{link_to world}}");
template({});
}).should.throw(/Missing helper: 'link_to'/);
}, undefined, /Missing helper: 'link_to'/);
});

it("if a context is not found, custom helperMissing is used", function() {
Expand Down Expand Up @@ -417,9 +417,9 @@ describe('helpers', function() {
equal(result, "bar", "'bar' should === '" + result);
});
it("Unknown helper call in knownHelpers only mode should throw", function() {
(function() {
shouldThrow(function() {
CompilerContext.compile("{{typeof hello}}", {knownHelpersOnly: true});
}).should.throw(Error);
}, Error);
});
});

Expand Down Expand Up @@ -491,7 +491,7 @@ describe('helpers', function() {

cruel: function(world) {
return "cruel " + world.toUpperCase();
},
}
};

var context = {
Expand All @@ -513,7 +513,7 @@ describe('helpers', function() {

cruel: function(world) {
return "cruel " + world.toUpperCase();
},
}
};

var context = {
Expand Down
Loading