UNPKG

faucet-pipeline-js

Version:

JavaScript module bundling for faucet-pipeline

426 lines (359 loc) 11.4 kB
/* global describe, it, beforeEach, afterEach */ "use strict"; let { MockAssetManager, makeBundle, FIXTURES_DIR } = require("./util"); let faucetJS = require("../../lib").plugin; let path = require("path"); let assert = require("assert"); let DEFAULT_OPTIONS = { browsers: {} }; describe("bundling", _ => { let { exit } = process; beforeEach(() => { process.exit = code => { throw new Error(`exit ${code}`); }; }); afterEach(() => { process.exit = exit; }); it("should verify configuration", () => { let config = [{}]; let assetManager = new MockAssetManager(FIXTURES_DIR); let fn = _ => faucetJS(config, assetManager, DEFAULT_OPTIONS)(); assert.throws(fn, /exit 1/); // aborts with "missing `source` configuration" config[0].source = "./src/index.js"; assert.throws(fn, /exit 1/); // aborts with "missing `target` configuration" }); it("should combine ES6 modules into a bundle", () => { let config = [{ source: "./src/index.js", target: "./dist/bundle.js" }]; let assetManager = new MockAssetManager(FIXTURES_DIR); return faucetJS(config, assetManager, DEFAULT_OPTIONS)(). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` var util = "UTIL"; console.log(\`[…] $\{util}\`); // eslint-disable-line no-console `) }]); }); }); it("should optionally transpile ES6 to ES5", () => { let config = [{ source: "./src/index.js", target: "./dist/bundle.js", esnext: true }]; let assetManager = new MockAssetManager(FIXTURES_DIR); return faucetJS(config, assetManager, DEFAULT_OPTIONS)(). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` var util = "UTIL"; console.log("[\\u2026] ".concat(util)); // eslint-disable-line no-console `) }]); }); }); it("should support skipping transpilation for select packages", () => { let cwd = process.cwd(); process.chdir(FIXTURES_DIR); // XXX: should not be test-specific!? let restore = _ => process.chdir(cwd); let config = [{ source: "./src/alt2.js", target: "./dist/bundle.js", esnext: { exclude: ["my-lib"] } }]; let assetManager = new MockAssetManager(FIXTURES_DIR); return faucetJS(config, assetManager, DEFAULT_OPTIONS)(). then(restore, restore). // XXX: hacky then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), /* eslint-disable max-len */ content: makeBundle(` function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var dist = {exports: {}}; /* eslint-disable */ var hasRequiredDist; function requireDist () { if (hasRequiredDist) return dist.exports; hasRequiredDist = 1; (function (module) { (function(window) { var MYLIB = "MY-LIB"; { module.exports = MYLIB; } }());$$$WHITESPACE$$$ } (dist)); return dist.exports; } var distExports = requireDist(); var MYLIB = /*@__PURE__*/getDefaultExportFromCjs(distExports); console.log("[\\u2026] ".concat(MYLIB)); // eslint-disable-line no-console `). // fugly workaround for trailing whitespace being generated replace("$$$WHITESPACE$$$", " ") /* eslint-enable max-len */ }]); }); }); it("should support customizing bundle's API", () => { let config = [{ source: "./src/lib.js", target: "./dist/bundle.js", exports: "MYLIB" }]; let assetManager = new MockAssetManager(FIXTURES_DIR); return faucetJS(config, assetManager, DEFAULT_OPTIONS)(). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` var util = "UTIL"; var lib = msg => { console.log(\`[…] $\{util} $\{msg}\`); // eslint-disable-line no-console }; export { lib as default }; `) }]); }); }); it("should support customizing bundle format", () => { let config = [{ source: "./src/lib.js", target: "./dist/bundle.js", format: "amd" }]; let assetManager = new MockAssetManager(FIXTURES_DIR); return faucetJS(config, assetManager, DEFAULT_OPTIONS)(). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` define((function () { 'use strict'; var util = "UTIL"; var lib = msg => { console.log(\`[…] $\{util} $\{msg}\`); // eslint-disable-line no-console }; return lib; })); `) }]); }); }); it("should support importing third-party packages", () => { let config = [{ source: "./src/alt.js", target: "./dist/bundle.js" }]; let assetManager = new MockAssetManager(FIXTURES_DIR); return faucetJS(config, assetManager, DEFAULT_OPTIONS)(). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` var MYLIB = "MY-LIB"; console.log(\`[…] $\{MYLIB}\`); // eslint-disable-line no-console `) }]); }); }); it("should support excluding module/package references", () => { let config = [{ source: "./src/alt.js", target: "./dist/bundle.js", externals: { "my-lib": "MYLIB" } }]; let assetManager = new MockAssetManager(FIXTURES_DIR); return faucetJS(config, assetManager, DEFAULT_OPTIONS)(). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` import MYLIB from 'my-lib'; console.log(\`[…] $\{MYLIB}\`); // eslint-disable-line no-console `) }]); }); }); it("should take into account Browserslist while transpiling", () => { let config = [{ source: "./src/index.js", target: "./dist/bundle.js", esnext: true }]; let assetManager = new MockAssetManager(FIXTURES_DIR); let browsers = { defaults: ["Chrome 63"] }; return faucetJS(config, assetManager, { browsers })(). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` var util = "UTIL"; console.log(\`[…] $\{util}\`); // eslint-disable-line no-console `) }]); }); }); it("should allow suppressing Browserslist auto-config while transpiling", () => { let config = [{ source: "./src/index.js", target: "./dist/bundle.js", esnext: { browserslist: false } }]; let assetManager = new MockAssetManager(FIXTURES_DIR); let browsers = { defaults: ["Chrome 63"] }; return faucetJS(config, assetManager, { browsers })(). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` var util = "UTIL"; console.log("[\\u2026] ".concat(util)); // eslint-disable-line no-console `) }]); }); }); it("should allow specifying an alternative Browserslist group", () => { let config = [{ source: "./src/index.js", target: "./dist/bundle.js", esnext: { browserslist: "modern" } }]; let assetManager = new MockAssetManager(FIXTURES_DIR); let browsers = { defaults: ["IE 11"], modern: ["Chrome 63"] }; return faucetJS(config, assetManager, { browsers })(). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` var util = "UTIL"; console.log(\`[…] $\{util}\`); // eslint-disable-line no-console `) }]); }); }); it("should optionally compact bundle", () => { let config = [{ source: "./src/multiline.js", target: "./dist/bundle.js" }]; let assetManager = new MockAssetManager(FIXTURES_DIR); let options = { browsers: {}, compact: true }; return faucetJS(config, assetManager, options)(). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(`let txt = \`foo bar\`; console.log(\`[…] $\{txt}\`); `, { compact: true }) }]); config[0].esnext = true; assetManager = new MockAssetManager(FIXTURES_DIR); return faucetJS(config, assetManager, options)(); }). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` var txt = "foo\\n\\nbar"; console.log("[\\u2026] ".concat(txt)); `, { compact: true }) }]); config[0].compact = false; // overrides global option assetManager = new MockAssetManager(FIXTURES_DIR); return faucetJS(config, assetManager, options)(); }). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` var txt = "foo\\n\\nbar"; console.log("[\\u2026] ".concat(txt)); // eslint-disable-line no-console `) }]); }); }); it("should balk at non-relative paths for target", () => { let assetManager = new MockAssetManager(FIXTURES_DIR); let entryPoint = "src/index.js"; let target = "dist/bundle.js"; let compile = (source, target) => faucetJS([{ source, target }], assetManager, DEFAULT_OPTIONS)(); let fn = _ => compile(`./${entryPoint}`, target); assert.throws(fn, /exit 1/); // aborts with "path must be relative" // non-relative path is acceptable for entry point, but a suitable // package path does not exist fn = _ => compile("dummy/src/does_not_exist.js", `./${target}`); assert.throws(fn, /exit 1/); // aborts with "could not resolve" return compile(`./${entryPoint}`, `./${target}`); }); it("should support Node resolution algorithm for entry point", () => { let entryPoint = "dummy/src/index.js"; let target = "./dist/bundle.js"; let assetManager = new MockAssetManager(FIXTURES_DIR); let compile = (source, target) => faucetJS([{ source, target }], assetManager, DEFAULT_OPTIONS)(); return compile(entryPoint, target). then(_ => { assetManager.assertWrites([{ filepath: path.resolve(FIXTURES_DIR, "./dist/bundle.js"), content: makeBundle(` var util = "DUMMY-UTIL"; console.log(\`[DUMMY] $\{util}\`); // eslint-disable-line no-console `) }]); let fn = _ => compile("dummy/src/does_not_exist.js", target); assert.throws(fn, /exit 1/); // aborts with "could not resolve" fn = _ => compile(entryPoint, "dist/bundle.js"); assert.throws(fn, /exit 1/); // aborts with "path must be relative" }); }); it("should build when the provided path is part of the bundle", () => { let config = [{ source: "./src/index.js", target: "./dist/bundle.js" }]; let assetManager = new MockAssetManager(FIXTURES_DIR); let buildJS = faucetJS(config, assetManager, DEFAULT_OPTIONS); let relevantModule = path.join(FIXTURES_DIR, "src/util.js"); return buildJS(). then(_ => buildJS([relevantModule])). then(_ => { assetManager.assertWriteCount(2); }); }); it("should not build when the provided path is not part of the bundle", () => { let config = [{ source: "./src/index.js", target: "./dist/bundle.js" }]; let assetManager = new MockAssetManager(FIXTURES_DIR); let buildJS = faucetJS(config, assetManager, DEFAULT_OPTIONS); let unusedModule = path.join(FIXTURES_DIR, "src/alt.js"); return buildJS(). then(_ => buildJS([unusedModule])). then(_ => { assetManager.assertWriteCount(1); }); }); });