408 lines
12 KiB
JavaScript
408 lines
12 KiB
JavaScript
/* eslint-disable no-console */
|
|
describe('precompiler', function() {
|
|
// NOP Under non-node environments
|
|
if (typeof process === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
var Handlebars = require('../lib'),
|
|
Precompiler = require('../dist/cjs/precompiler'),
|
|
fs = require('fs'),
|
|
uglify = require('uglify-js');
|
|
|
|
var log,
|
|
logFunction,
|
|
errorLog,
|
|
errorLogFunction,
|
|
precompile,
|
|
minify,
|
|
emptyTemplate = {
|
|
path: __dirname + '/artifacts/empty.handlebars',
|
|
name: 'empty',
|
|
source: ''
|
|
},
|
|
file,
|
|
content,
|
|
writeFileSync;
|
|
|
|
/**
|
|
* Mock the Module.prototype.require-function such that an error is thrown, when "uglify-js" is loaded.
|
|
*
|
|
* The function cleans up its mess when "callback" is finished
|
|
*
|
|
* @param {Error} loadError the error that should be thrown if uglify is loaded
|
|
* @param {function} callback a callback-function to run when the mock is active.
|
|
*/
|
|
function mockRequireUglify(loadError, callback) {
|
|
var Module = require('module');
|
|
var _resolveFilename = Module._resolveFilename;
|
|
delete require.cache[require.resolve('uglify-js')];
|
|
delete require.cache[require.resolve('../dist/cjs/precompiler')];
|
|
Module._resolveFilename = function(request, mod) {
|
|
if (request === 'uglify-js') {
|
|
throw loadError;
|
|
}
|
|
return _resolveFilename.call(this, request, mod);
|
|
};
|
|
try {
|
|
callback();
|
|
} finally {
|
|
Module._resolveFilename = _resolveFilename;
|
|
delete require.cache[require.resolve('uglify-js')];
|
|
delete require.cache[require.resolve('../dist/cjs/precompiler')];
|
|
}
|
|
}
|
|
|
|
beforeEach(function() {
|
|
precompile = Handlebars.precompile;
|
|
minify = uglify.minify;
|
|
writeFileSync = fs.writeFileSync;
|
|
|
|
// Mock stdout and stderr
|
|
logFunction = console.log;
|
|
log = '';
|
|
console.log = function() {
|
|
log += Array.prototype.join.call(arguments, '');
|
|
};
|
|
errorLogFunction = console.error;
|
|
errorLog = '';
|
|
console.error = function() {
|
|
errorLog += Array.prototype.join.call(arguments, '');
|
|
};
|
|
|
|
fs.writeFileSync = function(_file, _content) {
|
|
file = _file;
|
|
content = _content;
|
|
};
|
|
});
|
|
afterEach(function() {
|
|
Handlebars.precompile = precompile;
|
|
uglify.minify = minify;
|
|
fs.writeFileSync = writeFileSync;
|
|
console.log = logFunction;
|
|
console.error = errorLogFunction;
|
|
});
|
|
|
|
it('should output version', function() {
|
|
Precompiler.cli({ templates: [], version: true });
|
|
equals(log, Handlebars.VERSION);
|
|
});
|
|
it('should throw if lacking templates', function() {
|
|
shouldThrow(
|
|
function() {
|
|
Precompiler.cli({ templates: [] });
|
|
},
|
|
Handlebars.Exception,
|
|
'Must define at least one template or directory.'
|
|
);
|
|
});
|
|
it('should handle empty/filtered directories', function() {
|
|
Precompiler.cli({ hasDirectory: true, templates: [] });
|
|
// Success is not throwing
|
|
});
|
|
it('should throw when combining simple and minimized', function() {
|
|
shouldThrow(
|
|
function() {
|
|
Precompiler.cli({ templates: [__dirname], simple: true, min: true });
|
|
},
|
|
Handlebars.Exception,
|
|
'Unable to minimize simple output'
|
|
);
|
|
});
|
|
it('should throw when combining simple and multiple templates', function() {
|
|
shouldThrow(
|
|
function() {
|
|
Precompiler.cli({
|
|
templates: [
|
|
__dirname + '/artifacts/empty.handlebars',
|
|
__dirname + '/artifacts/empty.handlebars'
|
|
],
|
|
simple: true
|
|
});
|
|
},
|
|
Handlebars.Exception,
|
|
'Unable to output multiple templates in simple mode'
|
|
);
|
|
});
|
|
it('should throw when missing name', function() {
|
|
shouldThrow(
|
|
function() {
|
|
Precompiler.cli({ templates: [{ source: '' }], amd: true });
|
|
},
|
|
Handlebars.Exception,
|
|
'Name missing for template'
|
|
);
|
|
});
|
|
it('should throw when combining simple and directories', function() {
|
|
shouldThrow(
|
|
function() {
|
|
Precompiler.cli({ hasDirectory: true, templates: [1], simple: true });
|
|
},
|
|
Handlebars.Exception,
|
|
'Unable to output multiple templates in simple mode'
|
|
);
|
|
});
|
|
|
|
it('should output simple templates', function() {
|
|
Handlebars.precompile = function() {
|
|
return 'simple';
|
|
};
|
|
Precompiler.cli({ templates: [emptyTemplate], simple: true });
|
|
equal(log, 'simple\n');
|
|
});
|
|
it('should default to simple templates', function() {
|
|
Handlebars.precompile = function() {
|
|
return 'simple';
|
|
};
|
|
Precompiler.cli({ templates: [{ source: '' }] });
|
|
equal(log, 'simple\n');
|
|
});
|
|
it('should output amd templates', function() {
|
|
Handlebars.precompile = function() {
|
|
return 'amd';
|
|
};
|
|
Precompiler.cli({ templates: [emptyTemplate], amd: true });
|
|
equal(/template\(amd\)/.test(log), true);
|
|
});
|
|
it('should output multiple amd', function() {
|
|
Handlebars.precompile = function() {
|
|
return 'amd';
|
|
};
|
|
Precompiler.cli({
|
|
templates: [emptyTemplate, emptyTemplate],
|
|
amd: true,
|
|
namespace: 'foo'
|
|
});
|
|
equal(/templates = foo = foo \|\|/.test(log), true);
|
|
equal(/return templates/.test(log), true);
|
|
equal(/template\(amd\)/.test(log), true);
|
|
});
|
|
it('should output amd partials', function() {
|
|
Handlebars.precompile = function() {
|
|
return 'amd';
|
|
};
|
|
Precompiler.cli({ templates: [emptyTemplate], amd: true, partial: true });
|
|
equal(/return Handlebars\.partials\['empty'\]/.test(log), true);
|
|
equal(/template\(amd\)/.test(log), true);
|
|
});
|
|
it('should output multiple amd partials', function() {
|
|
Handlebars.precompile = function() {
|
|
return 'amd';
|
|
};
|
|
Precompiler.cli({
|
|
templates: [emptyTemplate, emptyTemplate],
|
|
amd: true,
|
|
partial: true
|
|
});
|
|
equal(/return Handlebars\.partials\[/.test(log), false);
|
|
equal(/template\(amd\)/.test(log), true);
|
|
});
|
|
it('should output commonjs templates', function() {
|
|
Handlebars.precompile = function() {
|
|
return 'commonjs';
|
|
};
|
|
Precompiler.cli({ templates: [emptyTemplate], commonjs: true });
|
|
equal(/template\(commonjs\)/.test(log), true);
|
|
});
|
|
|
|
it('should set data flag', function() {
|
|
Handlebars.precompile = function(data, options) {
|
|
equal(options.data, true);
|
|
return 'simple';
|
|
};
|
|
Precompiler.cli({ templates: [emptyTemplate], simple: true, data: true });
|
|
equal(log, 'simple\n');
|
|
});
|
|
|
|
it('should set known helpers', function() {
|
|
Handlebars.precompile = function(data, options) {
|
|
equal(options.knownHelpers.foo, true);
|
|
return 'simple';
|
|
};
|
|
Precompiler.cli({ templates: [emptyTemplate], simple: true, known: 'foo' });
|
|
equal(log, 'simple\n');
|
|
});
|
|
it('should output to file system', function() {
|
|
Handlebars.precompile = function() {
|
|
return 'simple';
|
|
};
|
|
Precompiler.cli({
|
|
templates: [emptyTemplate],
|
|
simple: true,
|
|
output: 'file!'
|
|
});
|
|
equal(file, 'file!');
|
|
equal(content, 'simple\n');
|
|
equal(log, '');
|
|
});
|
|
|
|
it('should output minimized templates', function() {
|
|
Handlebars.precompile = function() {
|
|
return 'amd';
|
|
};
|
|
uglify.minify = function() {
|
|
return { code: 'min' };
|
|
};
|
|
Precompiler.cli({ templates: [emptyTemplate], min: true });
|
|
equal(log, 'min');
|
|
});
|
|
|
|
it('should omit minimization gracefully, if uglify-js is missing', function() {
|
|
var error = new Error("Cannot find module 'uglify-js'");
|
|
error.code = 'MODULE_NOT_FOUND';
|
|
mockRequireUglify(error, function() {
|
|
var Precompiler = require('../dist/cjs/precompiler');
|
|
Handlebars.precompile = function() {
|
|
return 'amd';
|
|
};
|
|
Precompiler.cli({ templates: [emptyTemplate], min: true });
|
|
equal(/template\(amd\)/.test(log), true);
|
|
equal(/\n/.test(log), true);
|
|
equal(/Code minimization is disabled/.test(errorLog), true);
|
|
});
|
|
});
|
|
|
|
it('should fail on errors (other than missing module) while loading uglify-js', function() {
|
|
mockRequireUglify(new Error('Mock Error'), function() {
|
|
shouldThrow(
|
|
function() {
|
|
var Precompiler = require('../dist/cjs/precompiler');
|
|
Handlebars.precompile = function() {
|
|
return 'amd';
|
|
};
|
|
Precompiler.cli({ templates: [emptyTemplate], min: true });
|
|
},
|
|
Error,
|
|
'Mock Error'
|
|
);
|
|
});
|
|
});
|
|
|
|
it('should output map', function() {
|
|
Precompiler.cli({ templates: [emptyTemplate], map: 'foo.js.map' });
|
|
|
|
equal(file, 'foo.js.map');
|
|
equal(log.match(/sourceMappingURL=/g).length, 1);
|
|
});
|
|
|
|
it('should output map', function() {
|
|
Precompiler.cli({
|
|
templates: [emptyTemplate],
|
|
min: true,
|
|
map: 'foo.js.map'
|
|
});
|
|
|
|
equal(file, 'foo.js.map');
|
|
equal(log.match(/sourceMappingURL=/g).length, 1);
|
|
});
|
|
|
|
describe('#loadTemplates', function() {
|
|
it('should throw on missing template', function(done) {
|
|
Precompiler.loadTemplates({ files: ['foo'] }, function(err) {
|
|
equal(err.message, 'Unable to open template file "foo"');
|
|
done();
|
|
});
|
|
});
|
|
it('should enumerate directories by extension', function(done) {
|
|
Precompiler.loadTemplates(
|
|
{ files: [__dirname + '/artifacts'], extension: 'hbs' },
|
|
function(err, opts) {
|
|
equal(opts.templates.length, 1);
|
|
equal(opts.templates[0].name, 'example_2');
|
|
done(err);
|
|
}
|
|
);
|
|
});
|
|
it('should enumerate all templates by extension', function(done) {
|
|
Precompiler.loadTemplates(
|
|
{ files: [__dirname + '/artifacts'], extension: 'handlebars' },
|
|
function(err, opts) {
|
|
equal(opts.templates.length, 3);
|
|
equal(opts.templates[0].name, 'bom');
|
|
equal(opts.templates[1].name, 'empty');
|
|
equal(opts.templates[2].name, 'example_1');
|
|
done(err);
|
|
}
|
|
);
|
|
});
|
|
it('should handle regular expression characters in extensions', function(done) {
|
|
Precompiler.loadTemplates(
|
|
{ files: [__dirname + '/artifacts'], extension: 'hb(s' },
|
|
function(err) {
|
|
// Success is not throwing
|
|
done(err);
|
|
}
|
|
);
|
|
});
|
|
it('should handle BOM', function(done) {
|
|
var opts = {
|
|
files: [__dirname + '/artifacts/bom.handlebars'],
|
|
extension: 'handlebars',
|
|
bom: true
|
|
};
|
|
Precompiler.loadTemplates(opts, function(err, opts) {
|
|
equal(opts.templates[0].source, 'a');
|
|
done(err);
|
|
});
|
|
});
|
|
|
|
it('should handle different root', function(done) {
|
|
var opts = {
|
|
files: [__dirname + '/artifacts/empty.handlebars'],
|
|
simple: true,
|
|
root: 'foo/'
|
|
};
|
|
Precompiler.loadTemplates(opts, function(err, opts) {
|
|
equal(opts.templates[0].name, __dirname + '/artifacts/empty');
|
|
done(err);
|
|
});
|
|
});
|
|
|
|
it('should accept string inputs', function(done) {
|
|
var opts = { string: '' };
|
|
Precompiler.loadTemplates(opts, function(err, opts) {
|
|
equal(opts.templates[0].name, undefined);
|
|
equal(opts.templates[0].source, '');
|
|
done(err);
|
|
});
|
|
});
|
|
it('should accept string array inputs', function(done) {
|
|
var opts = { string: ['', 'bar'], name: ['beep', 'boop'] };
|
|
Precompiler.loadTemplates(opts, function(err, opts) {
|
|
equal(opts.templates[0].name, 'beep');
|
|
equal(opts.templates[0].source, '');
|
|
equal(opts.templates[1].name, 'boop');
|
|
equal(opts.templates[1].source, 'bar');
|
|
done(err);
|
|
});
|
|
});
|
|
it('should accept stdin input', function(done) {
|
|
var stdin = require('mock-stdin').stdin();
|
|
Precompiler.loadTemplates({ string: '-' }, function(err, opts) {
|
|
equal(opts.templates[0].source, 'foo');
|
|
done(err);
|
|
});
|
|
stdin.send('fo');
|
|
stdin.send('o');
|
|
stdin.end();
|
|
});
|
|
it('error on name missing', function(done) {
|
|
var opts = { string: ['', 'bar'] };
|
|
Precompiler.loadTemplates(opts, function(err) {
|
|
equal(
|
|
err.message,
|
|
'Number of names did not match the number of string inputs'
|
|
);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it('should complete when no args are passed', function(done) {
|
|
Precompiler.loadTemplates({}, function(err, opts) {
|
|
equal(opts.templates.length, 0);
|
|
done(err);
|
|
});
|
|
});
|
|
});
|
|
});
|