UNPKG

steal-tools

Version:

Futuristic build tools for ES6 Module applications.

2,116 lines (1,741 loc) 61.6 kB
var winston = require('winston'); var dependencyGraph = require("../lib/graph/make_graph"), comparify = require("comparify"), bundle = require("../lib/graph/make_graph_with_bundles"), recycle = require("../lib/graph/recycle"), orderGraph = require("../lib/graph/order"), mapDeps = require("../lib/graph/map_dependencies"), assert = require('assert'), multiBuild = require("../lib/build/multi"), Browser = require("zombie"), connect = require("connect"), path = require('path'), rmdir = require('rimraf'), transformImport = require("../lib/build/transform"), fs = require('fs-extra'), logging = require('../lib/logger'), stealExport = require('../lib/build/export'), asap = require("pdenodeify"); var isIOjs = process.version.substr(0, 3) !== "v0."; // mock-fs doesn't work in iojs 3.0 right now so skipping until that is fixed. if(!isIOjs) { var mockFs = require("mock-fs") } var find = require("./helpers").find; var open = require("./helpers").open; System.logLevel = 3; require("./test_cli"); require("./grunt_tasks/steal_build"); // Node 0.10 doesn't support Symbols so the live-reload tests will // not pass on it. if(typeof Symbol !== "undefined") { require("./test_live"); } (function(){ describe('dependency graph', function(){ beforeEach(function() { logging.setup({ quiet: true }); }); it('should work', function(done){ dependencyGraph({ config: path.join(__dirname, "stealconfig.js"), startId: "basics", logLevel: 3 }).then(function(data){ var result = comparify(data.graph, { "stealconfig.js": { load: {} }, '@dev': { load: { metadata: { // ignore: true } } }, 'basics/basics': { deps: ['basics/module/module'], dependencies: ['basics/module/module'] }, 'basics/module/module': { deps: ["basics/es6module"], dependencies:["basics/es6module"] }, "basics/es6module": { deps: ['basics/amdmodule'], dependencies:["basics/amdmodule"] } }, true); done(); }).catch(function(e){ done(e) }); }); it("Should allow extra config options to be passed in", function(done){ dependencyGraph({ config: __dirname + "/stealconfig.js", startId: "basics", extra: "stuff", logLevel: 3 }).then(function(data){ var steal = data.steal; var extra = steal.config("extra"); assert.equal(extra, "stuff", "Extra config options added"); }).then(done); }); describe("Utility functions", function(){ it("Map should work", function(done){ dependencyGraph({ config: __dirname + "/stealconfig.js", startId: "basics", logLevel: 3 }).then(function(data){ var graph = data.graph; var modules = mapDeps(graph, 'basics/basics', function(name){ return name; }); comparify(modules, [ "basics/basics", "basics/module/module", "basics/es6module", "basics/amdmodule" ], true); }).then(done); }); describe("Order", function(){ it("works when a module is dependent on @empty", function(){ var graph = { main: { dependencies: ["@empty", "dep"] }, dep: { dependencies: [] } }; orderGraph(graph, "main"); assert.equal(graph.dep.order, 0, "Dep is first"); assert.equal(graph.main.order, 1, "Main is second"); }); }); }); }); describe("bundle", function(){ it("should work", function(done){ bundle({ config: __dirname+"/bundle/stealconfig.js", main: "bundle", logLevel: 3 }).then(function(data){ var graphCompare = require('./bundle/bundle_graph'); comparify(data.graph, graphCompare, true); done(); }).catch(function(e){ done(e) }); }); it("works with globs", function(done){ bundle({ config: __dirname+"/bundle/stealconfig.js", main: "bundle", logLevel: 3, bundle: "app_*" }).then(function(data){ var graphCompare = require('./bundle/bundle_graph'); comparify(data.graph, graphCompare, true); done(); }).catch(function(e){ done(e) }); }); }); if(!isIOjs) { describe("Recycle", function(){ beforeEach(function() { logging.setup({ quiet: true }); }); afterEach(mockFs.restore); it("Creates an error message when there is an es6 syntax error", function(done){ var config = { config: path.join(__dirname, "stealconfig.js"), main: "basics/basics", logLevel: 3 }; var depStream = bundle.createBundleGraphStream(config); var recycleStream = recycle(config); depStream.pipe(recycleStream); // Wait for it to initially finish loading. recycleStream.once("data", function(data){ var node = data.graph["basics/es6module"]; var mockOptions = {}; // Fake string as the source. mockOptions[node.load.address.replace("file:", "")] = "syntax error"; mockFs(mockOptions); recycleStream.write(node.load.name); recycleStream.once("error", function(err){ assert(err instanceof Error, "we got an error"); done(); }); }); depStream.write(config.main); }); it("Works with a project using live-reload", function(done){ var config = { config: __dirname + "/live_reload/package.json!npm", logLevel: 3 }; var options = { localStealConfig: { env: "build-development" } }; var depStream = bundle.createBundleGraphStream(config, options); var recycleStream = recycle(config, options); depStream.pipe(recycleStream); // Wait for it to initially finish loading. recycleStream.once("data", function(data){ var node = data.graph.foo; var mockOptions = {}; // Fake string as the source. mockOptions[node.load.address.replace("file:", "")] = "module.exports = 'foo'"; mockFs(mockOptions); recycleStream.once("data", function(data){ var node = data.graph.main; assert(/foo/.test(node.load.source), "Source changed"); done(); }); recycleStream.write(node.load.name); }); depStream.write(config.main); }); it("Detects dynamic imports added when no static dependencies have changed", function(done){ var config = { config: path.join(__dirname, "/recycle_dynamic/config.js"), main: "something.txt!plug", logLevel: 3, map: { "@dev": "@empty" } }; var depStream = bundle.createBundleGraphStream(config); var recycleStream = recycle(config); depStream.pipe(recycleStream); // Wait for it to initially finish loading. recycleStream.once("data", function(data){ var node = data.graph["something.txt!plug"]; // Update the module so that it has a dynamic import. This should // be added to the loader's bundle and the graph reloaded. var mockOptions = {}; Object.keys(data.graph).forEach(function(moduleName){ var load = data.graph[moduleName].load; mockOptions[load.address.replace("file:", "")] = load.source; }); mockOptions[node.load.address.replace("file:", "")] = 'System.import("another");'; mockOptions[path.resolve(__dirname + "/recycle_dynamic/another.js")] = 'var dep = require("./dep");'; mockOptions[path.resolve(__dirname + "/recycle_dynamic/dep.js")] = 'module.exports = "dep";'; mockFs(mockOptions); recycleStream.write(node.load.name); recycleStream.once("data", function(data){ var graph = data.graph; assert(graph["another"], "this bundle was added to the graph"); assert(graph["dep"], "the bundle's dependency was also added"); done(); }); }); depStream.write(config.main); }); }); } describe("order", function(){ it("should work", function(){ var graph = { "a":{ "deps":[ "dep_a_b", "dep_all" ], "dependencies":[ "dep_a_b", "dep_all" ] }, "dep_a_b":{ "deps":[], "dependencies":[] }, "dep_all":{ "deps":["jquery"], "dependencies":["jquery"], }, "jquery": { deps: [], dependencies: [] } }; orderGraph(graph,"a"); comparify(graph, { "a":{ order: 3 }, "dep_a_b":{ order: 0 }, "dep_all":{ order: 2 }, "jquery": { order: 1 } }, true); }); }); describe("multi build", function(){ this.timeout(5000); it("should work", function(done){ rmdir(__dirname+"/bundle/dist", function(error){ if(error){ done(error); } multiBuild({ config: __dirname+"/bundle/stealconfig.js", main: "bundle" }, { quiet: true }).then(function(data){ var exists = fs.existsSync( path.join(__dirname,"bundle/dist/bundles/bundle.js") ); if(!exists) { done(new Error("no bundle info")); return; } open("test/bundle/bundle.html#a",function(browser, close){ find(browser,"appA", function(appA){ assert(true, "got A"); assert.equal(appA.name, "a", "got the module"); assert.equal(appA.ab.name, "a_b", "a got ab"); assert.equal(appA.clean, undefined, "removed dev code"); close(); }, close); }, done); }, done); }); }); it("should work with CommonJS", function(done){ rmdir(__dirname + "/commonjs/bundle", function(error){ if(error) { return done(error); } multiBuild({ config: __dirname + "/commonjs/config.js", main: "main" }, { quiet: true }).then(function(){ open("test/commonjs/prod.html", function(browser, close){ find(browser, "app", function(app){ assert.equal(app.foo, "bar", "Correct object placed on the window"); close(); }, close); }, done); }).catch(done); }); }); it("should pass the babelOptions to transpile", function(done){ this.timeout(20000); rmdir(__dirname + "/es6-loose/bundle", function(error){ if(error) { return done(error); } multiBuild({ config: __dirname + "/es6-loose/config.js", main: "main", transpiler: "babel" }, { quiet: true, minify: false, babelOptions: { loose: 'es6.modules' } }).then(function(){ fs.readFile("test/es6-loose/dist/bundles/main.js", "utf8", function(err, data) { if (err) { done(err); } var noObjectDefineProperty = data.indexOf("Object.defineProperty") === -1; var es6ModuleProperty = data.indexOf("exports.__esModule = true;") >= 0; assert(noObjectDefineProperty, "loose mode does not use Object.defineProperty"); assert(es6ModuleProperty, "should assign __esModule as normal object property"); done(); }); }).catch(done); }); }); it("doesn't include the traceur runtime if it's not being used", function(done){ rmdir(__dirname + "/simple-es6/dist", function(error){ if(error) { return done(error); } multiBuild({ config: __dirname + "/simple-es6/config.js", main: "main" }, { quiet: true }).then(function(){ fs.readFile(__dirname + "/simple-es6/dist/bundles/main.js", function(error, contents){ assert.equal(error, null, "Able to open the file"); assert.equal(/\$traceurRuntime/.test(contents), false, "Traceur not included"); done(); }); }).catch(done); }); }); it("Should minify by default", function(done){ var config = { config: __dirname + "/minify/config.js", main: "minify" }; rmdir(__dirname+"/minify/dist", function(error){ if(error) { done(error); return; } multiBuild(config, { quiet: true }).then(function(){ var actual = fs.readFileSync(__dirname + "/minify/dist/bundles/minify.js", "utf8"); var hasLongVariable = actual.indexOf("thisObjectHasABigName") !== -1; var hasGlobalLongVariable = actual.indexOf("anotherVeryLongName") !== -1; var hasDevCode = actual.indexOf("remove this") !== -1; assert(!hasLongVariable, "Minified source renamed long variable."); assert(!hasGlobalLongVariable, "Minified source includes a global that was minified."); assert(!hasDevCode, "Minified source has dev code removed."); }).then(done); }); }); it("Should allow minification to be turned off", function(done){ var config = { config: __dirname + "/minify/config.js", main: "minify" }; var options = { minify: false, quiet: true }; rmdir(__dirname+"/minify/dist", function(error){ if(error) { done(error); return; } multiBuild(config, options).then(function(){ var actual = fs.readFileSync(__dirname + "/minify/dist/bundles/minify.js", "utf8"); var hasLongVariable = actual.indexOf("thisObjectHasABigName") !== -1; assert(hasLongVariable, "Source includes long variable name."); done(); }).catch(function(e){ done(e); }); }); }); it("Should allow setting uglify-js options", function(done) { var config = { config: __dirname + "/minify/config.js", main: "minify" }; var options = { quiet: true, uglifyOptions: { mangle: false // skip mangling names. } }; rmdir(__dirname + "/minify/dist", function(error){ if(error) { done(error); return; } multiBuild(config, options).then(function(){ var actual = fs.readFileSync(__dirname + "/minify/dist/bundles/minify.js", "utf8"), hasLongVariable = actual.indexOf("thisObjectHasABigName") !== -1, hasAnotherLongVariable = actual.indexOf("anotherLongVariableName") !== -1; assert(hasLongVariable, "Skip mangling names in dependencies graph files"); assert(hasAnotherLongVariable, "skip mangling names in stealconfig and main files"); done(); }).catch(done); }); }); it("Should allow setting clean-css options", function(done) { var config = { config: __dirname + "/minify/config.js", main: "minify" }; var options = { quiet: true, cleanCSSOptions: { keepSpecialComments: 0 // remove all, default '*' } }; rmdir(__dirname + "/minify/dist", function(error){ if(error) { done(error); return; } multiBuild(config, options).then(function(){ var actual = fs.readFileSync(__dirname + "/minify/dist/bundles/minify.css", "utf8"), lackSpecialComment = actual.indexOf("a special comment") === -1; assert(lackSpecialComment, "clean-css set to remove special comments"); done(); }).catch(done); }); }); it("Allows specifying an alternative dist directory", function(done){ var config = { config: __dirname + "/other_bundle/stealconfig.js", main: "bundle", bundlesPath: __dirname + "/other_bundle/other_dist/bundles" }; var options = { quiet: true }; rmdir(__dirname + "/other_bundle/other_dist", function(error){ if(error) { done(error); return; } multiBuild(config, options).then(function(){ open("test/other_bundle/bundle.html#a",function(browser, close){ find(browser,"appA", function(appA){ assert(true, "got A"); assert.equal(appA.name, "a", "got the module"); assert.equal(appA.ab.name, "a_b", "a got ab"); close(); }, close); }, done); }); }); }); it("Allows specifying dist as the current folder", function(done){ this.timeout(5000); var config = { config: __dirname + "/other_bundle/stealconfig.js", main: "bundle", bundlesPath: __dirname+"/other_bundle/bundles" }; var options = { quiet: true }; rmdir(__dirname + "/other_bundle/bundles", function(error){ if(error) { done(error); return; } multiBuild(config, options).then(function(){ open("test/other_bundle/bundle-dist.html#a",function(browser, close){ find(browser,"appA", function(appA){ assert(true, "got A"); assert.equal(appA.name, "a", "got the module"); assert.equal(appA.ab.name, "a_b", "a got ab"); close(); }, close); }, done); }); }); }); it("supports bundling steal", function(done){ rmdir(__dirname+"/bundle/bundles", function(error){ if(error){ done(error) } multiBuild({ config: __dirname+"/bundle/stealconfig.js", main: "bundle" },{ bundleSteal: true, quiet: true }).then(function(data){ open("test/bundle/packaged_steal.html#a",function(browser, close){ find(browser,"appA", function(appA){ assert(true, "got A"); assert.equal(appA.name, "a", "got the module"); assert.equal(appA.ab.name, "a_b", "a got ab"); close(); }, close); }, done); }).catch(function(e){ done(e); }); }); }); it("allows bundling steal and loading from alternate locations", function(done){ rmdir(__dirname+"/bundle/alternate", function(error){ if(error){ done(error) } multiBuild({ config: __dirname+"/bundle/stealconfig.js", main: "bundle", bundlesPath: __dirname + "/bundle/alternate/bundles" },{ bundleSteal: true, quiet: true }).then(function(data){ open("test/bundle/folder/packaged_steal.html#a",function(browser, close){ find(browser,"appA", function(appA){ assert(true, "got A"); assert.equal(appA.name, "a", "got the module"); assert.equal(appA.ab.name, "a_b", "a got ab"); close(); }, close); }, done); }).catch(function(e){ done(e); }); }); }); it("builds and can load transpiled ES6 modules", function(done){ rmdir(__dirname+"/dist", function(error){ if(error){ done(error) } multiBuild({ config: __dirname+"/stealconfig.js", main: "basics/basics" }, { quiet: true, minify: false }).then(function(data){ open("test/basics/prod.html",function(browser, close){ find(browser,"MODULE", function(module){ assert(true, "module"); assert.equal(module.name, "module", "module name is right"); assert.equal(module.es6module.name, "es6Module", "steal loads ES6"); assert.equal(module.es6module.amdModule.name, "amdmodule", "ES6 loads amd"); close(); }, close); }, done); }, done); }); }); it("System.instantiate works when bundling steal", function(done){ rmdir(__dirname+"/dist", function(error){ if(error){ return done(error) } multiBuild({ config: __dirname+"/stealconfig.js", main: "basics/basics" }, { bundleSteal: true, quiet: true, minify: false }).then(function(data){ open("test/basics/prod-inst.html",function(browser, close){ find(browser,"MODULE", function(module){ assert(true, "module"); // We marked stealconfig.js as instantiated so it shouldn't have it's properties var System = browser.window.System; assert.equal(System.map["mapd/mapd"], undefined, "Mapping not applied"); close(); }, close); }, done); }); }); }); it("Returns an error when building a main that doesn\'t exist", function(done){ var config = { config: __dirname + "/stealconfig.js", main: "some/fake/app" }; var options = { quiet: true }; // Temporarily swallow console.logs to prevent 404 showing. var log = console.log; console.log = function(){}; multiBuild(config, options).then(function onFulfilled(){ // If we get then the error wasn't caught properly assert(false, "Build completed successfully when there should have been an error"); }, function onRejected(err){ assert(err instanceof Error, "Caught an error when loading a fake main"); }).then(function() { // Set back console.log console.log = log; }).then(done); }); it("removes steal.dev references", function(done){ rmdir(__dirname + "/bundle/dist", function(error){ if(error){ done(error); } multiBuild({ main: "bundle", config: __dirname + "/bundle/stealconfig.js" }, { quiet: true }).then(function(){ fs.readFile(__dirname + "/bundle/dist/bundles/app_a.js", function(error, content){ assert(!error, "able to open the file"); assert.equal( /steal.dev/.test(content), false, "it should remove steal.dev references" ); done(); }); }, done); }); }); it("works with the bower plugin", function(done){ rmdir(__dirname + "/bower/dist", function(error){ if(error) return done(error); multiBuild({ config: __dirname + "/bower/config.js", main: "main" }, { quiet: true, minify: false }).then(function(){ open("test/bower/prod.html",function(browser, close){ find(browser,"MODULE", function(module){ assert(true, "module"); assert(module.jquerty, "has jquerty"); assert(module.jquerty(), "hello jquerty", "correct function loaded"); close(); }, close); }, done); }, done); }); }); it("works with the bower plugin when using as the config", function(done){ // this test seems broken. rmdir(__dirname + "/bower/dist", function(error){ if(error) return done(error); multiBuild({ config: __dirname + "/bower/bower.json!bower", main: "main" }, { quiet: true, minify: false }).then(function(){ open("test/bower/prod.html",function(browser, close){ find(browser,"MODULE", function(module){ assert(true, "module"); assert(module.jquerty, "has jquerty"); assert(module.jquerty(), "hello jquerty", "correct function loaded"); close(); }, close); }, done); }, done); }); }); it("works with babel", function(done){ this.timeout(5000); // this test seems broken. rmdir(__dirname + "/babel/dist", function(error){ if(error) return done(error); multiBuild({ config: __dirname + "/babel/config.js", main: "main" }, { quiet: true, minify: false }).then(function(){ open("test/babel/prod.html",function(browser, close){ find(browser,"MODULE", function(module){ assert(true, "module"); assert(module.dep, "has jquerty"); assert(module.dep(), "hello jquerty", "correct function loaded"); close(); }, close); }, done); }, done); }); }); it("works with an unnormalized main", function(done){ rmdir(__dirname+"/dist", function(error){ if(error){ done(error) } multiBuild({ config: __dirname+"/stealconfig.js", main: "basics/" }, { quiet: true, minify: false }).then(function(data){ open("test/basics/prod.html",function(browser, close){ find(browser,"MODULE", function(module){ assert(true, "module"); assert.equal(module.name, "module", "module name is right"); assert.equal(module.es6module.name, "es6Module", "steal loads ES6"); assert.equal(module.es6module.amdModule.name, "amdmodule", "ES6 loads amd"); close(); }, close); }, done); }, done); }); }); it("works with a project with json", function(done){ rmdir(__dirname+"/json/dist", function(error){ if(error) return done(error); multiBuild({ config: __dirname + "/json/package.json!npm" }, { quiet: true, minify: false }).then(function(){ open("test/json/prod.html", function(browser, close){ find(browser, "MODULE", function(module){ assert(!!module.data, "json data exists"); assert.equal(module.data.foo, "bar", "correctly parsed"); close(); }, close); }, done); }); }); }); it("can define own translate with meta", function(done){ rmdir(__dirname+"/meta_translate/dist", function(error){ if(error) return done(error); multiBuild({ configMain: "@empty", main: "main", baseURL: __dirname + "/meta_translate", meta: { a: { translate: function(load){ load.metadata.format = "amd"; return "define([], function(){\n" + "return 'b';\n});"; } } } }, { quiet: true, minify: false }).then(function(){ open("test/meta_translate/prod.html", function(browser, close){ find(browser, "MODULE", function(module){ assert.equal(module.a, "b", "translate worked"); close(); }, close); }, done); }); }); }); it("sideBundle: true will move a module into a side bundle", function(done){ rmdir(__dirname+"/side_bundle/dist", function(error){ if(error) return done(error); multiBuild({ config: __dirname + "/side_bundle/package.json!npm" }, { quiet: true, minify: false }).then(function(){ open("test/side_bundle/prod.html", function(browser, close){ find(browser, "MODULE", function(module){ var loader = browser.window.System; comparify(loader.bundles, { "bundles/b": [ "d", "b" ] }, true); close(); }, close); }, done); }); }); }); it("returns a buildResult", function(done){ rmdir(__dirname+"/bundle/dist", function(error){ if(error){ done(error); } multiBuild({ config: __dirname+"/bundle/stealconfig.js", main: "bundle" }, { quiet: true }).then(function(data){ assert(!!data.bundles, "bundles"); assert(!!data.configuration, "configuration"); assert(!!data.graph, "graph"); assert(!!data.loader, "loader"); assert(!!data.steal, "steal"); }).then(done); }); }); it("virtual modules can become bundles", function(done){ rmdir(__dirname+"/virtual/dist", function(error){ if(error) { return done(error); } multiBuild({ config: __dirname + "/virtual/config.js", main: "main" }, { quiet: true }).then(function(){ assert(true, "it worked"); open("test/virtual/prod.html", function(browser, close){ find(browser, "MODULE", function(module){ assert(typeof module.b, "undefined", "b module not included in the main bundle"); close(); }, close); }, done); }).then(null, done); }); }); it("envs configuration works", function(done){ rmdir(__dirname+"/envs/dist", function(error){ if(error) { return done(error); } multiBuild({ config: __dirname + "/envs/config.js", main: "main" }, { quiet: true }).then(function(){ open("test/envs/prod.html", function(browser, close){ find(browser, "MODULE", function(module){ assert.equal(module.FOO, "bar", "envs configuration was set"); close(); }, close); }, done); }).then(null, done); }); }); describe("bundleAssets", function(){ this.timeout(5000); before(function(done){ asap(rmdir)(__dirname + "/bundle_assets/dist") .then(function(){ done(); }); }); it("works", function(done){ multiBuild({ config: __dirname + "/bundle_assets/package.json!npm" }, { quiet: true, bundleAssets: true }).then(function(){ open("test/bundle_assets/prod.html", function(browser, close){ find(browser, "MODULE", function(module){ assert(true, "page loaded correctly"); close(); }, close); }, done); }); }); }); }); describe("multi build with plugins", function(){ it("work on the client", function(done){ this.timeout(5000); open("test/plugins/site.html", function(browser, close){ find(browser,"PLUGTEXT", function(plugText){ assert.equal(plugText, "client-Holler", "client can do plugins"); close(); }, close); }, done); }); it("work built", function(done){ // remove the bundles dir rmdir(__dirname+"/plugins/dist/bundles", function(error){ if(error){ done(error) } // build the project that // uses a plugin multiBuild({ config: __dirname+"/plugins/config.js", main: "main" }, { quiet: true }).then(function(data){ // open the prod page and make sure // the plugin processed the input correctly open("test/plugins/prod.html", function(browser, close){ find(browser,"PLUGTEXT", function(plugText){ assert.equal(plugText, "server-Holler", "server can do plugins"); close(); }, close); }, done); }).catch(function(e){ done(e); }); }); }); describe("multi build when long bundle names", function(){ it("should work", function(done){ rmdir(__dirname+"/long_bundle_names/dist", function(error){ if(error){ done(error) } multiBuild({ config: __dirname+"/long_bundle_names/stealconfig.js", main: "bundle" }, { quiet: true }).then(function(data){ open("test/long_bundle_names/bundle.html#a",function(browser, close){ find(browser,"appA", function(appA){ assert(true, "got A"); assert.equal(appA.name, "a", "got the module"); assert.equal(appA.ab.name, "a_b", "a got ab"); close(); }, close); }, done); }).catch(function(e){ done(e); }); }); }); it("should truncate and hash long bundle names", function(done){ rmdir(__dirname+"/long_bundle_names/dist", function(error){ if(error){ done(error) } multiBuild({ config: __dirname+"/long_bundle_names/stealconfig.js", main: "bundle" }, { quiet: true }).then(function(data){ assert(fs.existsSync("test/long_bundle_names/dist/bundles/app_a_with_a_ver-5797ef41.js")); assert(fs.existsSync("test/long_bundle_names/dist/bundles/app_a_with_a_ver-8702980e.js")); fs.readFile("test/long_bundle_names/dist/bundles/bundle.js", "utf8", function(err, data) { if (err) { done(err); } assert(data.indexOf("app_a_with_a_ver-5797ef41")); assert(data.indexOf("app_a_with_a_ver-8702980e")); done(); }); }).catch(function(e){ done(e); }); }); }); }); it("work built using steal", function(done){ // remove the bundles dir rmdir(__dirname+"/plugins/dist", function(error){ if(error){ done(error) } // build the project that // uses a plugin multiBuild({ config: __dirname+"/plugins/config.js", main: "main-steal", paths: { "plug/plug": "plug.js" } }, { quiet: true }).then(function(data){ // open the prod page and make sure // the plugin processed the input correctly open("test/plugins/prod-steal.html", function(browser, close){ find(browser,"PLUGTEXT", function(plugText){ assert.equal(plugText, "server-Holler", "server can do plugins"); close(); }, close); }, done); }).catch(function(e){ done(e); }); }); }); it("work with css buildType", function(done){ rmdir(__dirname+"/build_types/dist", function(error){ if(error){ done(error) } // build the project that // uses a plugin multiBuild({ config: __dirname+"/build_types/config.js", main: "main" }, { quiet: true }).then(function(data){ // open the prod page and make sure // the plugin processed the input correctly open("test/build_types/prod.html", function(browser, close){ find(browser,"STYLE_CONTENT", function(styleContent){ assert(styleContent.indexOf("#test-element")>=0, "have correct style info"); close(); }, close); }, done); }).catch(function(e){ done(e); }); }); }); it("can build less", function(done){ rmdir(__dirname+"/dep_plugins/dist", function(error){ if(error){ done(error) } // build the project that // uses a plugin multiBuild({ config: __dirname+"/dep_plugins/config.js", main: "main" }, { quiet: true }).then(function(data){ // open the prod page and make sure // the plugin processed the input correctly open("test/dep_plugins/prod.html", function(browser, close){ find(browser,"STYLE_CONTENT", function(styleContent){ assert(styleContent.indexOf("#test-element")>=0, "have correct style info"); close(); }, close); }, done); }).catch(function(e){ done(e); }); }); }); it("builds paths correctly", function(done){ rmdir(__dirname+"/css_paths/dist", function(error){ if(error){ done(error) } // build the project that // uses a plugin multiBuild({ config: __dirname+"/css_paths/config.js", main: "main" }, { quiet: true }).then(function(data){ // open the prod page and make sure // the plugin processed the input correctly open("test/css_paths/prod.html", function(browser, close){ find(browser,"STYLE_CONTENT", function(styleContent){ var count = 0; styleContent.replace(/url\(['"]?([^'"\)]*)['"]?\)/g, function(whole, part){ assert.equal(part,"../../images/hero-ribbons.png", "reference is correct"); count++; }); assert.equal(count, 3, "correct number of styles"); close(); }, close); }, done); }).catch(function(e){ done(e); }); }); }); it("plugins that are part of the main are part of the main bundle", function(done){ rmdir(__dirname+"/plugin_main_bundle/dist", function(error){ if(error) { return done(error); } multiBuild({ config: __dirname + "/plugin_main_bundle/config.js", main: "main" }, { minify: false, quiet: true }).then(function(buildResult){ var mainBundle = buildResult.bundles[0]; var found = false; for(var i = 0, len = mainBundle.nodes.length; i < len; i++) { var node = mainBundle.nodes[i]; if(node.load.name === "plug") { found = true; } } assert.ok(found, "plugin was in the main bundle"); }).then(done, done); }); }); it("Errors that happen during transpile are reported with the name of the module that failed", function(done){ multiBuild({ config: __dirname + "/stealconfig.js", main: "transpile_error/main" }, { minify: false, quiet: true }).then(function(){ assert(false, "Succeeded when it should not have"); }, function(err){ assert(/Unable to transpile transpile_error\/main:/.test(err.message), "Reports the module that had the transpile error"); }).then(done, done); }); }); describe("transformImport", function(){ it("basics should work", function(done){ transformImport({ config: __dirname+"/stealconfig.js", main: "pluginify/pluginify" }, { exports: { 'pluginify/global': 'globalModule' }, quiet: true }).then(function(transform){ fs.writeFile(__dirname+"/pluginify/out.js", transform().code, function(err) { // open the prod page and make sure // the plugin processed the input correctly open("test/pluginify/index.html", function(browser, close){ find(browser,"RESULT", function(result){ assert(result.module.es6module, "have dependeny"); assert(result.cjs(), "cjs"); assert.equal(result.global, "This is a global module", "Global module loaded"); assert.equal(result.UMD, "works", "Doesn't mess with UMD modules"); assert.equal(result.define, undefined, "Not keeping a global.define"); assert.equal(result.System, undefined, "Not keeping a global.System"); close(); }, close); }, done); }); }).catch(function(e){ console.log(e.stack) }); }); it("ignores files told to ignore", function(done){ transformImport({ config: __dirname + "/stealconfig.js", main: "pluginify/pluginify" }, { exports: {}, quiet: true }).then(function(transform){ // Get the resulting string, ignoring amdmodule var result = transform(null, { ignore: ["basics/amdmodule"] }).code; // Regex test to see if the basics/amdmodule is included var includesIgnoredThings = new RegExp("\\*basics\\/amdmodule\\*").test(result); assert.equal(includesIgnoredThings, false, "It excluded the modules told to."); }).then(done); }); it("makes plugins that depend on other made plugins",function(done){ transformImport({ config: __dirname+"/pluginify_deps/config.js", main: "plugin" }, { exports: {}, quiet: true }).then(function(transform){ var pluginOut = transform("plugin",{ ignore: ["util"], minify: false }).code; var utilOut = transform("util",{ ignore: ["lib"], minify: false, exports: { "lib" : "lib" } }).code; fs.mkdirs(__dirname+"/pluginify_deps/out", function(err) { fs.writeFile(__dirname+"/pluginify_deps/out/plugin.js", pluginOut, function(err) { fs.writeFile(__dirname+"/pluginify_deps/out/util.js", utilOut, function(err) { // open the prod page and make sure // the plugin processed the input correctly open("test/pluginify_deps/prod.html", function(browser, close){ find(browser,"plugin", function(plugin){ assert.equal(plugin.util.lib.name, "lib"); close(); }, close); }, done); }); }); }); }).catch(function(e){ console.log(e.stack) }); }); it("works when a file has no callback", function(done) { transformImport({ config: __dirname + "/stealconfig.js", main: "nocallback/nocallback" }, { exports: {}, quiet: true }).then(function(transform) { fs.writeFile(__dirname+"/nocallback/out.js", transform().code, function(err) { // open the prod page and make sure // the plugin processed the input correctly open("test/nocallback/index.html", function(browser, close){ find(browser, "RESULT", function(result){ assert(result.message, "I worked!"); close(); }, close); }, done); }); }); }); it("Excludes plugins from the built output unless marked includeInBuild", function(done){ transformImport({ config: __dirname+"/plugins/config.js", main: "main" }, { exports: {}, quiet: true }).then(function(transform){ var pluginOut = transform(null, { minify: false }).code; assert.equal(/System\.set/.test(pluginOut), false, "No System.set in the output"); }).then(done); }); it("Works with globals that set `this`", function(done){ rmdir(__dirname+"/pluginify_global/out.js", function(error){ if(error){ return done(error); } transformImport({ config: __dirname+"/pluginify_global/config.js", main: "main" }, { exports: { "global": "GLOBAL" }, quiet: true }).then(function(transform){ var pluginOut = transform(null, { minify: false }).code; fs.writeFile(__dirname + "/pluginify_global/out.js", pluginOut, function(error) { if(error) { return done(error); } open("test/pluginify_global/site.html", function(browser, close){ find(browser,"MODULE", function(result){ assert.equal(result.GLOBAL, "global", "Global using this set correctly."); close(); }, close); }, done); }); }); }); }); it("Works with modules that check for define.amd", function(done){ rmdir(__dirname + "/pluginify_define/out.js", function(error){ if(error) { return done(error); } transformImport({ config: __dirname + "/pluginify_define/config.js", main: "main" }, { quiet: true }).then(function(transform){ var out = transform(null, { minify: false }).code; fs.writeFile(__dirname + "/pluginify_define/out.js", out, function(error){ if(error) { return done(error); } open("test/pluginify_define/site.html", function(browser, close){ find(browser, "MODULE", function(result){ assert.equal(result.define, "it worked", "Module using define.amd works"); close(); }, close); }, done); }); }); }); }); }); describe("multi-main", function(){ it("should work", function(done){ var mains = ["app_a","app_b","app_c","app_d"], ab = {name: "a_b"}, cd = {name: "c_d"}, all = {name: "all"}, results = { app_a: { name: "a", ab: ab, all: all }, app_b: { name: "b", ab: ab, all: all }, app_c:{ name: "b", cd: cd, all: all }, app_d:{ name: "d", cd: cd, all: all } }; rmdir(__dirname+"/multi-main/dist", function(error){ if(error){ done(error) } multiBuild({ config: __dirname+"/multi-main/config.js", main: mains }, { quiet: true //verbose: true }).then(function(data){ var checkNext = function(next){ if(next) { open("test/multi-main/"+next+".html",function(browser, close){ find(browser,"app", function(app){ assert(true, "got app"); comparify(results[next], app); close(); }, close); }, function(err){ if(err) { done(err); } else { var mynext = mains.shift(); if(mynext) { setTimeout(function(){ checkNext(mynext) },1); } else { done(); } } }); } }; checkNext( mains.pop() ); }).catch(function(e){ done(e); }); }); }); it("works with steal bundled", function(done){ var mains = ["app_a","app_b","app_c","app_d"], ab = {name: "a_b"}, cd = {name: "c_d"}, all = {name: "all"}, results = { app_a: { name: "a", ab: ab, all: all }, app_b: { name: "b", ab: ab, all: all }, app_c:{ name: "b", cd: cd, all: all }, app_d:{ name: "d", cd: cd, all: all } }; rmdir(__dirname+"/multi-main/dist", function(error){ if(error){ done(error) } multiBuild({ config: __dirname+"/multi-main/config.js", main: mains }, { bundleSteal: true, quiet: true, minify: false }).then(function(data){ var checkNext = function(next){ if(next) { open("test/multi-main/bundle_"+next+".html",function(browser, close){ find(browser,"app", function(app){ assert(true, "got app"); comparify(results[next], app); close(); }, close); }, function(err){ if(err) { done(err); } else { var mynext = mains.shift(); if(mynext) { setTimeout(function(){ checkNext(mynext) },1); } else { done(); } } }); } }; checkNext( mains.pop() ); }).catch(function(e){ done(e); }); }); }); }); describe("export", function(){ it("basics work", function(done){ stealExport({ system: { main: "pluginifier_builder/pluginify", config: __dirname+"/stealconfig.js" }, options: { quiet: true }, "outputs": { "basics standalone": { modules: ["basics/module/module"], dest: function(){ return __dirname+"/out/basics.js" }, minify: false }, "pluginify without basics": { modules: ["pluginifier_builder/pluginify"], ignore: ["basics/module/module"], dest: function(){ return __dirname+"/out/pluginify.js" }, minify: false } } }).then(function(){ open("test/pluginifier_builder/index.html", function(browser, close){ find(browser,"RESULT", function(result){ assert.ok(result.module, "has module"); assert.ok(result.cjs,"has cjs module"); assert.equal(result.name, "pluginified"); close(); }, close); }, done); }, done); }); it("works with multiple mains", function(done){ stealExport({ system: { main: [ "pluginifier_builder/pluginify", "pluginifier_builder/common" ], config: __dirname+"/stealconfig.js" }, options: { quiet: true }, "outputs": { "basics standalone": { modules: ["basics/module/module"], dest: function(){ return __dirname+"/out/basics.js" }, minify: false }, "pluginify without basics": { modules: ["pluginifier_builder/pluginify"], ignore: ["basics/module/module"], dest: function(){ return __dirname+"/out/pluginify.js" }, minify: false } } }).then(function(){ open("test/pluginifier_builder/index.html", function(browser, close){ find(browser,"RESULT", function(result){ assert.ok(result.module, "has module"); assert.ok(result.cjs,"has cjs module"); assert.equal(result.name, "pluginified"); close(); }, close); }, done); }, done); }); it("passes the load objects to normalize and dest", function(done){ var destCalls = 0; stealExport({ system: { main: "pluginifier_builder_load/main", config: __dirname+"/stealconfig.js" }, options: { quiet: true }, "outputs": { "cjs": { graphs: ["pluginifier_builder_load/main"], useNormalizedDependencies: false, format: "cjs", normalize: function(name, load, curName, curLoad, loader) { assert.equal(name, "./bar"); assert.equal(load.name, "pluginifier_builder_load/bar"); assert.equal(curName, "pluginifier_builder_load/main"); assert.equal(curLoad.name, "pluginifier_builder_load/main"); assert.equal(loader.main, "pluginifier_builder_load/main"); return name; }, ignore: function(moduleName, load){ switch(destCalls++) { case 0: assert.equal(load.name, "pluginifier_builder_load/main"); break; case 2: assert.equal(load.name, "pluginifier_builder_load/bar"); return true; break; default: assert.ok(false, "should not be called "+moduleName+"."+destCalls); break; } }, dest: function(moduleName, moduleData, load){ switch(destCalls++) { case 1: assert.equal(load.name, "pluginifier_builder_load/main"); break; default: assert.ok(false, "should not be called "+moduleName+"."+destCalls); break; } return __dirname+"/out/"+moduleName+".js" }, minify: false } } }).then(function(err){ done(); }, done); }); describe("helpers", function(){ beforeEach(function(done) { rmdir(path.join(__dirname, "pluginifier_builder_helpers", "node_modules"), function(error){ if(error){ return done(error); } rmdir(path.join(__dirname, "pluginifier_builder_helpers", "dist"), function(error){ if(error){ return done(error); } fs.copy( path.join(__dirname, "..", "node_modules","jquery"), path.join(__dirname, "pluginifier_builder_helpers", "node_modules", "jquery"), function(error){ if(error) { return done(error); } fs.copy( path.join(__dirname, "..", "node_modules","cssify"), path.join(__dirname, "pluginifier_builder_helpers", "node_modules", "cssify"), function(error){ if(error) { return done(error); } done(); } ); } ); }); }); }); it("+cjs", function(done){ this.timeout(10000); stealExport({ system: { config: __dirname+"/pluginifier_builder_helpers/package.json!npm" }, options: { quiet: true }, "outputs": { "+cjs": {} }, }).then(function(){ var browserify = require("browserify"); var b = browserify(); b.add(path.join(__dirname, "pluginifier_builder_helpers/browserify.js")); var out = fs.createWriteStream(path.join(__dirname, "pluginifier_builder_helpers/browserify-out.js")); b.bundle().pipe(out); out.on('finish', function(){ open("test/pluginifier_builder_helpers/browserify.html", function(browser, close) { find(browser,"WIDTH", function(width){ assert.equal(width, 200, "with of element"); close(); }, close); }, done); }); }, function(e) { done(e); }); }); it("+cjs with dest", function(done){ this.timeout(10000); stealExport({ system: { config: __dirname+"/pluginifier_builder_helpers/package.json!npm" }, options: { quiet: true }, "outputs": { "+cjs": {dest: __dirname+"/pluginifier_builder_helpers/cjs"} } }).then(function(){ var browserify = require("browserify"); var b = browserify(); b.add(path.join(__dirname, "pluginifier_builder_helpers/browserify-cjs.js")); var out = fs.createWriteStream(path.join(__dirname, "pluginifier_builder_helpers/browserify-out.js")); b.bundle().pipe(out); out.on('finish', function(){ open("test/pluginifier_builder_helpers/browserify.html", function(browser, close) { find(browser,"WIDTH", function(width){ assert.equal(width, 200, "with of element"); close(); }, close); }, done); }); }, done); }); // NOTICE: this test uses a modified version of the css plugin to better work // in HTMLDOM it("+amd", function(done){ this.timeout(10000); stealExport({ system: { config: __dirname+"/pluginifier_builder_helpers/package.json!npm" }, options: { quiet: true }, "outputs": { "+amd": {} } }).then(function(){ open("test/pluginifier_builder_helpers/amd.html", function(browser, close) { find(browser,"WIDTH", function(width){ assert.equal(width, 200, "with of element"); close(); }, close); }, done); }, done); }); it("+global-css +global-js", function(done){ this.timeout(10000); stealExport({ system: { config: __dirname+"/pluginifier_builder_helpers/package.json!npm" }, options: { quiet: true }, "outputs": { "+global-css": {}, "+global-js": { exports: {"jquery": "jQuery"} } } }).then(function(err){ open("test/pluginifier_builder_helpers/global.html", function(browser, close) { find(browser,"WIDTH", function(width){ assert.equal(width, 200, "width of element"); assert.ok(browser.window.TABS, "got tabs"); close(); }, close); }, done); }, done); }); it("+cjs +amd +global-css +global-js using Babel", function(done){ this.timeout(10000); stealExport({ system: { config: __dirname+"/pluginifier_builder_helpers/package.json!npm", transpiler: "babel" }, options: { quiet: true }, "outputs": { "+cjs": {}, "+amd": {}, "+global-js": { exports: { "jquery": "jQuery" } }, "+global-css": {} } }) .then(function() { open("test/pluginifier_builder_helpers/global.html", function(browser, close) { find(browser,"WIDTH", function(width){ assert.equal(width, 200, "width of element"); assert.ok(browser.window.TABS, "got tabs"); close(); }, close); }, done); }, done); }); it("ignore: false will not ignore node_modules for globals", function(done){ this.timeout(10000); stealExport({ system: { config: __dirname + "/pluginifier_builder_helpers/package.json!npm", meta: { jque