fuse-box
Version:
Fuse-Box a bundler that does it right
137 lines (124 loc) • 4.72 kB
text/typescript
import * as path from "path";
import * as fs from "fs-extra";
import * as appRoot from "app-root-path";
import { FuseBox } from "../../index";
import { BundleProducer } from "../../core/BundleProducer";
import { fork } from "child_process";
const jsdom = require("jsdom");
function createTestFolders(customFolder: string): { root, homeDir, dist } {
let root = path.join(appRoot.path, ".fusebox", "tests", new Date().getTime().toString() + "_" + Math.random());
if (customFolder) {
root = path.join(appRoot.path, customFolder);
}
fs.ensureDirSync(root);
const homeDir = path.join(root, "src");
fs.ensureDirSync(homeDir);
const output = path.join(root, "dist");
fs.ensureDirSync(output);
return {
root: root,
homeDir: homeDir,
dist: output
};
}
function createFiles(dir: string, files: any) {
for (let name in files) {
const content = files[name];
const filePath = path.join(dir, name)
fs.ensureDirSync(path.dirname(filePath));
fs.writeFileSync(filePath, content);
}
}
export class FuseTestEnv {
public fuse: FuseBox;
public window: any;
public producer: BundleProducer;
public dirs: { root, homeDir, dist };
constructor(config: any) {
this.dirs = createTestFolders(config.testFolder);
const basicConfig = {
homeDir: this.dirs.homeDir,
log: false,
experimentalFeatures: true,
output: `${this.dirs.dist}/$name.js`
}
config.project = config.project || {};
createFiles(this.dirs.homeDir, config.project.files);
if (config.project.distFiles) {
createFiles(this.dirs.dist, config.project.distFiles);
}
config = Object.assign(basicConfig, config.project || {});
this.fuse = FuseBox.init(config);
}
public simple(instructions: string = "> index.ts"): Promise<FuseTestEnv> {
this.fuse.bundle("app")
.instructions(instructions);
return this.fuse.run().then(producer => {
this.producer = producer;
return this;
});
}
public config(fn: { (fuse: FuseBox): any }): Promise<FuseTestEnv> {
return Promise.resolve(fn(this.fuse)).then(() => this.fuse.run()).then(producer => {
this.producer = producer;
return this;
});
}
public server(message, fn: { (response): any }): Promise<FuseTestEnv> {
return new Promise((resolve, reject) => {
const scripts = [];
const bundles = this.producer.sortBundles();
bundles.forEach(bundle => {
if (bundle.webIndexed) {
let contents = fs.readFileSync(bundle.context.output.lastPrimaryOutput.path).toString();
scripts.push(contents);
}
});
scripts.push(message);
const forkedFile = path.join(this.dirs.dist, "__isolated_fork.js");
fs.writeFileSync(forkedFile, scripts.join("\n"));
const proc = fork(forkedFile);
proc.on('message', (m) => {
return resolve(fn(m));
});
proc.on('data', (data) => {
console.log(`stdout: ${data}`);
});
});
}
public browser(fn: { (window: any, test: FuseTestEnv): any }): Promise<FuseTestEnv> {
const scripts = [path.join(appRoot.path, "src/tests/stubs/DummyXMLHttpRequest.js")];
const bundles = this.producer.sortBundles();
bundles.forEach(bundle => {
if (bundle.webIndexed) {
scripts.push(bundle.context.output.lastPrimaryOutput.path);
}
});
return new Promise((resolve, reject) => {
jsdom.env({
html: `<html>
<head>
</head><body></body></html>
`,
scripts: scripts,
//virtualConsole: jsdom.createVirtualConsole().sendTo(console),
done: (err, window) => {
window.__ajax = (url, fn) => {
const target = path.join(this.dirs.dist, url);
if (fs.existsSync(target)) {
return fn(200, fs.readFileSync(target).toString());
}
return fn(404, "Not found");
}
if (err) {
return reject(err);
}
return resolve(fn(window, this));
}
});
});
}
public static create(config) {
return new FuseTestEnv(config);
}
}