Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 19 commits
  • 41 files changed
  • 0 commit comments
  • 2 contributors
Showing with 723 additions and 860 deletions.
  1. +3 −1 .gitignore
  2. +2 −0  Makefile
  3. +1 −70 README.markdown
  4. +0 −69 bin/loadbuilder
  5. +0 −29 example/build_bundle.js
  6. +62 −0 lib/loadbuilder/analyzer.js
  7. +212 −0 lib/loadbuilder/asset.js
  8. +198 −0 lib/loadbuilder/builder.js
  9. +11 −0 lib/loadbuilder/util.js
  10. +6 −7 package.json
  11. +0 −347 src/loadbuilder.js
  12. +0 −48 src/util/mkdirSync.js
  13. +77 −0 test/analyzer.js
  14. +76 −0 test/asset.js
  15. +61 −0 test/builder.js
  16. +1 −0  test/fixtures/dep1.js
  17. +1 −0  test/fixtures/dep1dep.js
  18. +1 −0  test/fixtures/dep2.js
  19. +1 −0  test/fixtures/has_dep.js
  20. +1 −0  test/fixtures/simple.js
  21. +1 −0  test/fixtures/simple2.js
  22. +0 −8 test/javascripts/script1.js
  23. +0 −3  test/javascripts/script2.js
  24. +1 −1  test/modules/{mod1_a.js → anon.js}
  25. +1 −0  test/modules/common.js
  26. +3 −0  test/modules/has_dep.js
  27. +0 −20 test/modules/mod1-simple.js
  28. +0 −10 test/modules/mod2-multiple.js
  29. +0 −3  test/modules/mod2_a.js
  30. +0 −3  test/modules/mod2_b.js
  31. +0 −31 test/modules/mod3-tree.js
  32. +0 −5 test/modules/mod3_a.js
  33. +0 −3  test/modules/mod3_b.js
  34. +0 −5 test/modules/mod3_c.js
  35. +0 −9 test/modules/mod4-script.js
  36. +0 −5 test/modules/mod4_a.js
  37. +0 −1  test/modules/mod5-fail.js
  38. +0 −8 test/modules/mod6-sequence.js
  39. +3 −0  test/modules/named.js
  40. +0 −3  test/modules/sub/mod1_b.js
  41. +0 −171 test/shot.js
