@onlabsorg/stilo
Version:
Command line tool for managing olojs document packages
497 lines (388 loc) • 19.4 kB
JavaScript
var expect = require("chai").expect;
var pathlib = require('path');
var fs = require('fs');
var rimraf = require('rimraf');
var Package = require('../lib/package');
var stilo = {
init: require('../lib/stilo-init'),
install: require('../lib/stilo-install'),
uninstall: require('../lib/stilo-uninstall'),
read: require('../lib/stilo-read'),
render: require('../lib/stilo-render'),
run: require('../lib/stilo-run')
}
require('isomorphic-fetch');
describe("stilo", () => {
describe("THe stilo package manager", () => {
describe('package.path', () => {
it("should contain the root path of the .stilo npm package", () => {
const packagePath = pathlib.join(__dirname, "../package-template");
const package = new Package(packagePath);
expect(package.path).to.equal(packagePath);
});
});
describe('package.resolvePath(subPath)', () => {
it("should return the absolute path of subPath, considering it relative to the package path", () => {
const packagePath = pathlib.join(__dirname, "../package-template");
const package = new Package(packagePath);
expect(package.resolvePath('/../test')).to.equal(__dirname);
});
});
describe('package.require(moduleId)', () => {
it("should import a return a module of the npm package", () => {
const packagePath = pathlib.join(__dirname, "../package-template");
const package = new Package(packagePath);
expect(package.require('./index')).to.equal(require('../package-template/index'));
});
});
describe('package.spawn(command, ...args)', () => {
it("should execute a shell command from the root directory of the npm package", async () => {
const packagePath = pathlib.join(__dirname, "../package-template");
const package = new Package(packagePath);
const fileContent = String(Math.random());
await package.spawn('cp', './package.json', '../test/package.json');
expect(require('./package.json')).to.deep.equal(require('../package-template/package.json'))
await package.spawn('rm', '../test/package.json');
expect(fs.existsSync(pathlib.join(__dirname, 'package.json'))).to.be.false;
});
});
});
describe("stilo.init()", () => {
it("should clone and install the package-template in the cwd", async function () {
this.timeout(60000);
// Status snapshot
const cwd = process.cwd();
// Run the command
process.chdir( pathlib.join(__dirname, 'test-repository') );
var packagePath = pathlib.join(__dirname, 'test-repository', Package.DIR_NAME);
await stilo.init({force: true});
const package = new Package(packagePath);
// Ensure cloned
expect(package.require('./package.json')).to.deep.equal(require('../package-template/package.json'))
// Ensure npm packages installed
expect(fs.existsSync(pathlib.join(packagePath, 'node_modules/@onlabsorg/olojs')));
// Restore original status
process.chdir(cwd);
});
it("should not overwrite an existing initialization", async function () {
this.timeout(60000);
// Status snapshot
const cwd = process.cwd();
// Run the command
process.chdir( pathlib.join(__dirname, 'test-repository') );
var packagePath = pathlib.join(__dirname, 'test-repository', Package.DIR_NAME);
var dummyFilePath = `${packagePath}/dummy-file.txt`;
fs.writeFileSync(dummyFilePath, "...", "utf8");
await stilo.init({force: false});
// Ensure that the existing package has not been replaced
expect(fs.existsSync(dummyFilePath)).to.be.true;
// Restore original status
process.chdir(cwd);
});
});
describe("stilo.read(docPath)", () => {
it("should fetch the doc mapped to docPath and print it to stdout ", async () => {
let stdout = "";
// Status snapshot
const cwd = process.cwd();
const stdout_write = process.stdout.write;
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository') );
process.stdout.write = text => {
stdout += text;
stdout_write.call(process.stdout, text);
}
await stilo.read('/dir/doc1');
expect(stdout).to.equal(fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.olo'), 'utf8') + '\n');
// Restore original status
process.chdir(cwd);
process.stdout.write = stdout_write;
});
it("should consider the path as relative to the cwd", async () => {
let stdout = "";
// Status snapshot
const cwd = process.cwd();
const stdout_write = process.stdout.write;
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository/dir') );
process.stdout.write = text => {
stdout += text;
stdout_write.call(process.stdout, text);
}
await stilo.read('doc1');
expect(stdout).to.equal(fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.olo'), 'utf8') + '\n');
// Restore original status
process.chdir(cwd);
process.stdout.write = stdout_write;
});
it("should not give access to the direcories above the repository root", async () => {
let stdout = "";
// Status snapshot
const cwd = process.cwd();
const stdout_write = process.stdout.write;
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository/dir') );
process.stdout.write = text => {
stdout += text;
stdout_write.call(process.stdout, text);
}
await stilo.read('../../../dir/doc1');
expect(stdout).to.equal(fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.olo'), 'utf8') + '\n');
// Restore original status
process.chdir(cwd);
process.stdout.write = stdout_write;
});
it("should treat absolute paths as relative to the repository root", async () => {
let stdout = "";
// Status snapshot
const cwd = process.cwd();
const stdout_write = process.stdout.write;
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository/dir') );
process.stdout.write = text => {
stdout += text;
stdout_write.call(process.stdout, text);
}
await stilo.read('/dir/doc1');
expect(stdout).to.equal(fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.olo'), 'utf8') + '\n');
// Restore original status
process.chdir(cwd);
process.stdout.write = stdout_write;
});
it("should treat URIs as absolute paths", async () => {
let stdout = "";
// Status snapshot
const cwd = process.cwd();
const stdout_write = process.stdout.write;
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository/dir') );
process.stdout.write = text => {
stdout += text;
stdout_write.call(process.stdout, text);
}
await stilo.read(`file:/${__dirname}/test-repository/dir/doc1`);
expect(stdout).to.equal(fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.olo'), 'utf8') + '\n');
// Restore original status
process.chdir(cwd);
process.stdout.write = stdout_write;
});
it("should output the source to the file path eventually passed with the --output option", async () => {
// Status snapshot
const cwd = process.cwd();
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository') );
await stilo.read('/dir/doc1', {output:"dir/doc1.txt"});
const outputFileContent = fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.txt'), 'utf8')
const sourceFileContent = fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.olo'), 'utf8')
expect(outputFileContent).to.equal(sourceFileContent);
// Restore original status
process.chdir(cwd);
});
});
describe("stilo.render(docPath)", () => {
it("should fetch the doc mapped to docPath and print its rendered text to stdout ", async () => {
let stdout = "";
// Status snapshot
const cwd = process.cwd();
const stdout_write = process.stdout.write;
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository') );
process.stdout.write = text => {
stdout += text;
stdout_write.call(process.stdout, text);
}
await stilo.render('/dir/doc1');
expect(stdout).to.equal("document @ home://dir/doc1\n\n");
// Restore original status
process.chdir(cwd);
process.stdout.write = stdout_write;
});
it("should consider the path as relative to the cwd", async () => {
let stdout = "";
// Status snapshot
const cwd = process.cwd();
const stdout_write = process.stdout.write;
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository/dir') );
process.stdout.write = text => {
stdout += text;
stdout_write.call(process.stdout, text);
}
await stilo.render('doc1');
expect(stdout).to.equal("document @ home://dir/doc1\n\n");
// Restore original status
process.chdir(cwd);
process.stdout.write = stdout_write;
});
it("should not give access to the direcories above the repository root", async () => {
let stdout = "";
// Status snapshot
const cwd = process.cwd();
const stdout_write = process.stdout.write;
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository/dir') );
process.stdout.write = text => {
stdout += text;
stdout_write.call(process.stdout, text);
}
await stilo.render('../../../dir/doc1');
expect(stdout).to.equal("document @ home://dir/doc1\n\n");
// Restore original status
process.chdir(cwd);
process.stdout.write = stdout_write;
});
it("should treat absolute paths as relative to the repository root", async () => {
let stdout = "";
// Status snapshot
const cwd = process.cwd();
const stdout_write = process.stdout.write;
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository/dir') );
process.stdout.write = text => {
stdout += text;
stdout_write.call(process.stdout, text);
}
await stilo.render('/dir/doc1');
expect(stdout).to.equal("document @ home://dir/doc1\n\n");
// Restore original status
process.chdir(cwd);
process.stdout.write = stdout_write;
});
it("should treat URIs as absolute paths", async () => {
let stdout = "";
// Status snapshot
const cwd = process.cwd();
const stdout_write = process.stdout.write;
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository/dir') );
process.stdout.write = text => {
stdout += text;
stdout_write.call(process.stdout, text);
}
var docPath = `${__dirname}/test-repository/dir/doc1`;
await stilo.render(`file:${docPath}`);
expect(stdout).to.equal(`document @ file:/${docPath}\n\n`);
// Restore original status
process.chdir(cwd);
process.stdout.write = stdout_write;
});
it("should output the rendered document to the file path eventually passed with the --output option", async () => {
// Status snapshot
const cwd = process.cwd();
// Run the commands
process.chdir( pathlib.join(__dirname, 'test-repository') );
await stilo.render('/dir/doc1', {output:"dir/doc1.txt"});
const outputFileContent = fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.txt'), 'utf8')
expect(outputFileContent).to.equal("document @ home://dir/doc1\n");
// Restore original status
process.chdir(cwd);
});
});
describe("stilo.install(packageId)", () => {
it("should install the given package and record it in the plugins list", async function () {
this.timeout(5000);
// Status snapshot
const cwd = process.cwd();
// Run the command
process.chdir( pathlib.join(__dirname, 'test-repository') );
const testPluginPath = pathlib.join(__dirname, 'test-plugin');
await stilo.install(testPluginPath);
// Ensure plugin installed
const package = new Package(pathlib.join(__dirname, 'test-repository', Package.DIR_NAME));
expect(package.require('test-plugin')).to.equal(require(testPluginPath));
// Ensure plugin registered
const packageJsonPath = pathlib.join(__dirname, 'test-repository/.stilo/package.json');
const packageJsonText = fs.readFileSync(packageJsonPath, 'utf8');
const packageJson = JSON.parse(packageJsonText)
expect(packageJson.stilo.plugins).to.deep.equal(['test-plugin']);
// Ensure plugin routes added to the store
expect(await stilo.read('/test/route/path/to/doc')).to.equal("test plugin: read /path/to/doc");
expect(await stilo.read('ppp://path/to/doc')).to.equal("test plugin: read ppp://path/to/doc");
// Restore original status
process.chdir(cwd);
});
});
describe("stilo.run(commandName, ...args)", () => {
it("should execute the plugin command named 'commandName'", async () => {
// Status snapshot
const cwd = process.cwd();
// Run the command
process.chdir( pathlib.join(__dirname, 'test-repository/dir') );
const retval = await stilo.run('test-command', {x:1, y:2}, 10, 20, 30);
// Ensure command ran
expect(retval.args).to.deep.equal([10,20,30]);
expect(retval.options).to.deep.equal({x:1, y:2});
expect(await retval.stilo.store.read('/dir/doc1')).to.equal(fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.olo'), 'utf8'));
expect(retval.stilo.rootPath).to.equal(pathlib.join(__dirname, 'test-repository'));
expect(retval.stilo.cwp).to.equal('/dir/');
// Restore original status
process.chdir(cwd);
});
});
describe("stilo.uninstall(packageId)", () => {
it("should uninstall the given package and remove it from the plugins list", async function () {
this.timeout(5000);
// Status snapshot
const cwd = process.cwd();
// Run the command
process.chdir( pathlib.join(__dirname, 'test-repository') );
await stilo.uninstall('test-plugin');
// Ensure plugin uninstalled
const package = new Package(pathlib.join(__dirname, 'test-repository', Package.DIR_NAME));
try {
const testPlugin = require('test-plugin');
throw new Error("It did not throw");
} catch (error) {
expect(error.message.indexOf("Cannot find module 'test-plugin'")).to.equal(0);
}
// Ensure plugin unregistered
const packageJsonPath = pathlib.join(__dirname, 'test-repository/.stilo/package.json');
const packageJsonText = fs.readFileSync(packageJsonPath, 'utf8');
const packageJson = JSON.parse(packageJsonText)
expect(packageJson.stilo.plugins).to.deep.equal([]);
// Restore original status
process.chdir(cwd);
});
});
describe("stilo.run('http-server', path, {port})", () => {
it("should start serving the store over HTTP", async () => {
// Status snapshot
const cwd = process.cwd();
// Run the command
process.chdir( pathlib.join(__dirname, 'test-repository') );
const server = await stilo.run("http-server", {port:8011}, '/');
// Ensure the server is running
const req = await fetch('http://localhost:8011/dir/doc1');
expect(await req.text()).to.equal(fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.olo'), 'utf8'));
// Restore original status
process.chdir(cwd);
server.close();
});
it("should serve a substore if a non-root path is passed", async () => {
// Status snapshot
const cwd = process.cwd();
// Run the command
process.chdir( pathlib.join(__dirname, 'test-repository') );
const server = await stilo.run("http-server", {port:8011}, '/dir');
// Ensure the server is running
const req = await fetch('http://localhost:8011/doc1');
expect(await req.text()).to.equal(fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.olo'), 'utf8'));
// Restore original status
process.chdir(cwd);
server.close();
});
it("should resolve non-absolite path as relative to the cwd", async () => {
// Status snapshot
const cwd = process.cwd();
// Run the command
process.chdir( pathlib.join(__dirname, 'test-repository/dir') );
const server = await stilo.run("http-server", {port:8011}, './');
// Ensure the server is running
const req = await fetch('http://localhost:8011/doc1');
expect(await req.text()).to.equal(fs.readFileSync(pathlib.join(__dirname, 'test-repository/dir/doc1.olo'), 'utf8'));
// Restore original status
process.chdir(cwd);
server.close();
});
});
});