View
4 .gitignore
@@ -1 +1,3 @@
-test/dist
+test/dist
+node_modules
+.DS_Store
View
2  Makefile
@@ -0,0 +1,2 @@
+test_all:
+ NODE_PATH=./src `npm bin`/expresso -g test/*.js
View
71 README.markdown
@@ -6,73 +6,4 @@ loadbuilder.js (JavaScript dependency builder for [Loadrunner.js](https://github
Overview
--------
-Loadbuilder uses nodejs to build your loadrunner modules into simple bundles for production loading.
-
-Get
----
-
-Download this package.
-
-Install
--------
-
-cd into this folder and use npm to install it
- npm install .
-
-Test
-----
-
-We use expresso to run the tests
- npm install expresso
- cd test
- expresso shot.js
-
-Command Line
-------------
-
- Usage: loadbuilder [options] file
-
- Document root
- -d, --docRoot <value>
- Output root
- -o, --distRoot <value>
- Module path, relative to document root
- -m, --modPath <value>
- Don't minify
- -nm, --nomin
- Exclude scripts
- -x, --exclude <value>
- Run JSHint to log (info)
- -h, --hint
- Log Level - 0:none, 1:errors, 2:info
- -l, --logLevel <value>
-
- loadbuilder <module>
-
-Loads the module from 'modules' folder and all dependencies. Compiles them into a single file, and outputs it with the same name into 'dist/modules' folder.
-
- loadbuilder -d <docroot> -m <modpath> -o <distroot> <module>
-
-Loads the module from '<docroot>/<modpath>' folder and all dependencies. Compiles them into a single file, and outputs it with the same name into '<distroot>/<modpath>' folder.
-
-API
----
-
- var loadbuilder = require('loadbuilder');
-
- var myBuilder = loadbuilder.builder({
- docRoot: 'test',
- modPath: 'modules',
- distRoot: 'test/dist',
- logLevel: 3
- });
-
-Loads the loadbuilder library and configures a builder.
-
- phoenixBuilder.bundle('mod1-simple');
-
-Bundles module. Outputs to 'test/dist/modules/mod1-simple.js'
-
-.... More stuff
-
-Feedback appreciated as always.
+Loadbuilder uses nodejs to build your loadrunner modules into simple bundles for production loading.
View
69 bin/loadbuilder
@@ -1,69 +0,0 @@
-#!/usr/bin/env node
-
-var opts = require('opts'),
- loadbuilder = require('../src/loadbuilder');
-
-var options = [
- {
- short : 'l',
- long : 'logLevel',
- description : 'Log Level - 0:none, 1:errors, 2:info',
- value : true,
- default : 2,
- },
- {
- short : 'h',
- long : 'hint',
- description : 'Run JSHint to log (info)',
- },
- {
- short : 'x',
- long : 'exclude',
- description : 'Exclude scripts',
- value : true,
- default : '',
- },
- {
- short : 'nm',
- long : 'nomin',
- description : 'Don\'t minify',
- },
- {
- short : 'm',
- long : 'modPath',
- description : 'Module path, relative to document root',
- value : true,
- },
- {
- short : 'o',
- long : 'distRoot',
- description : 'Output root',
- value : true,
- },
- {
- short : 'd',
- long : 'docRoot',
- description : 'Document root',
- value : true,
- },
-];
-
-var arguments = [ { name : 'file' , required : true } ];
-
-opts.parse(options, arguments, true);
-
-var main = opts.arg('file');
-
-var LB = loadbuilder.builder({
- exclude : (opts.get('x') || '').split(','),
- docRoot : opts.get('d') || process.cwd(),
- distRoot : opts.get('o') || "STDOUT/",
- modPath : opts.get('m') || '',
- logLevel : opts.get('l') || 3,
- nomin : !!opts.get('nm')
-});
-LB.load(main);
-if (opts.get('h')) {
- LB.hint();
-}
-LB.save(main);
View
29 example/build_bundle.js
@@ -1,29 +0,0 @@
-#!/usr/bin/env node
-
-var loadbuilder = require('loadbuilder');
-
-var phoenixBuilder = loadbuilder.builder({
- docRoot: 'test',
- modPath: 'modules',
- distRoot: 'test/dist',
- logLevel: 2
-});
-
-var cbundle = phoenixBuilder.bundle('mod2-multiple');
-
-var dbundle = phoenixBuilder.bundle('mod1-simple', {
- exclude: [cbundle]
-});
-
-// var ebundle = phoenixBuilder.bundle(['mod1-simple', 'mod2-multiple']);
-
-var fbundle = phoenixBuilder.bundle('mod4-script');
-
-phoenixBuilder.bundle('mod3-tree', {
- exclude: ['mod3_b', cbundle, dbundle]
-});
-
-console.log('errors:', phoenixBuilder.getErrors());
-
-console.log('manifest:', phoenixBuilder.getBundleManifest());
-
View
62 lib/loadbuilder/analyzer.js
@@ -0,0 +1,62 @@
+var parser = require('uglify-js').parser;
+
+function match(fragment, tree) {
+ var matches = [];
+
+ if ((fragment.length <= tree.length) && fragment.every(function(item, i) {
+ var subMatches;
+
+ if (item === null) {
+ matches.push(tree[i]);
+ return true;
+ }
+
+ if (item === tree[i]) {
+ return true;
+ }
+
+ if (Array.isArray(tree[i]) && Array.isArray(item) && (subMatches = match(item, tree[i]))) {
+ matches = matches.concat(subMatches);
+ return true;
+ }
+
+ return false;
+ })) {
+ return matches;
+ }
+
+ return null;
+}
+
+function walk(matcher, tree, parent, index) {
+ var matches = [], m;
+
+ if (Array.isArray(tree)) {
+ if (m = match(matcher, tree)) {
+ matches.push({
+ parent: parent || null,
+ index: index || 0,
+ values: m
+ });
+ }
+
+ tree.forEach(function(node, i) {
+ matches = matches.concat(walk(matcher, node, tree, i));
+ });
+ }
+
+ return matches;
+}
+
+function analyze(matcher, sourceOrTree) {
+ var tree = Array.isArray(sourceOrTree) ?
+ sourceOrTree : parser.parse(sourceOrTree);
+
+ return walk(matcher, tree);
+}
+
+module.exports = {
+ match: match,
+ walk: walk,
+ analyze: analyze
+};
View
212 lib/loadbuilder/asset.js
@@ -0,0 +1,212 @@
+var util = require('./util'),
+ analyzer = require('./analyzer'),
+ fs = require('fs'),
+ path = require('path'),
+ jshint = require('jshint').JSHINT,
+ uglify = require("uglify-js");
+
+var USING = [ 'call', [ 'name', 'using' ], null ];
+var ARRAY_ARG = [ 'array', null ];
+var STRING_ARG = [ 'string', null ];
+var PROVIDE = [ 'call', [ 'name', 'provide' ], null ];
+var REQUIRE = [ 'call', [ 'name', 'require' ], [ [ 'string', null] ] ];
+
+var dependencyCache = {};
+var dependencyCacheLastUpdate = {};
+
+function Script(id) {
+ this.id = id;
+}
+
+util.extend(Script.prototype, {
+ dependencies: function() {
+
+ var usings, dependencies = [];
+
+ if(dependencyCache[this.id]) {
+ // Make sure it's not out of date
+ console.log(dependencyCache[this.id]);
+ }
+
+ if (!dependencyCache[this.id]) {
+ usings = analyzer.analyze(USING, this.fromFile());
+
+ usings.forEach(function(call) {
+ var args = call.values[0];
+
+ args.forEach(function(arg) {
+ var dep, m;
+
+ if (m = analyzer.match(STRING_ARG, arg)) {
+ dep = this.builder.matchAsset(m[0]);
+ dependencies = dependencies.concat(dep);
+ } else if(m = analyzer.match(ARRAY_ARG, arg)) {
+ arg[1].forEach(function(arg) {
+ // FIXME: duplicate code; un-nest this stuff
+ // nesty :(
+ var dep, m;
+
+ if (m = analyzer.match(STRING_ARG, arg)) {
+ dep = this.builder.matchAsset(m[0]);
+ dependencies = dependencies.concat(dep);
+ }
+ }, this);
+ }
+ }, this);
+ }, this);
+
+ dependencyCache[this.id] = dependencies;
+ dependencyCacheLastUpdate[this.id] = new Date();
+ }
+
+ return dependencyCache[this.id];
+ },
+ lint: function(options) {
+ var lintOptions = util.extend({}, this.builder.options.lint || {});
+ util.extend(lintOptions, options || {});
+
+ if (!jshint(this.fromFile(), lintOptions)) {
+ this.report(jshint.errors);
+ process.exit(1);
+ }
+ },
+ toSource: function() {
+ if (!this._source) {
+ this._source = this.fromFile();
+ }
+
+ return this.deferWrapper(this._source);
+ },
+ preProcess: function(data) {
+ return this.builder.preProcessor ? this.builder.preProcessor(data) : data;
+ },
+ fromFile: function() {
+ if (!this._fromFile) {
+ this._fromFile = this.preProcess(fs.readFileSync(this.fullPath(), 'utf8'));
+ }
+
+ return this._fromFile;
+ },
+ fullPath: function() {
+ if (this.id.match(/^\$/)) {
+ return this.builder.modPath(this.id.replace(/^\$/, ''));
+ } else {
+ return this.builder.path(this.id);
+ }
+ },
+ report: function(errors) {
+ console.log('Errors in ' + this.fullPath() + ':\n');
+
+ errors.forEach(function(e) {
+ console.log('#' + e.line + ': ' + e.evidence);
+ console.log(e.reason + ' line: ' + e.line +
+ ', col: ' + e.character + '\n');
+ });
+ },
+ deferWrapper: function(source) {
+ return this.builder.options.useDeferred === true ? "deferred('" +
+ this.id + "', function() {\n" + source + "\n});" : source;
+ }
+});
+
+function Module(id) {
+ this.id = id;
+}
+
+Module.prototype = new Script;
+Module.cjsMemo = {};
+
+util.extend(Module.prototype, {
+ fullPath: function() {
+ if(this.id.indexOf('bluejs') === 0) {
+ // FIXME: stop special casing bluejs and understand how it currently works in Monorail
+ return this.builder.modPath('../../' + this.id + '.js');
+ }
+ return this.builder.modPath(this.id + '.js');
+ },
+ toSource: function() {
+ if (!this._source) {
+ if (this.isCJS()) {
+ this._source = this.amdWrappedSource();
+ } else {
+ this._source = this.addId(this.fromFile());
+ }
+ } else {
+ console.log("Already had source");
+ }
+
+ return this._source;
+ },
+ isCJS: function() {
+ if (typeof this._isCJS == 'undefined') {
+ // FIXME: no memoization in Loadbuilder, please.
+ var fileInfo = fs.statSync(this.fullPath());
+ var cjsMemoKey = fileInfo.mtime + '_' + this.fullPath();
+ if(typeof(Module.cjsMemo[cjsMemoKey]) !== 'undefined') {
+ this._isCJS = Module.cjsMemo[cjsMemoKey];
+ } else {
+ this._isCJS = Module.cjsMemo[cjsMemoKey] = !analyzer.analyze(PROVIDE, this.fromFile()).length;
+ }
+ }
+
+ return this._isCJS;
+ },
+ amdWrappedSource: function() {
+ var deps = ['require', 'exports'].concat(this.dependencies().map(function(d) { return d.id; })),
+ preamble = "(function() {\nvar module=define(" + JSON.stringify(this.id) + "," +
+ JSON.stringify(deps) + ",function(require, exports) {\n",
+ postamble = "\n});\n})();"
+
+ return preamble + this.fromFile() + postamble;
+ },
+
+ dependencies: function() {
+ if(!this._deps) {
+ if (this.isCJS()) {
+ this._deps = this.dependenciesFromRequire();
+ } else {
+ this._deps = Script.prototype.dependencies.call(this);
+ }
+ }
+ return this._deps;
+ },
+ dependenciesFromRequire: function() {
+ var requires;
+
+ if (!dependencyCache[this.id]) {
+ requires = analyzer.analyze(REQUIRE, this.fromFile());
+
+ dependencyCache[this.id] = requires.map(function(r) {
+ return this.builder.matchAsset(r.values[0]);
+ }, this);
+ }
+
+ return dependencyCache[this.id];
+ },
+ addId: function() {
+ var tree = uglify.parser.parse(this.fromFile()),
+ provides = analyzer.analyze(PROVIDE, tree),
+ provide;
+
+ if (provides.length > 0) {
+ provide = provides[0];
+
+ // TODO make this nice - maybe have a transform function?
+ if (analyzer.match(STRING_ARG, provide.values[0][0]) == null) {
+ provide.parent[provide.index][2].unshift(['string', this.id]);
+ } else {
+ console.log("string thing is null");
+ }
+ } else {
+ console.log("provides.length is zero", provides.length);
+ console.log(JSON.stringify(provides));
+ }
+
+ return uglify.uglify.gen_code(tree, { beautify: true });
+ }
+});
+
+module.exports = {
+ Script: Script,
+ Module: Module
+};
View
198 lib/loadbuilder/builder.js
@@ -0,0 +1,198 @@
+var util = require('./util'),
+ asset = require('./asset'),
+ path = require('path'),
+ fs = require('fs'),
+ uglify = require("uglify-js");
+
+function collect(excluded, assets, includeDependencies) {
+ var collected = [];
+
+ assets.forEach(function(asset) {
+ if(!asset) {
+ console.warn('Undefined asset in assets list');
+ console.log(new Error().stack);
+ return;
+ }
+ var deps = [];
+ if (excluded.indexOf(asset.id) < 0) {
+ if (includeDependencies) {
+ deps = asset.dependencies();
+ }
+ excluded = excluded.concat([asset.id]);
+
+ collected = collected.concat(
+ collect(excluded, deps, includeDependencies)
+ ).concat(asset);
+ }
+ });
+
+ return collected;
+}
+
+function dedupe(assets) {
+ var i, ii, elem, seen = {},
+ result = [];
+
+ for (i = 0, ii = assets.length; i < ii; i++) {
+ elem = assets[i];
+ if (!seen[elem.id]) {
+ seen[elem.id] = true;
+ result.push(elem);
+ }
+ }
+
+ return result;
+}
+
+function Builder(options) {
+ this.options = {};
+ util.extend(this.options, Builder.default_options);
+ util.extend(this.options, options || {});
+ this.assets = [];
+ this.excludes = this.options.excludes || [];
+ this.matchers = [];
+ this.preProcessor = options.preProcessor;
+}
+
+Builder.default_options = {
+ path: process.cwd(),
+ docroot: process.cwd(),
+ includeDependencies: true,
+ preProcessor: null
+};
+
+util.extend(Builder.prototype, {
+ include: function(ids) {
+ this.assets = this.mapAssets(arguments);
+
+ return this;
+ },
+ exclude: function(ex) {
+ var excludes;
+
+ if (ex.assets) {
+ excludes = ex.assets.map(function(dep) { return dep.id });
+ } else {
+ excludes = [].slice.call(arguments);
+ }
+
+ this.excludes = this.excludes.concat(excludes);
+
+ return this;
+ },
+ log: function(message, level) {
+ console.log(message);
+ },
+ path: function(id) {
+ return path.join(this.options.docroot, id);
+ },
+ modPath: function(id) {
+ return path.join(this.options.docroot, this.options.path, id);
+ },
+ addMatcher: function(regex, factory) {
+ this.matchers.push([regex, factory]);
+ },
+ matchAsset: function(id) {
+ var m, dep, asset;
+ var allMatchers = this.matchers.concat(builder.matchers);
+ for (var i=0, matcher; matcher = allMatchers[i]; i++) {
+ var regex = matcher[0], factory = matcher[1];
+ if (this.excludes.indexOf(id) < 0 && (m = id.match(regex))) {
+ asset = factory(id);
+ asset.builder = this;
+ return asset;
+ }
+ }
+ },
+ mapAssets: function(assets) {
+ var mapped = [];
+
+ for (var i=0, asset; asset = assets[i]; i++) {
+ if (typeof asset == 'string') {
+ asset = this.matchAsset(asset);
+ }
+
+ mapped.push(asset);
+ }
+
+ return mapped;
+ },
+ lint: function(options) {
+ this.collectedAssets().forEach(function(a) {
+ a.lint(options);
+ });
+
+ return this;
+ },
+ minify: function(options) {
+ if (options === false) {
+ this.minifyOptions = null;
+ } else {
+ this.minifyOptions = (typeof options == 'object') ? options : {};
+ }
+
+ return this;
+ },
+ minifySource: function(source) {
+ this.log('- Minifying bundle');
+
+ var ast, opts = util.extend({}, this.options.minify || {});
+ util.extend(opts, this.minifyOptions);
+
+ ast = uglify.parser.parse(source);
+ ast = uglify.uglify.ast_mangle(ast, opts);
+ ast = uglify.uglify.ast_squeeze(ast, opts);
+
+ return uglify.uglify.gen_code(ast, opts);
+ },
+ toSource: function() {
+ var source = this.collectedAssets().map(function(a) {
+ this.log('* ' + a.id);
+ return a.toSource();
+ }, this).join('\n');
+
+ if (this.minifyOptions) {
+ source = this.minifySource(source);
+ }
+
+ return source;
+ },
+ write: function(path, success) {
+
+ fs.writeFile(
+ path, this.toSource(),
+ 'utf8', success || function() {}
+ );
+
+ this.log('> ' + path);
+
+ return this;
+ },
+ collectedAssets: function() {
+ return dedupe(collect(this.excludes, this.assets, this.options.includeDependencies));
+ }
+});
+
+function builder(options) {
+ return new Builder(options);
+}
+
+builder.asset = asset;
+builder.analyzer = require('./analyzer');
+builder.matchers = [];
+
+builder.matchers.add = function(regex, factory) {
+ this.unshift([regex, factory]);
+}
+
+asset.Module.regexp = /^\.?[a-zA-Z0-9_\-\/]+$/;
+builder.matchers.add(asset.Module.regexp, function(id) {
+ return new asset.Module(id);
+})
+
+asset.Script.regexp = /.js$/;
+builder.matchers.add(asset.Script.regexp, function(id) {
+ return new asset.Script(id);
+})
+
+module.exports = builder;
View
11 lib/loadbuilder/util.js
@@ -0,0 +1,11 @@
+function extend(target, source) {
+ Object.keys(source).forEach(function(key) {
+ target[key] = source[key];
+ });
+
+ return target;
+}
+
+module.exports = {
+ extend: extend
+};
View
13 package.json
@@ -1,20 +1,19 @@
{
"name": "loadbuilder",
- "version": "0.1.1",
+ "version": "0.2.0",
"description": "Combine and compress dependency chains created by Loadrunner",
"contributors": [{ "name": "Dan Webb", "email": "dan@danwebb.net" }, { "name": "Kenneth Kufluk", "email": "kenneth@kufluk.com" }],
"homepage": "https://github.com/danwrong/loadbuilder",
- "directories" : { "src" : "./src" },
- "main" : "./src/loadbuilder",
+ "directories" : { "lib" : "./lib" },
+ "main" : "./src/loadbuilder/builder",
"engines": { "node": ">= 0.4.0" },
- "bin": {
- "loadbuilder": "./bin/loadbuilder"
- },
"dependencies": {
- "npm": ">= 1.0.0",
"jshint": ">=0",
"opts": ">=1.2.1",
"uglify-js": ">=0.0.5",
"colors": ">=0.5.0"
+ },
+ "devDependencies": {
+ "expresso": ">=0.9.2"
}
}
View
347 src/loadbuilder.js
@@ -1,347 +0,0 @@
-var fs = require('fs'),
- sys = require('sys'),
- mkdir = require('./util/mkdirSync'),
- jsp = require('uglify-js').parser,
- jspro = require("uglify-js").uglify,
- opts = require('opts'),
- colors = require('colors'),
- path = require('path'),
- jshint = require('jshint').JSHINT;
-
-function mixin(target, source) {
- Object.keys(source).forEach(function(key) {
- target[key] = source[key];
- });
-
- return target;
-}
-
-function indent(depth) {
- return Array(depth).join(' ');
-}
-
-function extractDeps(argList) {
- var depList = [];
- argList.forEach(function(item) {
- if (item[0] == 'string') depList.push(item[1]);
- else if (item[0] == 'array') depList = depList.concat(extractDeps(item[1]));
- });
- return depList;
-}
-
-function isUsing(node) {
- return node[0] == 'call' && node[1] && node[1][1] == 'using';
-}
-
-function isProvide(node) {
- return node[0] == 'call' && node[1] && node[1][1] == 'provide';
-}
-
-function excluded(item, loadbuilder) {
- var excluded = false;
- loadbuilder.options.exclude.forEach(function(excl) {
- if (typeof(excl)=='string' && excl==item) {
- excluded = true;
- return;
- }
- if (typeof(excl)=='object') {
- excl.forEach(function(exclitem) {
- if (exclitem == item) {
- excluded = true;
- return;
- }
- });
- }
- });
- return excluded;
-}
-
-
-function Dependency() {
- // this.name => the string appearing in the using statement
- // this.lb => a reference to the builder object we're using
-}
-
-function DependencyChain() {
- this.deps = [];
-}
-DependencyChain.prototype.add = function(dep) {
- // remove from dependencies if existing
- this.deps = this.deps.filter(function(element) {
- return (element.name != dep.name);
- });
- // add above first script
- this.deps.unshift(dep);
-}
-
-function Script(name, loadbuilder, depth) {
- if (name) {
- this.name = name;
- this.lb = loadbuilder;
- this.filename = this.getFilename(this.lb.options.modPath);
- this.license = '';
- this.preCode = 'provide("' + name + '", function(exports) {';
- this.postCode = ';exports();loadrunner.Script.loaded.push("' + name + '")})';
- this.type = 'script';
- }
-
- if (depth === 0) {
- this.preCode = '';
- this.postCode = '';
- }
-}
-Script.matcher = /\.js$/;
-Script.prototype = new Dependency;
-Script.prototype.fetchSource = function() {
- return fs.readFileSync(this.lb.options.docRoot + this.filename, 'utf8');
-};
-Script.prototype.parseSource = function(source) {
- this.license = this.getLicense(source);
- return jsp.parse(source);
-};
-Script.prototype.getLicense = function(source) {
- var text = source.replace(/\n/g, '\\n');
- var matches = text.match(/^(\/\*\!.*?\*\/)/);
- if (matches) return matches[1].replace(/\\n/g, '\n');
- return '';
-};
-Script.prototype.hint = function(source, opts) {
- jshint(source, opts);
- if (jshint.errors.length) {
- this.lb.logInfo('JSHint ' + this.name, jshint.errors);
- }
-};
-Script.prototype.getCode = function(parsedSource, minify) {
- var code, ast = parsedSource;
- if (minify) {
- ast = jspro.ast_mangle(ast);
- ast = jspro.ast_squeeze(ast);
- }
- code = jspro.gen_code(ast);
- return this.preCode + this.license + code + this.postCode;
-};
-Script.prototype.getFilename = function(modPath) {
- return this.name.replace(/^\$/, modPath);
-};
-Script.prototype.traceDependencies = function(depth) {
- var me = this, source, parsedSource;
- depth = depth+1 || 0;
- if (excluded(this.name, this.lb)) {
- this.lb.logInfo('Ignoring file:', [ this.name, this.filename ]);
- return;
- }
- try {
- source = this.fetchSource();
- this.lb.logInfo('Loading file:', [ this.name, this.filename ]);
- } catch (error) {
- this.lb.logError('Failed to load file:', [ this.name, this.filename ]);
- return;
- }
- try {
- parsedSource = this.parseSource(source);
- this.lb.dependencies.add(this);
- } catch (error) {
- this.lb.logError('Failed to parse file:', [ this.name, this.filename ]);
- this.hint(source);
- return;
- }
-
- function walk(node) {
- if (Array.isArray(node)) {
- if (isUsing(node)) {
- var deps = extractDeps(node[2]);
- deps.forEach(function(d) {
- me.lb._loadFile(d, depth+1);
- });
- } else if (isProvide(node)) {
- if (node[2][0][0] === 'function') {
- node[2].unshift(['string', me.name]);
- }
- }
-
- node.forEach(walk);
- }
- }
-
- walk(parsedSource);
-
- this.code = this.getCode(parsedSource, !this.lb.options.nomin);
-
- return;
-};
-
-
-function Module(name, loadbuilder) {
- this.name = name;
- this.lb = loadbuilder;
- this.filename = this.lb.options.modPath + this.getFilename();
- this.license = '';
- this.preCode = '';
- this.postCode = '';
- this.type = 'module';
-}
-Module.matcher = /^[a-zA-Z0-9_\-\/]+$/;
-Module.prototype = new Script;
-Module.prototype.getFilename = function() {
- return this.name + '.js';
-};
-
-function LoadBuilder(options) {
- this.options = {
- exclude: [],
- docRoot: process.cwd(),
- distRoot: 'STDOUT/',
- modPath: '/modules',
- logLevel: 1, // log levels: 0:none, 1:error, 2:info
- matchers: [Script, Module],
- nomin: false
- };
- this.manifest = {};
- this.clean();
- this.config(options);
-}
-LoadBuilder.prototype = {
- // Removes data pertaining to current bundling task, but not the overall builder, like manifests and config.
- clean: function() {
- this.options.exclude = [];
- this.dependencies = new DependencyChain;
- this.code = '';
- this.errors = [];
- },
- // Applies new config options
- config: function(options) {
- mixin(this.options, options);
- this.options.docRoot = this.options.docRoot.replace(/\/$/,'') + '/';
- this.options.distRoot = this.options.distRoot.replace(/\/$/,'') + '/';
- this.options.modPath = this.options.modPath.replace(/^\//,'').replace(/\/$/,'') + '/';
- if (this.options.docRoot == this.options.distRoot) {
- this.logInfo('Helpfully appending "dist" to the distRoot.', []);
- this.options.distRoot += 'dist/';
- }
- return this;
- },
- // Works out the type of a given dependency
- // Then loads the file
- _loadFile: function(name, depth) {
- for (var index in this.options.matchers) {
- if (name.match(this.options.matchers[index].matcher)) {
- var file = new this.options.matchers[index](name, this, depth);
- file.traceDependencies(depth);
- return;
- }
- }
- this.logError('Unrecognised dependency', [ name ]);
- },
- // This is used to load the initial files/modules provided to the builder
- load: function(files, options) {
- var file, loadbuilder=this;
- if (typeof(files)==="string") files=[files];
- files.forEach(function(d) {
- loadbuilder._loadFile(d, 0);
- });
- return this;
- },
- // Use JSHINT on all the dependencies in the bundle
- hint: function(opts){
- this.dependencies.deps.forEach(function(d) {
- d.hint(opts);
- });
- },
- // Wrap our code string with a custom namespace
- namespace: function(code) {
- return this.options.namespace + "(function(using, provide, loadrunner, define) {" +
- code + '});';
- },
- // Add a minified version of loadrunner to the top of the code string
- addLoadrunner: function(code) {
- var lr = fs.readFileSync(this.options.standAlone, 'utf8');
-
- if (!this.options.nomin) {
- var ast = jsp.parse(lr);
- ast = jspro.ast_mangle(ast);
- ast = jspro.ast_squeeze(ast);
-
- lr = jspro.gen_code(ast);
- }
-
- if (typeof this.options.namespace == 'string' && this.options.namespace.length > 0) {
- lr += ";window." + this.options.namespace + " = loadrunner.noConflict();"
- }
-
- return lr + code;
- },
- // Generate the code string, apply options and output to a file or stdout
- save: function(outputFilename) {
- // merge code
- var codeArr = [], code;
- this.dependencies.deps.forEach(function(item) {
- codeArr.push(item.code);
- });
- code = codeArr.join(";\n");
-
- if (typeof this.options.namespace == 'string' && this.options.namespace.length > 0) {
- code = this.namespace(code);
- }
-
- if (typeof this.options.standAlone == 'string' && this.options.standAlone.length > 0) {
- code = this.addLoadrunner(code);
- }
-
- var outputFile = this.options.distRoot + outputFilename;
-
- if (this.options.distRoot == 'STDOUT/') {
- console.log(code);
- } else {
- this.logInfo('Output file', [ outputFile ]);
- mkdir(outputFile.replace(/[^\/]+$/, ''));
- fs.writeFileSync(outputFile, code);
- }
- return this;
- },
- // Bundle a module
- bundle: function(name, bundleOpts) {
- this.clean();
- var files = name;
- if (!!bundleOpts) {
- this.config(bundleOpts);
- if (bundleOpts.files) files = bundleOpts.files;
- }
- this.load(files);
- var filename = name;
- if (!name.match(/\.js$/)) {
- filename = this.options.modPath + name + '.js'; // TODO: This is a poor detection for Modules
- }
- this.save(filename.replace(/\$/, this.options.modPath));
-
- // return the dep names for use in the exclusion param of future bundles
- var loadedDeps = [];
- this.dependencies.deps.forEach(function(dep) {
- loadedDeps.push(dep.name);
- });
- this.manifest[name] = loadedDeps;
- return loadedDeps;
- },
- log: function(level, message, obj) {
- this.errors.push({ level: level, message: message, obj:obj });
- if (this.options.logLevel >= level) console.log(message, obj);
- },
- logInfo: function(message, obj) {
- this.log(2, message, obj);
- },
- logError: function(message, obj) {
- this.log(1, message, obj);
- },
- getErrors: function() {
- return this.errors;
- },
- getBundleManifest: function() {
- return this.manifest;
- }
-};
-
-mixin(exports, {
- builder: function(options) {
- return new LoadBuilder(options);
- },
- Dependency: Dependency // output to make testing possible
-});
View
48 src/util/mkdirSync.js
@@ -1,48 +0,0 @@
-/*
- * Adapted from @isaacs's mkdir-p... made sync...
- */
-
-var fs = require("fs")
- , path = require("path")
-
-module.exports = mkdirSync
-
-function mkdirSync (ensure, mode) {
- mode = mode || 0755;
- ensure = ensure.replace(/\/+$/, '');
- if (ensure.charAt(0) !== "/") ensure = path.join(process.cwd(), ensure);
- try {
- var s = fs.statSync(ensure);
- if (s && s.isDirectory()) return;
- } catch (e) {}
- return walkDirs(ensure, mode);
-}
-
-function walkDirs (ensure, mode) {
- var dirs = ensure.split("/")
- , walker = [];
-
- walker.push(dirs.shift()) // gobble the "/" first
- ;(function S (d) {
- if (d === undefined) return;
- walker.push(d);
- var dir = walker.join("/");
- (function STATCB() {
- try {
- if (fs.statSync(dir).isDirectory()) {
- S(dirs.shift());
- } else {
- throw new Error("Failed to mkdir "+dir+": File exists");
- }
- } catch (e) {
- try {
- fs.mkdirSync(dir, mode);
- S(dirs.shift())
- } catch (er) {
- if (er.message.indexOf("EEXIST")) return STATCB();
- throw er;
- }
- }
- })();
- })(dirs.shift())
-}
View
77 test/analyzer.js
@@ -0,0 +1,77 @@
+var analyzer = require('loadbuilder/analyzer'),
+ assert = require('assert');
+
+var tree = [1, 2, [3], [4, [5]], [5]], match, matches;
+
+module.exports = {
+ testMatchShouldReturnNullIfNoMatches: function() {
+ match = analyzer.match(['not', 'here', 3556], tree);
+ assert.isNull(match);
+ },
+
+ testMatchShouldReturnArrayIfMatches: function() {
+ match = analyzer.match([1, 2], tree);
+ assert.eql(match, []);
+
+ match = analyzer.match([1, 2, [3]], tree);
+ assert.eql(match, []);
+
+ match = analyzer.match(tree, tree);
+ assert.eql(match, []);
+ },
+
+ testMatchShouldReturnMatchedWildcardsInArray: function() {
+
+ match = analyzer.match([null, 2], tree);
+ assert.eql(match, [1]);
+
+ match = analyzer.match([1, 2, [null]], tree);
+ assert.eql(match, [3]);
+
+ match = analyzer.match([null, 2, [null]], tree);
+ assert.eql(match, [1, 3]);
+ },
+
+ testMatchShouldMatchArraysWithWildcard: function() {
+
+ match = analyzer.match([1, 2, null], tree);
+ assert.eql(match, [[3]]);
+ },
+
+ testWalkShouldReturnArrayOfMatches: function() {
+ matches = analyzer.walk([4], tree);
+ assert.eql(matches, [
+ { parent: tree, index: 3, values: [] }
+ ]);
+
+ matches = analyzer.walk([1, null], tree);
+ assert.eql(matches, [
+ { parent: null, index: 0, values: [2] }
+ ]);
+
+ matches = analyzer.walk([4, [null]], tree);
+ assert.eql(matches, [
+ { parent: tree, index: 3, values: [5] }
+ ]);
+
+ matches = analyzer.walk([5], tree);
+ assert.eql(matches, [
+ { parent: tree[3], index: 1, values: [] },
+ { parent: tree, index: 4, values: [] }
+ ]);
+ },
+
+ testAnalyzeShouldWalkJSSource: function() {
+ var src = "function pow() { var thing = require('blah'); }";
+
+ matches = analyzer.analyze(
+ [ 'call',
+ [ 'name', 'require' ],
+ [
+ ['string', null]
+ ]
+ ], src);
+
+ assert.eql(matches[0].values, ['blah']);
+ }
+}
View
76 test/asset.js
@@ -0,0 +1,76 @@
+var builder = require('loadbuilder/builder'),
+ asset = require('loadbuilder/asset'),
+ assert = require('assert');
+
+module.exports = {
+ testAssetShouldRetrieveSource: function() {
+ var a = new asset.Script('fixtures/simple.js');
+ a.builder = builder({
+ docroot: __dirname
+ });
+ assert.equal("alert('hello world');", a.toSource());
+ },
+ testAssetCanBeWrappedInDeferred: function() {
+ var a = new asset.Script('fixtures/simple.js');
+ a.builder = builder({
+ docroot: __dirname,
+ useDeferred: true
+ });
+ assert.equal("deferred('fixtures/simple.js', function() {\nalert('hello world');\n});", a.toSource());
+ },
+ testShouldFindDependenciesForModule: function() {
+ var a = new asset.Script('fixtures/dep1.js');
+ a.builder = builder({
+ docroot: __dirname
+ });
+
+ assert.equal('dep1dep', a.dependencies()[0].id);
+ },
+ testShouldAddNameToAnonModule: function() {
+ var a = new asset.Module('anon');
+ a.builder = builder({
+ docroot: __dirname,
+ path: '/modules'
+ });
+
+ assert.equal('provide("anon", function(exports) {\n exports("hi");\n});', a.toSource());
+ },
+ testShouldNotAddNameToNamedModule: function() {
+ var a = new asset.Module('named');
+ a.builder = builder({
+ docroot: __dirname,
+ path: '/modules'
+ });
+
+ assert.equal('provide("shindig", function(exports) {\n exports("hi");\n});', a.toSource());
+ },
+ testShouldFindDependenciesForModule: function() {
+ var a = new asset.Module('has_dep');
+ a.builder = builder({
+ docroot: __dirname,
+ path: '/modules'
+ });
+
+ assert.equal('anon', a.dependencies()[0].id);
+ },
+ testShouldFindDependenciesForModule: function() {
+ var a = new asset.Module('common');
+ a.builder = builder({
+ docroot: __dirname,
+ path: '/modules'
+ });
+
+ assert.equal('anon', a.dependencies()[0].id);
+ },
+ testShouldWrapModule: function() {
+ var a = new asset.Module('common');
+
+ a.builder = builder({
+ docroot: __dirname,
+ path: '/modules'
+ });
+
+ assert.equal('(function() {\nvar module=define("common",["require","exports","anon"],' +
+ 'function(require, exports) {\nvar a = require("anon");\n});\n})();', a.toSource());
+ }
+}
View
61 test/builder.js
@@ -0,0 +1,61 @@
+var builder = require('loadbuilder/builder'),
+ asset = require('loadbuilder/asset'),
+ assert = require('assert'),
+ fs = require('fs');
+
+var opts = {
+ docroot: __dirname
+};
+
+module.exports = {
+ testBuildShouldProvideSourceOfAllAssetsInCollection: function() {
+ assert.equal(
+ "alert('hello world');\nalert('hello world again');",
+ builder(opts).include('fixtures/simple.js', 'fixtures/simple2.js').toSource()
+ );
+ },
+ testShouldDedupeAssetsInACollection: function() {
+ assert.equal(
+ "alert('hello world');\nalert('hello world again');",
+ builder(opts).include('fixtures/simple.js', 'fixtures/simple2.js', 'fixtures/simple.js').toSource()
+ );
+ },
+ testShouldBeAbleToExcludeFiles: function() {
+ assert.equal(
+ "alert('hello world');",
+ builder(opts).include('fixtures/simple.js', 'fixtures/simple2.js').exclude('fixtures/simple2.js').toSource()
+ );
+ },
+ testShouldCollectDependencies: function() {
+ assert.equal(
+ "alert('hello dep1');\nusing('fixtures/dep1dep.js');\nalert('hello');\nusing('fixtures/dep1.js', 'fixtures/dep2.js');",
+ builder(opts).include('fixtures/has_dep.js').toSource()
+ );
+ },
+ testShouldExcludeDependenciesOfExcludedAsset: function() {
+ assert.equal(
+ "alert('hello');\nusing('fixtures/dep1.js', 'fixtures/dep2.js');",
+ builder(opts).include('fixtures/has_dep.js').exclude('fixtures/dep1.js').toSource()
+ );
+ },
+ testShouldBeAbleToExcludeMultipleDependencies: function() {
+ assert.equal(
+ "using('fixtures/dep1.js', 'fixtures/dep2.js');",
+ builder(opts).include('fixtures/has_dep.js').exclude('fixtures/dep1.js', 'fixtures/dep2.js').toSource()
+ );
+ },
+ testShouldBeAbleToExcludeABundle: function() {
+ var a = builder(opts).include('fixtures/dep1.js', 'fixtures/dep2.js');
+ assert.equal(
+ "using('fixtures/dep1.js', 'fixtures/dep2.js');",
+ builder(opts).include('fixtures/has_dep.js').exclude(a).toSource()
+ );
+ },
+ testShouldBeAbleToWriteToAFile: function() {
+ var path = __dirname + '/bundle.js';
+ builder(opts).include('fixtures/simple.js', 'fixtures/simple2.js').write(path, function() {
+ assert.equal("alert('hello world');\nalert('hello world again');",fs.readFileSync(path, 'utf8'));
+ fs.unlinkSync(path);
+ });
+ }
+};
View
1  test/fixtures/dep1.js
@@ -0,0 +1 @@
+using('fixtures/dep1dep.js');
View
1  test/fixtures/dep1dep.js
@@ -0,0 +1 @@
+alert('hello dep1');
View
1  test/fixtures/dep2.js
@@ -0,0 +1 @@
+alert('hello');
View
1  test/fixtures/has_dep.js
@@ -0,0 +1 @@
+using('fixtures/dep1.js', 'fixtures/dep2.js');
View
1  test/fixtures/simple.js
@@ -0,0 +1 @@
+alert('hello world');
View
1  test/fixtures/simple2.js
@@ -0,0 +1 @@
+alert('hello world again');
View
8 test/javascripts/script1.js
@@ -1,8 +0,0 @@
-/*!
- This is a license comment.
- It's a license comment because I put /*! at the start.
- That means it should be preserved, even through minification.
-*/
-var S1 = function(s) {
- return 's1' + s;
-};
View
3  test/javascripts/script2.js
@@ -1,3 +0,0 @@
-var S2 = function(s) {
- return S1('s2' + s);
-};
View
2  test/modules/mod1_a.js → test/modules/anon.js
@@ -1,3 +1,3 @@
provide(function(exports) {
- exports(true);
+ exports('hi');
});
View
1  test/modules/common.js
@@ -0,0 +1 @@
+var a = require("anon");
View
3  test/modules/has_dep.js
@@ -0,0 +1,3 @@
+using('anon', function(a) {
+ alert(a);
+});
View
20 test/modules/mod1-simple.js
@@ -1,20 +0,0 @@
-/*!
- This is a license comment.
- It's a license comment because I put /*! at the start.
- That means it should be preserved, even through minification.
-*/
-provide(function(exports) {
- var monitor = '';
-
- using('mod1_a', function(simple) {
- monitor.push('mod1_a' + simple);
- exports(function() {
- return monitor;
- });
- });
-
- using('sub/mod1_b', function(simple) {
- monitor.push('mod1_b' + simple);
- });
-
-});
View
10 test/modules/mod2-multiple.js
@@ -1,10 +0,0 @@
-provide(function(exports) {
- using('mod2_a', function(a) {
- using('mod2_b', function(b) {
- exports(b);
- });
- });
- using('mod2_b', function(b) {
-
- });
-});
View
3  test/modules/mod2_a.js
@@ -1,3 +0,0 @@
-provide(function(exports) {
- exports(true);
-});
View
3  test/modules/mod2_b.js
@@ -1,3 +0,0 @@
-provide(function(exports) {
- exports(true);
-});
View
31 test/modules/mod3-tree.js
@@ -1,31 +0,0 @@
-/*
- This is a more complex use-case for dependencies.
- We'll try to load in a complicated tree.
-*/
-provide(function(exports) {
-
- using('mod3_a', function(a) { // A depends on B
- using('mod3_c', function(c) { // C depends on A
- exports(c);
- });
- });
- // -> B, A, C
-
- using('mod3_a', 'mod3_c', function(a, c) { // A depends on B // C depends on A
- exports(c);
- });
- // -> B, A, C
-
- using('mod3_a', function(a) { // A depends on B
- using('mod3_c', function(c) { // C depends on A
- using('mod3_a', function(a2) { // A depends on B
- exports(a2);
- });
- });
- using('mod3_c', function(c) { // C depends on A
- exports(c);
- });
- });
- // -> B, A, C
-
-});
View
5 test/modules/mod3_a.js
@@ -1,5 +0,0 @@
-provide(function(exports) {
- using('mod3_b', function(b) {
- exports(b);
- });
-});
View
3  test/modules/mod3_b.js
@@ -1,3 +0,0 @@
-provide(function(exports) {
- exports(true);
-});
View
5 test/modules/mod3_c.js
@@ -1,5 +0,0 @@
-provide(function(exports) {
- using('mod3_a', function(a) {
- exports(a);
- });
-});
View
9 test/modules/mod4-script.js
@@ -1,9 +0,0 @@
-provide(function(exports) {
- using('javascripts/script1.js', function() { // S1 provides global S1 var
- using('mod4_a', function(a) { // A needs S1
- using('$../javascripts/script2.js', function() { // S2 uses S1, provides global S2 var
- exports(a);
- });
- });
- });
-});
View
5 test/modules/mod4_a.js
@@ -1,5 +0,0 @@
-provide(function(exports) {
- if (typeof(S1) != 'undefined') {
- exports(true);
- }
-});
View
1  test/modules/mod5-fail.js
@@ -1 +0,0 @@
-penguins are cool;
View
8 test/modules/mod6-sequence.js
@@ -1,8 +0,0 @@
-provide(function(exports) {
- using(['mod2_a', 'mod2_b'], function(a, b) {
- exports(b);
- });
- using('mod2_b', function(b) {
-
- });
-});
View
3  test/modules/named.js
@@ -0,0 +1,3 @@
+provide('shindig', function(exports) {
+ exports('hi');
+});
View
3  test/modules/sub/mod1_b.js
@@ -1,3 +0,0 @@
-provide(function(exports) {
- exports(true);
-});
View
171 test/shot.js
@@ -1,171 +0,0 @@
-/*
-
- Tests for LoadBuilder
- Requires expresso
- > expresso shot.js
-
- // TODO: check excludes, bundle manifest, errors
-
-*/
-
-var assert = require('assert'),
- fs = require('fs');
-
-// require loadbuilder
-var LoadBuilder = require('../src/loadbuilder');
-
-// check the configs are correctly set
-exports.testConfig = function(beforeExit){
-
- var testRunner = LoadBuilder.builder({
- docRoot: '.',
- distRoot: 'testdist',
- modPath: 'modules'
- });
- assert.equal(testRunner.options.docRoot, './');
- assert.equal(testRunner.options.distRoot, 'testdist/');
- assert.equal(testRunner.options.modPath, 'modules/');
-
-};
-
-
-// simple test, load a module
-exports.testSimple = function(beforeExit){
-
- var testRunner = LoadBuilder.builder({
- docRoot: '.',
- distRoot: 'testdist',
- modPath: 'modules',
- logLevel: 3
- });
- var modCount = 0;
- // load mod1
- testRunner.load('mod1-simple');
- // check deps are loaded
- var expected = ['sub/mod1_b', 'mod1_a', 'mod1-simple'];
- testRunner.dependencies.deps.forEach(function(mod){
- assert.equal(expected.shift(), mod.name);
- modCount++;
- });
- beforeExit(function(){
- assert.equal(3, modCount, 'All modules loaded.');
- });
-
-};
-// multiple file test
-exports.testMultiple = function(beforeExit){
-
- var testRunner = LoadBuilder.builder({
- docRoot: '.',
- distRoot: 'testdist',
- modPath: 'modules'
- });
- var modCount = 0;
- // load mod2
- testRunner.load('mod2-multiple');
- // check deps are loaded
- var expected = ['mod2_b', 'mod2_a', 'mod2-multiple'];
- testRunner.dependencies.deps.forEach(function(mod){
- assert.equal(expected.shift(), mod.name);
- modCount++;
- });
- beforeExit(function(){
- assert.equal(3, modCount, 'All modules loaded.');
- });
-
-};
-// nasty, complicated test
-exports.testTree = function(beforeExit){
-
- var testRunner = LoadBuilder.builder({
- docRoot: '.',
- distRoot: 'testdist',
- modPath: 'modules'
- });
- var modCount = 0;
- // load mod3
- testRunner.load('mod3-tree');
- // check load order is correct
- var expected = ['mod3_b', 'mod3_a', 'mod3_c', 'mod3-tree'];
- testRunner.dependencies.deps.forEach(function(item){
- assert.equal(expected.shift(), item.name);
- modCount++;
- });
- beforeExit(function(){
- assert.equal(4, modCount, 'All modules loaded.');
- });
-
-};
-// script loading test
-exports.testScript = function(beforeExit){
-
- var testRunner = LoadBuilder.builder({
- docRoot: '.',
- distRoot: 'testdist',
- modPath: 'modules'
- });
- var modCount = 0;
- // load mod4
- testRunner.load('mod4-script');
- // check load order is correct
- var expected = ['$../javascripts/script2.js', 'mod4_a', 'javascripts/script1.js', 'mod4-script'];
- testRunner.dependencies.deps.forEach(function(item){
- assert.equal(expected.shift(), item.name);
- modCount++;
- });
- beforeExit(function(){
- assert.equal(4, modCount, 'All items loaded.');
- });
-
-};
-// bundle test
-exports.testBundle = function(beforeExit){
-
- var testRunner = LoadBuilder.builder({
- docRoot: '.',
- distRoot: 'testdist',
- modPath: 'modules'
- });
- var modCount = 0;
- // load mod2
- testRunner.bundle('mod2-multiple');
- // check file exists
- fs.stat('testdist/modules/mod2-multiple.js', function(err, stats) {
- assert.ok(!err);
- fs.unlinkSync('testdist/modules/mod2-multiple.js');
- modCount++;
- });
-
- // check load order is correct
- var expected = ['mod2_b', 'mod2_a', 'mod2-multiple'];
- testRunner.dependencies.deps.forEach(function(item){
- assert.equal(expected.shift(), item.name);
- modCount++;
- });
- beforeExit(function(){
- assert.equal(4, modCount, 'Bundle test complete.');
- });
-
-};
-// sequence test
-exports.testSequence = function(beforeExit){
-
- var testRunner = LoadBuilder.builder({
- docRoot: '.',
- distRoot: 'testdist',
- modPath: 'modules'
- });
- var modCount = 0;
- // load mod2
- testRunner.load('mod6-sequence');
- // check deps are loaded
- var expected = ['mod2_b', 'mod2_a', 'mod6-sequence'];
- testRunner.dependencies.deps.forEach(function(mod){
- assert.equal(expected.shift(), mod.name);
- modCount++;
- });
- beforeExit(function(){
- assert.equal(3, modCount, 'All modules loaded.');
- });
-
-};

No commit comments for this range

Something went wrong with that request. Please try again.