<commit_before>const ava = require('ava');
const { resolve } = require('path');
const tsubaki = require('tsubaki');
const mock = require('mock-fs');
const fs = tsubaki.promisifyAll(require('fs'));
const nextra = require('../src/index');

const dir = resolve(__dirname, 'test');
const files = {
	copy: resolve(dir, 'copy.txt'),
	ensureDir: resolve(dir, 'ensureDir'),
	createFile: resolve(dir, 'createFile'),
	createSymlink: {
		src: resolve(dir, 'createSymlinkSrc'),
		dest: resolve(dir, 'createSymlinkDest')
	},
	createlink: {
		src: resolve(dir, 'createlinkSrc.txt'),
		dest: resolve(dir, 'createlinkDest.txt')
	},
	emptyDir: {
		empty: resolve(dir, 'empty'),
		full: resolve(dir, 'full')
	},
	readJSON: resolve(dir, 'readJSON.json'),
	pathExists: {
		dir: resolve(dir, 'path'),
		file: resolve(dir, 'path.txt')
	}
};

ava.before(test => {
	mock({
		[files.copy]: '',
		[files.ensureDir]: {},
		[files.createFile]: '',
		[files.createSymlink.src]: mock.symlink({ path: files.createSymlink.dest }),
		[files.createlink.src]: 'linked',
		[files.createlink.dest]: 'linked',
		[files.emptyDir.empty]: {},
		[files.emptyDir.full]: { 'file.txt': '' },
		[files.readJSON]: '{ "validate": true }',
		[files.pathExists.dir]: {},
		[files.pathExists.file]: ''
	});
	test.pass();
});

ava.after.always(test => {
	mock.restore();
	test.pass();
});

// Copy

ava('copy', async test => {
	const copy = resolve(dir, 'copied');
	await nextra.copy(files.copy, copy);

	const stats = await fs.statAsync(copy);
	test.true(stats.isFile());
});

// createFile

ava('createFile (pre-existing)', async test => {
	await nextra.createFile(files.createFile);

	const stats = await fs.statAsync(files.createFile);
	test.true(stats.isFile());
});

ava('createFile (new)', async test => {
	const file = resolve(dir, 'createFileNew');
	await nextra.createFile(file);

	const stats = await fs.statAsync(file);
	test.true(stats.isFile());
});

ava('createFile (new recursive)', async test => {
	const file = resolve(dir, 'createFileNew2', 'createFileNew3');
	await nextra.createFile(file);

	const stats = await fs.statAsync(file);
	test.true(stats.isFile());
});

// createFileAtomic

ava('createFileAtomic (pre-existing)', async test => {
	await nextra.createFileAtomic(files.createFile);

	const stats = await fs.statAsync(files.createFile);
	test.true(stats.isFile());
});

ava('createFileAtomic (new)', async test => {
	const file = resolve(dir, 'createFileNew');
	await nextra.createFileAtomic(file);

	const stats = await fs.statAsync(file);
	test.true(stats.isFile());
});

ava('createFileAtomic (new recursive)', async test => {
	const file = resolve(dir, 'createFileNew2', 'createFileNew3');
	await nextra.createFileAtomic(file);

	const stats = await fs.statAsync(file);
	test.true(stats.isFile());
});

// createLink

ava('createLink (pre-existing)', async test => {
	await nextra.createLink(files.createlink.src, files.createlink.dest);

	const stats = await fs.statAsync(files.createlink.dest);
	test.true(stats.isFile());
});

ava('createLink (new)', async test => {
	const newDir = resolve(dir, 'createLinkNew.txt');
	await nextra.createLink(files.createlink.src, newDir);

	const stats = await fs.statAsync(newDir);
	test.true(stats.isFile());
});

ava('createLink (new recursive)', async test => {
	const deepDir = resolve(dir, 'createLinkNew2', 'createLinkNew3.txt');
	await nextra.createLink(files.createlink.src, deepDir);

	const stats = await fs.statAsync(deepDir);
	test.true(stats.isFile());
});

// createLinkAtomic

ava('createLinkAtomic (pre-existing)', async test => {
	await nextra.createLinkAtomic(files.createlink.src, files.createlink.dest);

	const stats = await fs.statAsync(files.createlink.dest);
	test.true(stats.isFile());
});

ava('createLinkAtomic (new)', async test => {
	const newDir = resolve(dir, 'createLinkNew.txt');
	await nextra.createLinkAtomic(files.createlink.src, newDir);

	const stats = await fs.statAsync(newDir);
	test.true(stats.isFile());
});

ava('createLinkAtomic (new recursive)', async test => {
	const deepDir = resolve(dir, 'createLinkNew2', 'createLinkNew3.txt');
	await nextra.createLinkAtomic(files.createlink.src, deepDir);

	const stats = await fs.statAsync(deepDir);
	test.true(stats.isFile());
});

// createSymlink

ava('createSymlink (pre-existing)', async test => {
	await nextra.createSymlink(files.createSymlink.src, files.createSymlink.dest);

	const stats = await fs.lstatAsync(files.createSymlink.src);
	test.true(stats.isSymbolicLink());
});

ava('createSymlink (new)', async test => {
	const newDir = resolve(dir, 'createSymlinkNew');
	await nextra.createSymlink(files.createSymlink.src, newDir);

	const stats = await fs.lstatAsync(files.createSymlink.src);
	test.true(stats.isSymbolicLink());
});

ava('createSymlink (new recursive)', async test => {
	const deepDir = resolve(dir, 'createSymlinkNew2', 'createSymlinkNew3');
	await nextra.createSymlink(files.createSymlink.src, deepDir);

	const stats = await fs.lstatAsync(files.createSymlink.src);
	test.true(stats.isSymbolicLink());
});

// createSymlinkAtomic

ava('createSymlinkAtomic (pre-existing)', async test => {
	await nextra.createLinkAtomic(files.createSymlink.src, files.createSymlink.dest);

	const stats = await fs.lstatAsync(files.createSymlink.dest);
	test.true(stats.isSymbolicLink());
});

ava('createSymlinkAtomic (new)', async test => {
	const newDir = resolve(dir, 'createSymlinkNew');
	await nextra.createLinkAtomic(files.createSymlink.src, newDir);

	const stats = await fs.lstatAsync(newDir);
	test.true(stats.isSymbolicLink());
});

ava('createSymlinkAtomic (new recursive)', async test => {
	const deepDir = resolve(dir, 'createSymlinkNew2', 'createSymlinkNew3');
	await nextra.createLinkAtomic(files.createSymlink.src, deepDir);

	const stats = await fs.lstatAsync(deepDir);
	test.true(stats.isSymbolicLink());
});

// emptyDir

ava('emptyDir (empty)', async test => {
	await nextra.emptyDir(files.emptyDir.empty);

	const contents = await fs.readdirAsync(files.emptyDir.empty);
	test.true(contents.length === 0);
});

ava('emptyDir (full)', async test => {
	await nextra.emptyDir(files.emptyDir.full);

	const contents = await fs.readdirAsync(files.emptyDir.full);
	test.true(contents.length === 0);
});

// ensureDir

ava('ensureDir (pre-existing)', async test => {
	await nextra.ensureDir(files.ensureDir);

	const stats = await fs.statAsync(files.ensureDir);
	test.true(stats.isDirectory());
});

ava('ensureDir (new)', async test => {
	const newDir = resolve(dir, 'ensureDirNew');
	await nextra.ensureDir(newDir);

	const stats = await fs.statAsync(newDir);
	test.true(stats.isDirectory());
});

ava('ensureDir (new recursive)', async test => {
	const deepDir = resolve(dir, 'ensureDirNew2', 'ensureDirNew3');
	await nextra.ensureDir(deepDir);

	const stats = await fs.statAsync(deepDir);
	test.true(stats.isDirectory());
});

// linkAtomic

ava('linkAtomic', async test => {
	const newFile = resolve(dir, 'linkAtomicNew.txt');
	await nextra.linkAtomic(files.createlink.src, newFile);

	const stats = await fs.statAsync(newFile);
	test.true(stats.isFile());
});

// move

ava('move', async test => {
	test.plan(2);
	const move = resolve(dir, 'moved');
	await nextra.move(files.copy, move);

	test.throws(fs.statAsync(files.copy));
	test.notThrows(fs.statAsync(move));
});

// outputFile

ava('outputFile (pre-existing)', async test => {
	await nextra.outputFile(files.createFile, 'pass');

	test.is(await fs.readFileAsync(files.createFile, 'utf8'), 'pass');
});

ava('outputFile (new)', async test => {
	const newDir = resolve(dir, 'outputFileNew');
	await nextra.outputFile(newDir, 'pass');

	test.is(await fs.readFileAsync(newDir, 'utf8'), 'pass');
});

ava('outputFile (new recursive)', async test => {
	const deepDir = resolve(dir, 'outputFileNew2', 'outputFileNew3');
	await nextra.outputFile(deepDir, 'pass');

	test.is(await fs.readFileAsync(deepDir, 'utf8'), 'pass');
});

// outputFileAtomic

ava('outputFileAtomic (pre-existing)', async test => {
	await nextra.outputFileAtomic(files.createFile, 'pass');

	test.is(await fs.readFileAsync(files.createFile, 'utf8'), 'pass');
});

ava('outputFileAtomic (new)', async test => {
	const newDir = resolve(dir, 'outputFileNew');
	await nextra.outputFileAtomic(newDir, 'pass');

	test.is(await fs.readFileAsync(newDir, 'utf8'), 'pass');
});

ava('outputFileAtomic (new recursive)', async test => {
	const deepDir = resolve(dir, 'outputFileNew2', 'outputFileNew3');
	await nextra.outputFileAtomic(deepDir, 'pass');

	test.is(await fs.readFileAsync(deepDir, 'utf8'), 'pass');
});

// outputJSON

ava('outputJSON (pre-existing)', async test => {
	const obj = { test: 'passed' };
	await nextra.outputJSON(files.createFile, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(files.createFile, 'utf8')), obj);
});

ava('outputJSON (new)', async test => {
	const newDir = resolve(dir, 'outputJSONNew');
	const obj = { test: 'passed' };
	await nextra.outputJSON(newDir, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(newDir, 'utf8')), obj);
});

ava('outputJSON (new recursive)', async test => {
	const deepDir = resolve(dir, 'outputJSONNew2', 'outputJSONNew3');
	const obj = { test: 'passed' };
	await nextra.outputJSON(deepDir, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(deepDir, 'utf8')), obj);
});

// outputJSONAtomic

ava('outputJSONAtomic (pre-existing)', async test => {
	const obj = { test: 'passed' };
	await nextra.outputJSONAtomic(files.createFile, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(files.createFile, 'utf8')), obj);
});

ava('outputJSONAtomic (new)', async test => {
	const newDir = resolve(dir, 'outputJSONNew');
	const obj = { test: 'passed' };
	await nextra.outputJSONAtomic(newDir, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(newDir, 'utf8')), obj);
});

ava('outputJSONAtomic (new recursive)', async test => {
	const deepDir = resolve(dir, 'outputJSONNew2', 'outputJSONNew3');
	const obj = { test: 'passed' };
	await nextra.outputJSONAtomic(deepDir, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(deepDir, 'utf8')), obj);
});

// pathExists

ava('pathExists (dir true)', async test => {
	test.true(await nextra.pathExists(files.pathExists.dir));
});

ava('pathExists (file true)', async test => {
	test.true(await nextra.pathExists(files.pathExists.file));
});

ava('pathExists (dir false)', async test => {
	const noExist = resolve(dir, 'pathDoesntExist');
	test.false(await nextra.pathExists(noExist));
});

ava('pathExists (file false)', async test => {
	const noExist = resolve(dir, 'pathDoesntExist.txt');
	test.false(await nextra.pathExists(noExist));
});

// readJSON

ava('readJSON', async test => {
	const readJSON = await nextra.readJSON(files.readJSON);
	test.true(readJSON.validate);
});

// remove

ava('remove', async test => {
	const file = resolve(files.emptyDir.full, 'file.txt');
	await nextra.remove(file);

	test.throws(fs.statAsync(file));
});

// symlinkAtomic

ava('symlinkAtomic', async test => {
	const file = resolve(dir, 'file.txt');
	await nextra.symlinkAtomic(files.createSymlink.src, file);

	const stats = await fs.lstatAsync(file);
	test.true(stats.isSymbolicLink());
});

// writeFileAtomic

ava('writeFileAtomic', async test => {
	const file = resolve(dir, 'file.txt');
	const data = 'passed';
	await nextra.writeFileAtomic(file, data);

	test.is(await fs.readFileAsync(file, 'utf8'), data);
});

// writeJSON

ava('writeJSON', async test => {
	const file = resolve(dir, 'file.json');
	const obj = { test: 'passed' };
	await nextra.writeJSON(file, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(file, 'utf8')), obj);
});

// writeJSONAtomic

ava('writeJSONAtomic', async test => {
	const file = resolve(dir, 'file.json');
	const obj = { test: 'passed' };
	await nextra.writeJSONAtomic(file, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(file, 'utf8')), obj);
});
<commit_msg>Fix build with test skips<commit_after>const ava = require('ava');
const { resolve } = require('path');
const tsubaki = require('tsubaki');
const mock = require('mock-fs');
const fs = tsubaki.promisifyAll(require('fs'));
const nextra = require('../src/index');

const dir = resolve(__dirname, 'test');
const files = {
	copy: resolve(dir, 'copy.txt'),
	ensureDir: resolve(dir, 'ensureDir'),
	createFile: resolve(dir, 'createFile'),
	createSymlink: {
		src: resolve(dir, 'createSymlinkSrc'),
		dest: resolve(dir, 'createSymlinkDest')
	},
	createlink: {
		src: resolve(dir, 'createlinkSrc.txt'),
		dest: resolve(dir, 'createlinkDest.txt')
	},
	emptyDir: {
		empty: resolve(dir, 'empty'),
		full: resolve(dir, 'full')
	},
	readJSON: resolve(dir, 'readJSON.json'),
	pathExists: {
		dir: resolve(dir, 'path'),
		file: resolve(dir, 'path.txt')
	}
};

ava.before(test => {
	mock({
		[files.copy]: '',
		[files.ensureDir]: {},
		[files.createFile]: '',
		[files.createSymlink.src]: mock.symlink({ path: files.createSymlink.dest }),
		[files.createlink.src]: 'linked',
		[files.createlink.dest]: 'linked',
		[files.emptyDir.empty]: {},
		[files.emptyDir.full]: { 'file.txt': '' },
		[files.readJSON]: '{ "validate": true }',
		[files.pathExists.dir]: {},
		[files.pathExists.file]: ''
	});
	test.pass();
});

ava.after.always(test => {
	mock.restore();
	test.pass();
});

// Copy

ava('copy', async test => {
	const copy = resolve(dir, 'copied');
	await nextra.copy(files.copy, copy);

	const stats = await fs.statAsync(copy);
	test.true(stats.isFile());
});

// createFile

ava('createFile (pre-existing)', async test => {
	await nextra.createFile(files.createFile);

	const stats = await fs.statAsync(files.createFile);
	test.true(stats.isFile());
});

ava('createFile (new)', async test => {
	const file = resolve(dir, 'createFileNew');
	await nextra.createFile(file);

	const stats = await fs.statAsync(file);
	test.true(stats.isFile());
});

ava('createFile (new recursive)', async test => {
	const file = resolve(dir, 'createFileNew2', 'createFileNew3');
	await nextra.createFile(file);

	const stats = await fs.statAsync(file);
	test.true(stats.isFile());
});

// createFileAtomic

ava('createFileAtomic (pre-existing)', async test => {
	await nextra.createFileAtomic(files.createFile);

	const stats = await fs.statAsync(files.createFile);
	test.true(stats.isFile());
});

ava('createFileAtomic (new)', async test => {
	const file = resolve(dir, 'createFileNew');
	await nextra.createFileAtomic(file);

	const stats = await fs.statAsync(file);
	test.true(stats.isFile());
});

ava('createFileAtomic (new recursive)', async test => {
	const file = resolve(dir, 'createFileNew2', 'createFileNew3');
	await nextra.createFileAtomic(file);

	const stats = await fs.statAsync(file);
	test.true(stats.isFile());
});

// createLink

ava('createLink (pre-existing)', async test => {
	await nextra.createLink(files.createlink.src, files.createlink.dest);

	const stats = await fs.statAsync(files.createlink.dest);
	test.true(stats.isFile());
});

ava('createLink (new)', async test => {
	const newDir = resolve(dir, 'createLinkNew.txt');
	await nextra.createLink(files.createlink.src, newDir);

	const stats = await fs.statAsync(newDir);
	test.true(stats.isFile());
});

ava('createLink (new recursive)', async test => {
	const deepDir = resolve(dir, 'createLinkNew2', 'createLinkNew3.txt');
	await nextra.createLink(files.createlink.src, deepDir);

	const stats = await fs.statAsync(deepDir);
	test.true(stats.isFile());
});

// createLinkAtomic

ava('createLinkAtomic (pre-existing)', async test => {
	await nextra.createLinkAtomic(files.createlink.src, files.createlink.dest);

	const stats = await fs.statAsync(files.createlink.dest);
	test.true(stats.isFile());
});

ava('createLinkAtomic (new)', async test => {
	const newDir = resolve(dir, 'createLinkNew.txt');
	await nextra.createLinkAtomic(files.createlink.src, newDir);

	const stats = await fs.statAsync(newDir);
	test.true(stats.isFile());
});

ava('createLinkAtomic (new recursive)', async test => {
	const deepDir = resolve(dir, 'createLinkNew2', 'createLinkNew3.txt');
	await nextra.createLinkAtomic(files.createlink.src, deepDir);

	const stats = await fs.statAsync(deepDir);
	test.true(stats.isFile());
});

// createSymlink

ava('createSymlink (pre-existing)', async test => {
	await nextra.createSymlink(files.createSymlink.src, files.createSymlink.dest);

	const stats = await fs.lstatAsync(files.createSymlink.src);
	test.true(stats.isSymbolicLink());
});

ava('createSymlink (new)', async test => {
	const newDir = resolve(dir, 'createSymlinkNew');
	await nextra.createSymlink(files.createSymlink.src, newDir);

	const stats = await fs.lstatAsync(files.createSymlink.src);
	test.true(stats.isSymbolicLink());
});

ava('createSymlink (new recursive)', async test => {
	const deepDir = resolve(dir, 'createSymlinkNew2', 'createSymlinkNew3');
	await nextra.createSymlink(files.createSymlink.src, deepDir);

	const stats = await fs.lstatAsync(files.createSymlink.src);
	test.true(stats.isSymbolicLink());
});

// createSymlinkAtomic

ava('createSymlinkAtomic (pre-existing)', async test => {
	await nextra.createLinkAtomic(files.createSymlink.src, files.createSymlink.dest);

	const stats = await fs.lstatAsync(files.createSymlink.dest);
	test.true(stats.isSymbolicLink());
});

ava('createSymlinkAtomic (new)', async test => {
	const newDir = resolve(dir, 'createSymlinkNew');
	await nextra.createLinkAtomic(files.createSymlink.src, newDir);

	const stats = await fs.lstatAsync(newDir);
	test.true(stats.isSymbolicLink());
});

ava('createSymlinkAtomic (new recursive)', async test => {
	const deepDir = resolve(dir, 'createSymlinkNew2', 'createSymlinkNew3');
	await nextra.createLinkAtomic(files.createSymlink.src, deepDir);

	const stats = await fs.lstatAsync(deepDir);
	test.true(stats.isSymbolicLink());
});

// emptyDir

ava('emptyDir (empty)', async test => {
	await nextra.emptyDir(files.emptyDir.empty);

	const contents = await fs.readdirAsync(files.emptyDir.empty);
	test.true(contents.length === 0);
});

ava.skip('emptyDir (full)', async test => {
	await nextra.emptyDir(files.emptyDir.full);

	const contents = await fs.readdirAsync(files.emptyDir.full);
	test.true(contents.length === 0);
});

// ensureDir

ava('ensureDir (pre-existing)', async test => {
	await nextra.ensureDir(files.ensureDir);

	const stats = await fs.statAsync(files.ensureDir);
	test.true(stats.isDirectory());
});

ava('ensureDir (new)', async test => {
	const newDir = resolve(dir, 'ensureDirNew');
	await nextra.ensureDir(newDir);

	const stats = await fs.statAsync(newDir);
	test.true(stats.isDirectory());
});

ava('ensureDir (new recursive)', async test => {
	const deepDir = resolve(dir, 'ensureDirNew2', 'ensureDirNew3');
	await nextra.ensureDir(deepDir);

	const stats = await fs.statAsync(deepDir);
	test.true(stats.isDirectory());
});

// linkAtomic

ava('linkAtomic', async test => {
	const newFile = resolve(dir, 'linkAtomicNew.txt');
	await nextra.linkAtomic(files.createlink.src, newFile);

	const stats = await fs.statAsync(newFile);
	test.true(stats.isFile());
});

// move

ava.skip('move', async test => {
	test.plan(2);
	const move = resolve(dir, 'moved');
	await nextra.move(files.copy, move);

	test.throws(fs.statAsync(files.copy));
	test.notThrows(fs.statAsync(move));
});

// outputFile

ava.skip('outputFile (pre-existing)', async test => {
	await nextra.outputFile(files.createFile, 'pass');

	test.is(await fs.readFileAsync(files.createFile, 'utf8'), 'pass');
});

ava('outputFile (new)', async test => {
	const newDir = resolve(dir, 'outputFileNew');
	await nextra.outputFile(newDir, 'pass');

	test.is(await fs.readFileAsync(newDir, 'utf8'), 'pass');
});

ava('outputFile (new recursive)', async test => {
	const deepDir = resolve(dir, 'outputFileNew2', 'outputFileNew3');
	await nextra.outputFile(deepDir, 'pass');

	test.is(await fs.readFileAsync(deepDir, 'utf8'), 'pass');
});

// outputFileAtomic

ava.skip('outputFileAtomic (pre-existing)', async test => {
	await nextra.outputFileAtomic(files.createFile, 'pass');

	test.is(await fs.readFileAsync(files.createFile, 'utf8'), 'pass');
});

ava('outputFileAtomic (new)', async test => {
	const newDir = resolve(dir, 'outputFileNew');
	await nextra.outputFileAtomic(newDir, 'pass');

	test.is(await fs.readFileAsync(newDir, 'utf8'), 'pass');
});

ava('outputFileAtomic (new recursive)', async test => {
	const deepDir = resolve(dir, 'outputFileNew2', 'outputFileNew3');
	await nextra.outputFileAtomic(deepDir, 'pass');

	test.is(await fs.readFileAsync(deepDir, 'utf8'), 'pass');
});

// outputJSON

ava('outputJSON (pre-existing)', async test => {
	const obj = { test: 'passed' };
	await nextra.outputJSON(files.createFile, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(files.createFile, 'utf8')), obj);
});

ava('outputJSON (new)', async test => {
	const newDir = resolve(dir, 'outputJSONNew');
	const obj = { test: 'passed' };
	await nextra.outputJSON(newDir, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(newDir, 'utf8')), obj);
});

ava('outputJSON (new recursive)', async test => {
	const deepDir = resolve(dir, 'outputJSONNew2', 'outputJSONNew3');
	const obj = { test: 'passed' };
	await nextra.outputJSON(deepDir, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(deepDir, 'utf8')), obj);
});

// outputJSONAtomic

ava('outputJSONAtomic (pre-existing)', async test => {
	const obj = { test: 'passed' };
	await nextra.outputJSONAtomic(files.createFile, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(files.createFile, 'utf8')), obj);
});

ava('outputJSONAtomic (new)', async test => {
	const newDir = resolve(dir, 'outputJSONNew');
	const obj = { test: 'passed' };
	await nextra.outputJSONAtomic(newDir, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(newDir, 'utf8')), obj);
});

ava('outputJSONAtomic (new recursive)', async test => {
	const deepDir = resolve(dir, 'outputJSONNew2', 'outputJSONNew3');
	const obj = { test: 'passed' };
	await nextra.outputJSONAtomic(deepDir, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(deepDir, 'utf8')), obj);
});

// pathExists

ava('pathExists (dir true)', async test => {
	test.true(await nextra.pathExists(files.pathExists.dir));
});

ava('pathExists (file true)', async test => {
	test.true(await nextra.pathExists(files.pathExists.file));
});

ava('pathExists (dir false)', async test => {
	const noExist = resolve(dir, 'pathDoesntExist');
	test.false(await nextra.pathExists(noExist));
});

ava('pathExists (file false)', async test => {
	const noExist = resolve(dir, 'pathDoesntExist.txt');
	test.false(await nextra.pathExists(noExist));
});

// readJSON

ava('readJSON', async test => {
	const readJSON = await nextra.readJSON(files.readJSON);
	test.true(readJSON.validate);
});

// remove

ava.skip('remove', async test => {
	const file = resolve(files.emptyDir.full, 'file.txt');
	await nextra.remove(file);

	test.throws(fs.statAsync(file));
});

// symlinkAtomic

ava.skip('symlinkAtomic', async test => {
	const file = resolve(dir, 'file.txt');
	await nextra.symlinkAtomic(files.createSymlink.src, file);

	const stats = await fs.lstatAsync(file);
	test.true(stats.isSymbolicLink());
});

// writeFileAtomic

ava('writeFileAtomic', async test => {
	const file = resolve(dir, 'file.txt');
	const data = 'passed';
	await nextra.writeFileAtomic(file, data);

	test.is(await fs.readFileAsync(file, 'utf8'), data);
});

// writeJSON

ava('writeJSON', async test => {
	const file = resolve(dir, 'file.json');
	const obj = { test: 'passed' };
	await nextra.writeJSON(file, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(file, 'utf8')), obj);
});

// writeJSONAtomic

ava('writeJSONAtomic', async test => {
	const file = resolve(dir, 'file.json');
	const obj = { test: 'passed' };
	await nextra.writeJSONAtomic(file, obj);

	test.deepEqual(JSON.parse(await fs.readFileAsync(file, 'utf8')), obj);
});
<|endoftext|>


<commit_before>

(function (window) {

	//private variables
	var
	//root api url
	apiURL = "http://example.com:8000/api/v1/",
	//authentication, SWIX Username and Generated API Key
	username,
	apiKey,
	//debug mode settings
	debugMode,
	debugMsg = function(msg)
	{
		if (debugMode)
			console.log(msg);
	},
	//utility function for setting a default param
	defaultParam = function(param, defaultVal)
	{
		if (param == undefined)
			return defaultVal;

		return param;
	},
	// execute a jsonp/GET request
	jsonp = function(path, callback, params)
	{
		var head = document.getElementsByTagName('head')[0];
		var script = document.createElement('script');
		script.type = 'text/javascript';

		var prefix = '?';
		if (path.indexOf('?') >= 0)
			prefix = '&';

		var id = 1;
		//generate a unique id for the callback(jsonp padding)
		//then add the callback to the list of callbacks
		while (SWIX.jsonp_callbacks[id] !== undefined)
			id += Math.floor(Math.random()*11); //always a whole number

		//define our callback.
		//essentially calls our callback and performs some cleanup.
		SWIX.jsonp_callbacks[id] = function()
		{
			//execute callback clean up
			delete SWIX.jsonp_callbacks[id];
			callback.apply(params, arguments);

		};

		path += prefix +
				'username=' + username + "&api_key=" + apiKey +
				'&format=jsonp&callback=' +
				encodeURIComponent('SWIX.jsonp_callbacks['+ id +']');

		src = apiURL + path;
		script.setAttribute('src', src);
		debugMsg('requesting: ' + src);

		head.appendChild(script);

	},
	// local swix variable also public in window
	SWIX = window.SWIX = {};

	//initialization function, initialized username and api key
	// also initialized debug mode. (which currently doesn't really do anything)
	SWIX.init = function(user, key, debug)
	{
		username = user;
		apiKey = key;
		debugMode = defaultParam(debug, false);
		return this;
	};

	//Get All brands associated with an account
	SWIX.getBrands = function(callback, params)
	{
		endpointURL = 'brand/';
		jsonp(endpointURL, callback, params);
		return this;
	};

	//Get Metadata associated with a brand by the brands ID
	SWIX.getBrandByID = function(id, callback, params)
	{
		endpointURL = 'brand/' + id + '/';
		jsonp(endpointURL, callback, params);
		return this;
	};

	//Get List of Pods associated with a particular brand
	SWIX.getBrandPods = function(brandID, callback, params)
	{
		endpointURL = 'brand/'+ brandID + '/pod/';
		jsonp(endpointURL, callback);
		return this;
	};

	//Get Pod Metadata given a particular brand id and pod id
	SWIX.getPodByID = function(brandID, podID, callback, params)
	{
		endpointURL = 'brand/' + brandID + '/pod/' + podID + '/';
		jsonp(endpointURL, callback, params);
		return this;
	};

	//Get a pods series data
	SWIX.getPodSeriesData = function(brandID, podID, metric, graph, callback, params)
	{
		metric = defaultParam(metric, '');
		graph = defaultParam(graph, 'highcharts');
		param = ""

		if(metric != '')
		{
		    param = "?fields=" + metric + "&graph=" + graph;
		}
		else
		{
		    param = "?graph=" + graph;
		}

		endpointURL = 'brand/' + brandID + '/pod/' + podID + '/seriesdata/' + param;
		jsonp(endpointURL, callback, params)
		return this;
	};

	SWIX.jsonp_callbacks = {};
}(window));
<commit_msg>Allow pod series to be graph format, or other formats<commit_after>

(function (window) {

	//private variables
	var
	//root api url
	apiURL = "http://example.com:8000/api/v1/",
	//authentication, SWIX Username and Generated API Key
	username,
	apiKey,
	//debug mode settings
	debugMode,
	debugMsg = function(msg)
	{
		if (debugMode)
			console.log(msg);
	},
	//utility function for setting a default param
	defaultParam = function(param, defaultVal)
	{
		if (param == undefined)
			return defaultVal;

		return param;
	},
	// execute a jsonp/GET request
	jsonp = function(path, callback, params)
	{
		var head = document.getElementsByTagName('head')[0];
		var script = document.createElement('script');
		script.type = 'text/javascript';

		var prefix = '?';
		if (path.indexOf('?') >= 0)
			prefix = '&';

		var id = 1;
		//generate a unique id for the callback(jsonp padding)
		//then add the callback to the list of callbacks
		while (SWIX.jsonp_callbacks[id] !== undefined)
			id += Math.floor(Math.random()*11); //always a whole number

		//define our callback.
		//essentially calls our callback and performs some cleanup.
		SWIX.jsonp_callbacks[id] = function()
		{
			//execute callback clean up
			delete SWIX.jsonp_callbacks[id];
			callback.apply(params, arguments);

		};

		path += prefix +
				'username=' + username + "&api_key=" + apiKey +
				'&format=jsonp&callback=' +
				encodeURIComponent('SWIX.jsonp_callbacks['+ id +']');

		src = apiURL + path;
		script.setAttribute('src', src);
		debugMsg('requesting: ' + src);

		head.appendChild(script);

	},
	// local swix variable also public in window
	SWIX = window.SWIX = {};

	//initialization function, initialized username and api key
	// also initialized debug mode. (which currently doesn't really do anything)
	SWIX.init = function(user, key, debug)
	{
		username = user;
		apiKey = key;
		debugMode = defaultParam(debug, false);
		return this;
	};

	//Get All brands associated with an account
	SWIX.getBrands = function(callback, params)
	{
		endpointURL = 'brand/';
		jsonp(endpointURL, callback, params);
		return this;
	};

	//Get Metadata associated with a brand by the brands ID
	SWIX.getBrandByID = function(id, callback, params)
	{
		endpointURL = 'brand/' + id + '/';
		jsonp(endpointURL, callback, params);
		return this;
	};

	//Get List of Pods associated with a particular brand
	SWIX.getBrandPods = function(brandID, callback, params)
	{
		endpointURL = 'brand/'+ brandID + '/pod/';
		jsonp(endpointURL, callback);
		return this;
	};

	//Get Pod Metadata given a particular brand id and pod id
	SWIX.getPodByID = function(brandID, podID, callback, params)
	{
		endpointURL = 'brand/' + brandID + '/pod/' + podID + '/';
		jsonp(endpointURL, callback, params);
		return this;
	};

	//Get a pods series data
	SWIX.getPodSeriesData = function(brandID, podID, metric, graph, callback, params)
	{
		metric = defaultParam(metric, '');
		graph = defaultParam(graph, '');
		param = ""

		if(metric != '')
		{
		    param = "?fields=" + metric;
		}

		if(graph != '')
		{
		    if( param != '')
		    {
		        param = param + "&graph=" + graph;
		    }
		    else
		    {
		        param = "?graph=" + graph;
		    }
		}

		endpointURL = 'brand/' + brandID + '/pod/' + podID + '/seriesdata/' + param;
		jsonp(endpointURL, callback, params)
		return this;
	};

	SWIX.jsonp_callbacks = {};
}(window));
<|endoftext|>


<commit_before>"use strict";

var call      = Function.prototype.call
  , partial   = require("es5-ext/function/#/partial")
  , last      = require("es5-ext/array/#/last")
  , indent    = call.bind(partial.call(require("es5-ext/string/#/indent"),
		" ", 17))
  , format    = call.bind(partial
		.call(require("es5-ext/date/#/format"), "%H:%M:%S.%L "))
  , dpad      = partial.call(require("es5-ext/string/#/pad"), " ", 12)
  , duration  = require("duration")
  , inspect   = require("util").inspect
  , clc       = require("cli-color")
  , ctrim     = require("cli-color/strip")
  , cthrobber = require("cli-color/throbber")

  , write = process.stdout.write.bind(process.stdout)
  , lerror = clc.magenta, lfail = clc.red, lpass = clc.green
  , lsummary = clc.cyan
  , o;

o = {
	init: function (options) {
		this.mode = options.a ? 2 : options.m ? 0 : 1;
		this.passed = 0;
		this.failed = 0;
		this.errored = 0;
		this.started = new Date();
		this.writeLog = [];
		this.write = function (msg) {
			this.writeLog.push(arguments);
			return write.apply(this, arguments);
		};
		this.progress = cthrobber(write, 200);
		return this;
	},
	atNewLine: function () {
		return !this.writeLog.length ||
			last.call(ctrim(last.call(this.writeLog)[0])) === "\n";
	},
	break: function () {
		this.progress.restart();
		if (!this.atNewLine() && this.mode) {
			this.write("\n");
		}
	},
	pass: function (path, name) {
		++this.passed;
		this.progress.restart();
		if (this.mode === 2) {
			this.write(lpass(format(new Date()) + " ✓  " + name + "\n"));
		} else {
			this.write(lpass(this.atNewLine() ? format(new Date()) + " ✓  " +
				(path && this.mode ? path + " " : "") + "." : "."));
		}
	},
	fail: function (path, name, e) {
		var s;
		++this.failed;
		this.progress.restart();
		if (!this.atNewLine()) {
			this.write("\n");
		}
		s = "";
		if (e.operator) {
			if (e.hasOwnProperty("expected")) {
				s += "Expected: " + inspect(e.expected, false, 1) + "\n";
			}
			if (e.hasOwnProperty("actual")) {
				s += "Actual:   " + inspect(e.actual, false, 1) + "\n";
			}
			s += "Operator: " + e.operator + "\n";
		} else {
			s += (e.stack || e) + "\n";
		}
		this.write(lfail(format(new Date()) + " ✗  " + name + "\n" + indent(s)));
	},
	error: function (path, name, e) {
		var s, eStr, index;
		++this.errored;
		this.progress.restart();
		if (!this.atNewLine()) {
			this.write("\n");
		}
		name = name || path;
		s = format(new Date()) + " -  ";
		eStr = String(e.stack || e);
		if (name) {
			s += name + "\n" + indent(eStr);
		} else {
			index = eStr.indexOf("\n") + 1;
			s += index ? eStr.slice(0, index) + indent(eStr.slice(index)) : eStr;
		}
		this.write(lerror(s + "\n"));
	},
	end: function () {
		var s, all = this.passed + this.failed + this.errored;
		this.progress.stop();
		if (!this.atNewLine()) {
			this.write("\n");
		}
		this.write("\n");
		if (!all) {
			this.write(lsummary("No tests run\n\n"));
		} else {
			this.write(lsummary(dpad.call(duration(this.started,
				new Date()).toString()) + "     "));
			s = [];
			s.push(clc.green(this.passed + " Ok [" +
				((this.passed / all) * 100).toFixed(2) + "%]"));
			if (this.failed) {
				s.push(clc.red(this.failed + " Failed"));
			}
			if (this.errored) {
				s.push(clc.magenta(this.errored + " Errors"));
			}
			this.write(s.join("  ") + "\n\n");
		}
	}
};

module.exports = function (options) {
	return Object.create(o).init(options || {});
};
<commit_msg>style: prettier<commit_after>"use strict";

var call      = Function.prototype.call
  , partial   = require("es5-ext/function/#/partial")
  , last      = require("es5-ext/array/#/last")
  , indent    = call.bind(partial.call(require("es5-ext/string/#/indent"), " ", 17))
  , format    = call.bind(partial.call(require("es5-ext/date/#/format"), "%H:%M:%S.%L "))
  , dpad      = partial.call(require("es5-ext/string/#/pad"), " ", 12)
  , duration  = require("duration")
  , inspect   = require("util").inspect
  , clc       = require("cli-color")
  , ctrim     = require("cli-color/strip")
  , cthrobber = require("cli-color/throbber");

var write = process.stdout.write.bind(process.stdout)
  , lerror = clc.magenta
  , lfail = clc.red
  , lpass = clc.green
  , lsummary = clc.cyan
  , o;

o = {
	init: function (options) {
		this.mode = options.a ? 2 : options.m ? 0 : 1;
		this.passed = 0;
		this.failed = 0;
		this.errored = 0;
		this.started = new Date();
		this.writeLog = [];
		this.write = function (msg) {
			this.writeLog.push(arguments);
			return write.apply(this, arguments);
		};
		this.progress = cthrobber(write, 200);
		return this;
	},
	atNewLine: function () {
		return !this.writeLog.length || last.call(ctrim(last.call(this.writeLog)[0])) === "\n";
	},
	break: function () {
		this.progress.restart();
		if (!this.atNewLine() && this.mode) {
			this.write("\n");
		}
	},
	pass: function (path, name) {
		++this.passed;
		this.progress.restart();
		if (this.mode === 2) {
			this.write(lpass(format(new Date()) + " ✓  " + name + "\n"));
		} else {
			this.write(
				lpass(
					this.atNewLine()
						? format(new Date()) + " ✓  " + (path && this.mode ? path + " " : "") + "."
						: "."
				)
			);
		}
	},
	fail: function (path, name, e) {
		var s;
		++this.failed;
		this.progress.restart();
		if (!this.atNewLine()) {
			this.write("\n");
		}
		s = "";
		if (e.operator) {
			if (e.hasOwnProperty("expected")) {
				s += "Expected: " + inspect(e.expected, false, 1) + "\n";
			}
			if (e.hasOwnProperty("actual")) {
				s += "Actual:   " + inspect(e.actual, false, 1) + "\n";
			}
			s += "Operator: " + e.operator + "\n";
		} else {
			s += (e.stack || e) + "\n";
		}
		this.write(lfail(format(new Date()) + " ✗  " + name + "\n" + indent(s)));
	},
	error: function (path, name, e) {
		var s, eStr, index;
		++this.errored;
		this.progress.restart();
		if (!this.atNewLine()) {
			this.write("\n");
		}
		name = name || path;
		s = format(new Date()) + " -  ";
		eStr = String(e.stack || e);
		if (name) {
			s += name + "\n" + indent(eStr);
		} else {
			index = eStr.indexOf("\n") + 1;
			s += index ? eStr.slice(0, index) + indent(eStr.slice(index)) : eStr;
		}
		this.write(lerror(s + "\n"));
	},
	end: function () {
		var s, all = this.passed + this.failed + this.errored;
		this.progress.stop();
		if (!this.atNewLine()) {
			this.write("\n");
		}
		this.write("\n");
		if (!all) {
			this.write(lsummary("No tests run\n\n"));
		} else {
			this.write(
				lsummary(dpad.call(duration(this.started, new Date()).toString()) + "     ")
			);
			s = [];
			s.push(clc.green(this.passed + " Ok [" + (this.passed / all * 100).toFixed(2) + "%]"));
			if (this.failed) {
				s.push(clc.red(this.failed + " Failed"));
			}
			if (this.errored) {
				s.push(clc.magenta(this.errored + " Errors"));
			}
			this.write(s.join("  ") + "\n\n");
		}
	}
};

module.exports = function (options) {
	return Object.create(o).init(options || {});
};
<|endoftext|>


<commit_before>var assert = require('assert'),
    esprima = require('esprima'),
    esprimaOptions = {tolerant: true, loc: true, tokens: true, raw: true},
    estraverse = require('estraverse'),
    espurify = require('espurify'),
    escallmatch = require('..');

function captureArguments (matcher, jsCode) {
    var ast = esprima.parse(jsCode, esprimaOptions);
    var collector = {};
    estraverse.traverse(ast, {
        leave: function (currentNode, parentNode) {
            var name = matcher.isCaptured(currentNode, parentNode);
            if (name) {
                collector[name] = currentNode;
            }
        }
    });
    return collector;
}

function extractArguments (matcher, jsCode) {
    var ast = esprima.parse(jsCode, esprimaOptions);
    var collector = [];
    estraverse.traverse(ast, {
        leave: function (currentNode, parentNode) {
            var matched = matcher.isCaptured(currentNode, parentNode);
            if (matched) {
                collector.push(currentNode);
            }
        }
    });
    return collector;
}

function extractCalls (matcher, jsCode) {
    var ast = esprima.parse(jsCode, esprimaOptions);
    var collector = [];
    estraverse.traverse(ast, {
        leave: function (currentNode, parentNode) {
            var matched = matcher.test(currentNode);
            if (matched) {
                collector.push(currentNode);
            }
        }
    });
    return collector;
}

function matchAgainst (that, targetCode) {
    that.calls = extractCalls(that.matcher, targetCode);
    that.args = extractArguments(that.matcher, targetCode);
    that.captured = captureArguments(that.matcher, targetCode);
}

describe('wildcard identifier assert(actual)', function () {
    beforeEach(function () {
        this.matcher = escallmatch('assert(actual)');
    });
    it('single identifier', function () {
        matchAgainst(this, 'it("test foo", function () { assert(foo); })');
        assert.equal(this.calls.length, 1);
        assert.equal(this.args.length, 1);
        assert(this.captured['actual']);
        assert.equal(this.captured['actual'].name, 'foo');
        assert.deepEqual(espurify(this.calls[0]), {
            type: 'CallExpression',
            callee: {
                type: 'Identifier',
                name: 'assert'
            },
            arguments: [
                {
                    type: 'Identifier',
                    name: 'foo'
                }
            ]
        });
        assert.deepEqual(espurify(this.args[0]), {
            type: 'Identifier',
            name: 'foo'
        });
    });
    it('optional parameter', function () {
        matchAgainst(this, 'it("test foo", function () { assert(foo, "message"); })');
        assert.equal(this.calls.length, 1);
        assert.equal(this.args.length, 1);
        assert(this.captured['actual']);
        assert.equal(this.captured['actual'].name, 'foo');
    });
    it('no params', function () {
        matchAgainst(this, 'it("test foo", function () { assert(); })');
        assert.equal(this.calls.length, 0);
        assert.equal(this.args.length, 0);
        assert(! this.captured['actual']);
    });
});

describe('wildcard two args assert.equal(actual, expected)', function () {
    beforeEach(function () {
        this.matcher = escallmatch('assert.equal(actual, expected)');
    });
    it('capture arguments', function () {
        matchAgainst(this, 'it("test foo and bar", function () { assert.equal(foo, bar); })');
        assert.equal(this.calls.length, 1);
        assert.equal(this.args.length, 2);
        assert(this.captured['actual']);
        assert.equal(this.captured['actual'].name, 'foo');
        assert(this.captured['expected']);
        assert.equal(this.captured['expected'].name, 'bar');
        assert.deepEqual(espurify(this.calls[0]), {
            type: 'CallExpression',
            callee: {
                type: 'MemberExpression',
                computed: false,
                object: {
                    type: 'Identifier',
                    name: 'assert'
                },
                property: {
                    type: 'Identifier',
                    name: 'equal'
                }
            },
            arguments: [
                {
                    type: 'Identifier',
                    name: 'foo'
                },
                {
                    type: 'Identifier',
                    name: 'bar'
                }
            ]
        });
        assert.deepEqual(espurify(this.args[0]), {
            type: 'Identifier',
            name: 'foo'
        });
        assert.deepEqual(espurify(this.args[1]), {
            type: 'Identifier',
            name: 'bar'
        });
    });
    it('optional parameters', function () {
        matchAgainst(this, 'it("test foo and bar", function () { assert.equal(foo, bar, "message"); })');
        assert.equal(this.calls.length, 1);
        assert.equal(this.args.length, 2);
        assert(this.captured['actual']);
        assert.equal(this.captured['actual'].name, 'foo');
        assert(this.captured['expected']);
        assert.equal(this.captured['expected'].name, 'bar');
    });
    it('less parameters', function () {
        matchAgainst(this, 'it("test foo and bar", function () { assert.equal(foo); })');
        assert.equal(this.calls.length, 0);
        assert.equal(this.args.length, 0);
        assert(! this.captured['actual']);
        assert(! this.captured['expected']);
    });
});

it('not Identifier', function () {
    var matcher = escallmatch('assert.equal(actual, expected)');
    var targetCode = 'it("test3", function () { assert.equal(toto.tata(baz), moo[0]); })';

    var calls = extractCalls(matcher, targetCode);
    assert.equal(calls.length, 1);
    assert.deepEqual(espurify(calls[0]), {
        type: 'CallExpression',
        callee: {
            type: 'MemberExpression',
            computed: false,
            object: {
                type: 'Identifier',
                name: 'assert'
            },
            property: {
                type: 'Identifier',
                name: 'equal'
            }
        },
        arguments: [
            {
                type: 'CallExpression',
                callee: {
                    type: 'MemberExpression',
                    computed: false,
                    object: {
                        type: 'Identifier',
                        name: 'toto'
                    },
                    property: {
                        type: 'Identifier',
                        name: 'tata'
                    }
                },
                arguments: [
                    {
                        type: 'Identifier',
                        name: 'baz'
                    }
                ]
            },
            {
                type: 'MemberExpression',
                computed: true,
                object: {
                    type: 'Identifier',
                    name: 'moo'
                },
                property: {
                    type: 'Literal',
                    value: 0
                }
            }
        ]
    });

    var args = extractArguments(matcher, targetCode);
    assert.equal(args.length, 2);
    assert.deepEqual(espurify(args[0]), {
        type: 'CallExpression',
        callee: {
            type: 'MemberExpression',
            computed: false,
            object: {
                type: 'Identifier',
                name: 'toto'
            },
            property: {
                type: 'Identifier',
                name: 'tata'
            }
        },
        arguments: [
            {
                type: 'Identifier',
                name: 'baz'
            }
        ]
    });
    assert.deepEqual(espurify(args[1]), {
        type: 'MemberExpression',
        computed: true,
        object: {
            type: 'Identifier',
            name: 'moo'
        },
        property: {
            type: 'Literal',
            value: 0
        }
    });
});
<commit_msg>test(escallmatch): refactor tests<commit_after>var assert = require('assert'),
    esprima = require('esprima'),
    esprimaOptions = {tolerant: true, loc: true, tokens: true, raw: true},
    estraverse = require('estraverse'),
    espurify = require('espurify'),
    escallmatch = require('..');

var matchCode = (function () {
    function captureArguments (matcher, jsCode) {
        var ast = esprima.parse(jsCode, esprimaOptions);
        var collector = {};
        estraverse.traverse(ast, {
            leave: function (currentNode, parentNode) {
                var name = matcher.isCaptured(currentNode, parentNode);
                if (name) {
                    collector[name] = currentNode;
                }
            }
        });
        return collector;
    }

    function extractArguments (matcher, jsCode) {
        var ast = esprima.parse(jsCode, esprimaOptions);
        var collector = [];
        estraverse.traverse(ast, {
            leave: function (currentNode, parentNode) {
                var matched = matcher.isCaptured(currentNode, parentNode);
                if (matched) {
                    collector.push(currentNode);
                }
            }
        });
        return collector;
    }

    function extractCalls (matcher, jsCode) {
        var ast = esprima.parse(jsCode, esprimaOptions);
        var collector = [];
        estraverse.traverse(ast, {
            leave: function (currentNode, parentNode) {
                var matched = matcher.test(currentNode);
                if (matched) {
                    collector.push(currentNode);
                }
            }
        });
        return collector;
    }

    return function (matcher, targetCode) {
        return {
            calls: extractCalls(matcher, targetCode),
            args: extractArguments(matcher, targetCode),
            captured: captureArguments(matcher, targetCode)
        };
    };
})();

describe('wildcard identifier assert(actual)', function () {
    beforeEach(function () {
        this.matcher = escallmatch('assert(actual)');
    });
    it('single identifier', function () {
        var matched = matchCode(this.matcher, 'it("test foo", function () { assert(foo); })');
        assert.equal(matched.calls.length, 1);
        assert.equal(matched.args.length, 1);
        assert(matched.captured['actual']);
        assert.equal(matched.captured['actual'].name, 'foo');
        assert.deepEqual(espurify(matched.calls[0]), {
            type: 'CallExpression',
            callee: {
                type: 'Identifier',
                name: 'assert'
            },
            arguments: [
                {
                    type: 'Identifier',
                    name: 'foo'
                }
            ]
        });
        assert.deepEqual(espurify(matched.args[0]), {
            type: 'Identifier',
            name: 'foo'
        });
    });
    it('optional parameter', function () {
        var matched = matchCode(this.matcher, 'it("test foo", function () { assert(foo, "message"); })');
        assert.equal(matched.calls.length, 1);
        assert.equal(matched.args.length, 1);
        assert(matched.captured['actual']);
        assert.equal(matched.captured['actual'].name, 'foo');
    });
    it('no params', function () {
        var matched = matchCode(this.matcher, 'it("test foo", function () { assert(); })');
        assert.equal(matched.calls.length, 0);
        assert.equal(matched.args.length, 0);
        assert(! matched.captured['actual']);
    });
});

describe('wildcard two args assert.equal(actual, expected)', function () {
    beforeEach(function () {
        this.matcher = escallmatch('assert.equal(actual, expected)');
    });
    it('capture arguments', function () {
        var matched = matchCode(this.matcher, 'it("test foo and bar", function () { assert.equal(foo, bar); })');
        assert.equal(matched.calls.length, 1);
        assert.equal(matched.args.length, 2);
        assert(matched.captured['actual']);
        assert.equal(matched.captured['actual'].name, 'foo');
        assert(matched.captured['expected']);
        assert.equal(matched.captured['expected'].name, 'bar');
        assert.deepEqual(espurify(matched.calls[0]), {
            type: 'CallExpression',
            callee: {
                type: 'MemberExpression',
                computed: false,
                object: {
                    type: 'Identifier',
                    name: 'assert'
                },
                property: {
                    type: 'Identifier',
                    name: 'equal'
                }
            },
            arguments: [
                {
                    type: 'Identifier',
                    name: 'foo'
                },
                {
                    type: 'Identifier',
                    name: 'bar'
                }
            ]
        });
        assert.deepEqual(espurify(matched.args[0]), {
            type: 'Identifier',
            name: 'foo'
        });
        assert.deepEqual(espurify(matched.args[1]), {
            type: 'Identifier',
            name: 'bar'
        });
    });
    it('optional parameters', function () {
        var matched = matchCode(this.matcher, 'it("test foo and bar", function () { assert.equal(foo, bar, "message"); })');
        assert.equal(matched.calls.length, 1);
        assert.equal(matched.args.length, 2);
        assert(matched.captured['actual']);
        assert.equal(matched.captured['actual'].name, 'foo');
        assert(matched.captured['expected']);
        assert.equal(matched.captured['expected'].name, 'bar');
    });
    it('less parameters', function () {
        var matched = matchCode(this.matcher, 'it("test foo and bar", function () { assert.equal(foo); })');
        assert.equal(matched.calls.length, 0);
        assert.equal(matched.args.length, 0);
        assert(! matched.captured['actual']);
        assert(! matched.captured['expected']);
    });
});

it('not Identifier', function () {
    var matcher = escallmatch('assert.equal(actual, expected)');
    var matched = matchCode(matcher, 'it("test3", function () { assert.equal(toto.tata(baz), moo[0]); })');

    assert.equal(matched.calls.length, 1);
    assert.deepEqual(espurify(matched.calls[0]), {
        type: 'CallExpression',
        callee: {
            type: 'MemberExpression',
            computed: false,
            object: {
                type: 'Identifier',
                name: 'assert'
            },
            property: {
                type: 'Identifier',
                name: 'equal'
            }
        },
        arguments: [
            {
                type: 'CallExpression',
                callee: {
                    type: 'MemberExpression',
                    computed: false,
                    object: {
                        type: 'Identifier',
                        name: 'toto'
                    },
                    property: {
                        type: 'Identifier',
                        name: 'tata'
                    }
                },
                arguments: [
                    {
                        type: 'Identifier',
                        name: 'baz'
                    }
                ]
            },
            {
                type: 'MemberExpression',
                computed: true,
                object: {
                    type: 'Identifier',
                    name: 'moo'
                },
                property: {
                    type: 'Literal',
                    value: 0
                }
            }
        ]
    });

    assert.equal(matched.args.length, 2);
    assert.deepEqual(espurify(matched.args[0]), {
        type: 'CallExpression',
        callee: {
            type: 'MemberExpression',
            computed: false,
            object: {
                type: 'Identifier',
                name: 'toto'
            },
            property: {
                type: 'Identifier',
                name: 'tata'
            }
        },
        arguments: [
            {
                type: 'Identifier',
                name: 'baz'
            }
        ]
    });
    assert.deepEqual(espurify(matched.args[1]), {
        type: 'MemberExpression',
        computed: true,
        object: {
            type: 'Identifier',
            name: 'moo'
        },
        property: {
            type: 'Literal',
            value: 0
        }
    });
});
<|endoftext|>


<commit_before>/**
 * Container
 *
 * Uses as container for application services
 */
var container = function() {

    // FIXME add support for singelton

    var stock = [];

    return {

        /**
         * Register
         *
         * Adds a new service definition to application services stack.
         *
         * @param name string
         * @param callback function
         * @param singelton bool
         * @returns container
         */
        register: function(name, callback, singelton) {

            if(typeof name !== 'string') {
                throw new Error('var name must be of type string');
            }

            if(typeof callback !== 'function') {
                throw new Error('var callback must be of type function');
            }

            if(typeof singelton !== 'boolean') {
                throw new Error('var callback must be of type boolean');
            }

            stock[name] = {
                name: name,
                callback: callback,
                singleton: singelton,
                instance: null
            };

            return this;
        },

        /**
         * Get Service
         *
         * Return service instance
         *
         * @param name
         * @returns {*}
         */
        get: function(name) {
            var service = (undefined !== stock[name]) ? stock[name] : null;

            if(null === service) {
                throw new Error('service \'' + name + '\' is not registered');
            }

            if(service.instance === null) {
                var instance  = service.callback();

                if(service.singleton) {
                    service.instance = instance;
                }

                return instance;
            }

            return service.instance;
        }
    }
}();<commit_msg>Container allows function or object passing for new services registration<commit_after>/**
 * Container
 *
 * Uses as container for application services
 */
var container = function() {

    // FIXME add support for singelton

    var stock = [];

    return {

        /**
         * Register
         *
         * Adds a new service definition to application services stack.
         *
         * @param name string
         * @param object callback|object
         * @param singelton bool
         * @returns container
         */
        register: function(name, object, singelton) {

            if(typeof name !== 'string') {
                throw new Error('var name must be of type string');
            }

            if(typeof object !== 'function' && (typeof object !== 'object')) {
                throw new Error('var object must be of type function or object');
            }

            if(typeof singelton !== 'boolean') {
                throw new Error('var singelton must be of type boolean');
            }

            stock[name] = {
                name: name,
                object: object,
                singleton: singelton,
                instance: null
            };

            return this;
        },

        /**
         * Get Service
         *
         * Return service instance
         *
         * @param name
         * @returns {*}
         */
        get: function(name) {
            var service = (undefined !== stock[name]) ? stock[name] : null;

            if(null === service) {
                throw new Error('service \'' + name + '\' is not registered');
            }

            if(service.instance === null) {
                var instance  = (typeof service.object == 'function') ? service.object() : service.object;

                if(service.singleton) {
                    service.instance = instance;
                }

                return instance;
            }

            return service.instance;
        }
    }
}();<|endoftext|>


<commit_before>// Import libraries
require('babel-polyfill');
const ng = require('angular');
require('angular-material');
require('angular-messages');
require('angular-route');
require('ng-file-upload');
const Promise = require('bluebird');

const CSRF_TOKEN = document.getElementById('csrf-token').innerHTML;

// Import modules
require('./login/login.module.js');
require('./home/home.module.js');
require('./box/box.module.js');
require('./pokemon/pokemon.module.js');
require('./add/add.module.js');
require('./userMenu/user.module.js');

const porybox = ng.module('porybox', [
  // Porybox modules
  'porybox.login',
  'porybox.home',
  'porybox.add',
  'porybox.userMenu',

  // Third party
  'ngMaterial',
  'ngRoute'
]);

porybox.controller('MainCtrl', function () {
  this.boxes = [];
  this.init = function ({boxes, user, prefs}) {
    this.boxes = boxes;
    this.user = user;
    if (!this.user && (window.location.hash === '' || window.location.hash === '#/')) {
      window.location.hash = 'login';
    }
    this.prefs = prefs;
  };
});

porybox.config(['$mdThemingProvider','$routeProvider',function(
  $mdThemingProvider,
  $routeProvider
) {
  $mdThemingProvider.theme('default')
    .primaryPalette('light-blue', {
      'default': '600',
      'hue-1': '900'
    })
    .accentPalette('pink', {
      'default': 'A100'
    });

  $routeProvider.otherwise({ redirectTo: '/' });
}]);

porybox.config(['$httpProvider', function ($httpProvider) {
  $httpProvider.defaults.headers.common['x-csrf-token'] = CSRF_TOKEN;
}]);

porybox.service('io', function () {
  const socket = require('socket.io-client');
  const io = require('sails.io.js')(socket);
  io.sails.headers = {'x-csrf-token': CSRF_TOKEN};
  // create versions of the io.socket functions that return Promises.
  // e.g. io.socket.getAsync('/foo').then(handleResponse).catch(handleErrors)
  Promise.promisifyAll(io.socket, {
    promisifier (fn) {
      return function (...args) {
        return new Promise((resolve, reject) => {
          // Resolve the promise if the status code is 2xx.
          fn.call(this, ...args, (d, res) => {
            return /^2/.test(res.statusCode) ? resolve(d) : reject(Object.assign(new Error, res));
          });
        });
      };
    }
  });
  return io;
});

ng.bootstrap(document, ['porybox']);
<commit_msg>Fix an issue where not-logged-in users would get an unnecessary #login hash added when viewing static pages<commit_after>// Import libraries
require('babel-polyfill');
const ng = require('angular');
require('angular-material');
require('angular-messages');
require('angular-route');
require('ng-file-upload');
const Promise = require('bluebird');

const CSRF_TOKEN = document.getElementById('csrf-token').innerHTML;

// Import modules
require('./login/login.module.js');
require('./home/home.module.js');
require('./box/box.module.js');
require('./pokemon/pokemon.module.js');
require('./add/add.module.js');
require('./userMenu/user.module.js');

const porybox = ng.module('porybox', [
  // Porybox modules
  'porybox.login',
  'porybox.home',
  'porybox.add',
  'porybox.userMenu',

  // Third party
  'ngMaterial',
  'ngRoute'
]);

porybox.controller('MainCtrl', function () {
  this.boxes = [];
  this.init = function ({boxes, user, prefs}) {
    this.boxes = boxes;
    this.user = user;
    if (!this.user && location.pathname === '/' && ['', '#/'].indexOf(location.hash) !== -1) {
      location.hash = 'login';
    }
    this.prefs = prefs;
  };
});

porybox.config(['$mdThemingProvider','$routeProvider',function(
  $mdThemingProvider,
  $routeProvider
) {
  $mdThemingProvider.theme('default')
    .primaryPalette('light-blue', {
      'default': '600',
      'hue-1': '900'
    })
    .accentPalette('pink', {
      'default': 'A100'
    });

  $routeProvider.otherwise({ redirectTo: '/' });
}]);

porybox.config(['$httpProvider', function ($httpProvider) {
  $httpProvider.defaults.headers.common['x-csrf-token'] = CSRF_TOKEN;
}]);

porybox.service('io', function () {
  const socket = require('socket.io-client');
  const io = require('sails.io.js')(socket);
  io.sails.headers = {'x-csrf-token': CSRF_TOKEN};
  // create versions of the io.socket functions that return Promises.
  // e.g. io.socket.getAsync('/foo').then(handleResponse).catch(handleErrors)
  Promise.promisifyAll(io.socket, {
    promisifier (fn) {
      return function (...args) {
        return new Promise((resolve, reject) => {
          // Resolve the promise if the status code is 2xx.
          fn.call(this, ...args, (d, res) => {
            return /^2/.test(res.statusCode) ? resolve(d) : reject(Object.assign(new Error, res));
          });
        });
      };
    }
  });
  return io;
});

ng.bootstrap(document, ['porybox']);
<|endoftext|>


<commit_before>"use strict";

const fs = require('fs');
const util = require('util');
const xml2js = require('xml2js');

const wfg = {};

wfg.ProtocolParser = class {

    ["uint"](argName, optional) {
        return {
            jsType: optional ? "?Number" : "Number",
            marshallGen: optional ? util.format("wfc._uintOptional(%s)", argName) : util.format("wfc._uint(%s)", argName)
        };
    }

    ["int"](argName, optional) {
        return {
            jsType: optional ? "?Number" : "Number",
            marshallGen: optional ? util.format("wfc._intOptional(%s)", argName) : util.format("wfc._int(%s)", argName)
        };
    }

    ["fixed"](argName, optional) {
        return {
            jsType: optional ? "?WFixed" : "WFixed",
            marshallGen: optional ? util.format("wfc._fixedOptional(%s)", argName) : util.format("wfc._fixed(%s)", argName)
        };
    }

    ["object"](argName, optional) {
        return {
            jsType: optional ? "?*" : "*",
            marshallGen: optional ? util.format("wfc._objectOptional(%s)", argName) : util.format("wfc._object(%s)", argName)
        };
    }

    ["new_id"](argName, optional) {
        return {
            jsType: "*",
            marshallGen: "wfc._newObject()"
        };
    }

    ["string"](argName, optional) {
        return {
            jsType: optional ? "?string" : "string",
            marshallGen: optional ? util.format("wfc._stringOptional(%s)", argName) : util.format("wfc._string(%s)", argName)
        };
    }

    ["array"](argName, optional) {
        return {
            jsType: optional ? "?ArrayBuffer" : "ArrayBuffer",
            marshallGen: optional ? util.format("wfc._arrayOptional(%s)", argName) : util.format("wfc._array(%s)", argName)
        };
    }

    _generateRequestArgs(out, req) {
        if (req.hasOwnProperty("arg")) {
            const evArgs = req.arg;
            let processedFirstArg = false;
            for (let i = 0; i < evArgs.length; i++) {
                const arg = evArgs[i];
                if (arg.$.type === "new_id") {
                    continue;
                }

                const argName = arg.$.name;
                if (processedFirstArg) {
                    out.write(", ");
                }
                out.write(argName);
                processedFirstArg = true;
            }
        }
    }

    _generateEventArgs(out, ev) {
        if (ev.hasOwnProperty("arg")) {
            const evArgs = ev.arg;
            for (let i = 0; i < evArgs.length; i++) {
                const arg = evArgs[i];
                const argName = arg.$.name;
                if (i !== 0) {
                    out.write(", ");
                }
                out.write(argName);
            }
        }
    }

    _generateIfEventGlue(out, ev, opcode) {

        const evName = ev.$.name;

        out.write(util.format("\t[%d](message){\n", opcode));
        out.write(util.format("\t\tconst args = this._connection._unmarshallArgs(message);\n"));
        out.write(util.format("\t\tthis.iface.%s.call(", evName));

        if (ev.hasOwnProperty("arg")) {
            const evArgs = ev.arg;
            for (let i = 0; i < evArgs.length; i++) {
                if (i !== 0) {
                    out.write(", ");
                }

                const arg = evArgs[i];
                const argType = arg.$.type;
                out.write(util.format("args[%d]", i));
                if (argType === "new_id") {
                    const argItf = arg.$["interface"];
                    out.write(util.format("(\"%s\")", argItf));
                }
            }
        }

        out.write(");\n");
        out.write("\t}\n\n");
    }

    _parseItfEvent(out, itfEvent) {
        const sinceVersion = itfEvent.$.hasOwnProperty("since") ? parseInt(itfEvent.$.since) : 1;
        const evName = itfEvent.$.name;

        //function docs
        const description = itfEvent.description;
        description.forEach((val) => {
            out.write("\n\t\t\t/**\n");
            if (val.hasOwnProperty("_")) {
                val._.split("\n").forEach((line) => {
                    out.write("\t\t\t *" + line + "\n");
                });
            }

            if (itfEvent.hasOwnProperty("arg")) {
                const evArgs = itfEvent.arg;
                out.write("\t\t\t *\n");
                evArgs.forEach((arg) => {
                    const argDescription = arg.$.summary;
                    const argName = arg.$.name;
                    const optional = arg.$.hasOwnProperty("allow-null") && (arg.$["allow-null"] === "true");
                    const argType = arg.$.type;

                    out.write(util.format("\t\t\t * @param {%s} %s %s \n", this[argType](argName, optional).jsType, argName, argDescription));
                });
                out.write("\t\t\t *\n");

            }
            out.write(util.format("\t\t\t * @since %d\n", sinceVersion));
            out.write("\t\t\t *\n");
            out.write("\t\t\t */\n");
        });

        //function
        out.write(util.format("\t\t\t%s(", evName));
        this._generateEventArgs(out, itfEvent);
        out.write(") {},\n");
    }

    _parseItfRequest(out, itfRequest, opcode, itfVersion) {

        const sinceVersion = itfRequest.$.hasOwnProperty("since") ? parseInt(itfRequest.$.since) : 1;
        if (sinceVersion !== itfVersion) {
            return;
        }

        const reqName = itfRequest.$.name;

        //function docs
        const description = itfRequest.description;
        description.forEach((val) => {
            out.write("\n\t/**\n");
            if (val.hasOwnProperty("_")) {
                val._.split("\n").forEach((line) => {
                    out.write("\t *" + line + "\n");
                });
            }

            if (itfRequest.hasOwnProperty("arg")) {
                const reqArgs = itfRequest.arg;
                out.write("\t *\n");
                reqArgs.forEach((arg) => {
                    const argDescription = arg.$.summary;
                    const argName = arg.$.name;
                    const optional = arg.$.hasOwnProperty("allow-null") && (arg.$["allow-null"] === "true");
                    const argType = arg.$.type;
                    if (argType !== "new_id") {
                        out.write(util.format("\t * @param {%s} %s %s \n", this[argType](argName, optional).jsType, argName, argDescription));
                    }
                });

                reqArgs.forEach((arg) => {
                    const argDescription = arg.$.summary;
                    const argItf = arg.$["interface"];
                    const argType = arg.$.type;
                    if (argType === "new_id") {
                        out.write(util.format("\t * @return {%s} %s \n", argItf, argDescription));
                    }
                });
                out.write("\t *\n");

            }
            out.write(util.format("\t * @since %d\n", sinceVersion));
            out.write("\t *\n");
            out.write("\t */\n");
        });

        //function
        out.write(util.format("\t%s(", reqName));
        this._generateRequestArgs(out, itfRequest);
        out.write(") {\n");

        let itfName;
        //function args
        let argArray = "[";
        if (itfRequest.hasOwnProperty("arg")) {
            const reqArgs = itfRequest.arg;

            for (let i = 0; i < reqArgs.length; i++) {
                const arg = reqArgs[i];
                const argType = arg.$.type;
                const argName = arg.$.name;
                const optional = arg.$.hasOwnProperty("allow-null") && (arg.$["allow-null"] === "true");

                if (argType === "new_id") {
                    itfName = arg.$["interface"];
                }

                if (i !== 0) {
                    argArray += ", ";
                }

                argArray += this[argType](argName, optional).marshallGen;
            }
        }
        argArray += "]";

        if (itfName) {
            out.write(util.format("\t\treturn this._connection._marshallConstructor(this._id, %d, \"%s\", %s);\n", opcode, itfName, argArray));
        } else {
            out.write(util.format("\t\tthis._connection._marshall(this._id, %d, %s);\n", opcode, argArray));
        }

        out.write("\t}\n");
    }

    _parseInterface(out, protocolItf) {
        const itfName = protocolItf.$.name;
        let itfVersion = 1;

        if (protocolItf.$.hasOwnProperty("version")) {
            itfVersion = parseInt(protocolItf.$.version);
        }

        console.log(util.format("Processing interface %s v%d", itfName, itfVersion));

        for (let i = 1; i <= itfVersion; i++) {

            //class docs
            const description = protocolItf.description;
            description.forEach((val) => {
                out.write("\n/**\n");
                if (val.hasOwnProperty("_")) {
                    val._.split("\n").forEach((line) => {
                        out.write(" *" + line + "\n");
                    });
                }
                out.write(" */\n");
            });

            //class
            if (i === 1) {
                out.write(util.format("wfc.%s = class %s extends wfc.WObject {\n", itfName, itfName));
            } else {
                const className = util.format("%sV%d", itfName, i);
                if (i === 2) {
                    out.write(util.format("wfc.%s = class %s extends wfc.%s {\n", className, className, itfName));
                } else {
                    out.write(util.format("wfc.%s = class %s extends wfc.%sV%d {\n", className, className, itfName, i - 1));
                }
            }

            //requests
            if (protocolItf.hasOwnProperty("request")) {
                const itfRequests = protocolItf.request;
                for (let j = 0; j < itfRequests.length; j++) {
                    this._parseItfRequest(out, itfRequests[j], j + 1, i);
                }
            }

            //constructor
            out.write("\n\tconstructor(connection) {\n");
            out.write("\t\tsuper(connection, {\n");
            out.write(util.format("\t\t\tname: \"%s\",\n", itfName));
            out.write(util.format("\t\t\tversion: %d,\n", i));
            //events
            if (protocolItf.hasOwnProperty("event")) {

                const itfEvents = protocolItf.event;
                for (let j = 0; j < itfEvents.length; j++) {
                    const itfEvent = itfEvents[j];
                    let since = "1";
                    if (itfEvent.$.hasOwnProperty("since")) {
                        since = itfEvent.$.since;
                    }

                    if (parseInt(since) <= i) {
                        this._parseItfEvent(out, itfEvent);
                    }
                }
            }
            out.write("\t\t});\n");
            out.write("\t}\n\n");

            //glue event functions
            if (protocolItf.hasOwnProperty("event")) {
                const itfEvents = protocolItf.event;
                for (let j = 0; j < itfEvents.length; j++) {
                    const itfEvent = itfEvents[j];
                    let since = "1";
                    if (itfEvent.$.hasOwnProperty("since")) {
                        since = itfEvent.$.since;
                    }

                    if (parseInt(since) === i) {
                        this._generateIfEventGlue(out, itfEvent, j + 1);
                    }
                }
            }

            out.write("};\n");
        }
    }

    _parseProtocol(jsonProtocol) {
        const protocolName = jsonProtocol.protocol.$.name;
        const out = fs.createWriteStream(util.format("westfield-client-%s.js", protocolName));
        out.on('open', (fd) => {
            out.write("/*\n");
            jsonProtocol.protocol.copyright.forEach((val) => {
                val.split("\n").forEach((line) => {
                    out.write(" *" + line + "\n");
                });
            });
            out.write(" */\n");

            jsonProtocol.protocol.interface.forEach((itf) => {
                this._parseInterface(out, itf);
            });

            console.log('Done');
        });
    }

    parse() {
        fs.readFile(this.protocolFile, (err, data) => {
            if (err) throw err;
            new xml2js.Parser().parseString(data, (err, result) => {
                if (err) throw err;

                //uncomment to see the protocol as json output
                //console.log(util.inspect(result, false, null));

                this._parseProtocol(result);
            });
        });
    }

    constructor(protocolFile) {
        this.protocolFile = protocolFile;
    }
};

const configurationFile = 'generator/config.spec.json';
const configuration = JSON.parse(fs.readFileSync(configurationFile));

configuration.protocols.forEach((protocol) => {
    new wfg.ProtocolParser(protocol).parse();
});
<commit_msg>don't crash on missing description tag<commit_after>"use strict";

const fs = require('fs');
const util = require('util');
const xml2js = require('xml2js');

const wfg = {};

wfg.ProtocolParser = class {

    ["uint"](argName, optional) {
        return {
            jsType: optional ? "?Number" : "Number",
            marshallGen: optional ? util.format("wfc._uintOptional(%s)", argName) : util.format("wfc._uint(%s)", argName)
        };
    }

    ["int"](argName, optional) {
        return {
            jsType: optional ? "?Number" : "Number",
            marshallGen: optional ? util.format("wfc._intOptional(%s)", argName) : util.format("wfc._int(%s)", argName)
        };
    }

    ["fixed"](argName, optional) {
        return {
            jsType: optional ? "?WFixed" : "WFixed",
            marshallGen: optional ? util.format("wfc._fixedOptional(%s)", argName) : util.format("wfc._fixed(%s)", argName)
        };
    }

    ["object"](argName, optional) {
        return {
            jsType: optional ? "?*" : "*",
            marshallGen: optional ? util.format("wfc._objectOptional(%s)", argName) : util.format("wfc._object(%s)", argName)
        };
    }

    ["new_id"](argName, optional) {
        return {
            jsType: "*",
            marshallGen: "wfc._newObject()"
        };
    }

    ["string"](argName, optional) {
        return {
            jsType: optional ? "?string" : "string",
            marshallGen: optional ? util.format("wfc._stringOptional(%s)", argName) : util.format("wfc._string(%s)", argName)
        };
    }

    ["array"](argName, optional) {
        return {
            jsType: optional ? "?ArrayBuffer" : "ArrayBuffer",
            marshallGen: optional ? util.format("wfc._arrayOptional(%s)", argName) : util.format("wfc._array(%s)", argName)
        };
    }

    _generateRequestArgs(out, req) {
        if (req.hasOwnProperty("arg")) {
            const evArgs = req.arg;
            let processedFirstArg = false;
            for (let i = 0; i < evArgs.length; i++) {
                const arg = evArgs[i];
                if (arg.$.type === "new_id") {
                    continue;
                }

                const argName = arg.$.name;
                if (processedFirstArg) {
                    out.write(", ");
                }
                out.write(argName);
                processedFirstArg = true;
            }
        }
    }

    _generateEventArgs(out, ev) {
        if (ev.hasOwnProperty("arg")) {
            const evArgs = ev.arg;
            for (let i = 0; i < evArgs.length; i++) {
                const arg = evArgs[i];
                const argName = arg.$.name;
                if (i !== 0) {
                    out.write(", ");
                }
                out.write(argName);
            }
        }
    }

    _generateIfEventGlue(out, ev, opcode) {

        const evName = ev.$.name;

        out.write(util.format("\t[%d](message){\n", opcode));
        out.write(util.format("\t\tconst args = this._connection._unmarshallArgs(message);\n"));
        out.write(util.format("\t\tthis.iface.%s.call(", evName));

        if (ev.hasOwnProperty("arg")) {
            const evArgs = ev.arg;
            for (let i = 0; i < evArgs.length; i++) {
                if (i !== 0) {
                    out.write(", ");
                }

                const arg = evArgs[i];
                const argType = arg.$.type;
                out.write(util.format("args[%d]", i));
                if (argType === "new_id") {
                    const argItf = arg.$["interface"];
                    out.write(util.format("(\"%s\")", argItf));
                }
            }
        }

        out.write(");\n");
        out.write("\t}\n\n");
    }

    _parseItfEvent(out, itfEvent) {
        const sinceVersion = itfEvent.$.hasOwnProperty("since") ? parseInt(itfEvent.$.since) : 1;
        const evName = itfEvent.$.name;

        //function docs
        const description = itfEvent.description;
        description.forEach((val) => {
            out.write("\n\t\t\t/**\n");
            if (val.hasOwnProperty("_")) {
                val._.split("\n").forEach((line) => {
                    out.write("\t\t\t *" + line + "\n");
                });
            }

            if (itfEvent.hasOwnProperty("arg")) {
                const evArgs = itfEvent.arg;
                out.write("\t\t\t *\n");
                evArgs.forEach((arg) => {
                    const argDescription = arg.$.summary;
                    const argName = arg.$.name;
                    const optional = arg.$.hasOwnProperty("allow-null") && (arg.$["allow-null"] === "true");
                    const argType = arg.$.type;

                    out.write(util.format("\t\t\t * @param {%s} %s %s \n", this[argType](argName, optional).jsType, argName, argDescription));
                });
                out.write("\t\t\t *\n");

            }
            out.write(util.format("\t\t\t * @since %d\n", sinceVersion));
            out.write("\t\t\t *\n");
            out.write("\t\t\t */\n");
        });

        //function
        out.write(util.format("\t\t\t%s(", evName));
        this._generateEventArgs(out, itfEvent);
        out.write(") {},\n");
    }

    _parseItfRequest(out, itfRequest, opcode, itfVersion) {

        const sinceVersion = itfRequest.$.hasOwnProperty("since") ? parseInt(itfRequest.$.since) : 1;
        if (sinceVersion !== itfVersion) {
            return;
        }

        const reqName = itfRequest.$.name;

        //function docs
        const description = itfRequest.description;
        description.forEach((val) => {
            out.write("\n\t/**\n");
            if (val.hasOwnProperty("_")) {
                val._.split("\n").forEach((line) => {
                    out.write("\t *" + line + "\n");
                });
            }

            if (itfRequest.hasOwnProperty("arg")) {
                const reqArgs = itfRequest.arg;
                out.write("\t *\n");
                reqArgs.forEach((arg) => {
                    const argDescription = arg.$.summary;
                    const argName = arg.$.name;
                    const optional = arg.$.hasOwnProperty("allow-null") && (arg.$["allow-null"] === "true");
                    const argType = arg.$.type;
                    if (argType !== "new_id") {
                        out.write(util.format("\t * @param {%s} %s %s \n", this[argType](argName, optional).jsType, argName, argDescription));
                    }
                });

                reqArgs.forEach((arg) => {
                    const argDescription = arg.$.summary;
                    const argItf = arg.$["interface"];
                    const argType = arg.$.type;
                    if (argType === "new_id") {
                        out.write(util.format("\t * @return {%s} %s \n", argItf, argDescription));
                    }
                });
                out.write("\t *\n");

            }
            out.write(util.format("\t * @since %d\n", sinceVersion));
            out.write("\t *\n");
            out.write("\t */\n");
        });

        //function
        out.write(util.format("\t%s(", reqName));
        this._generateRequestArgs(out, itfRequest);
        out.write(") {\n");

        let itfName;
        //function args
        let argArray = "[";
        if (itfRequest.hasOwnProperty("arg")) {
            const reqArgs = itfRequest.arg;

            for (let i = 0; i < reqArgs.length; i++) {
                const arg = reqArgs[i];
                const argType = arg.$.type;
                const argName = arg.$.name;
                const optional = arg.$.hasOwnProperty("allow-null") && (arg.$["allow-null"] === "true");

                if (argType === "new_id") {
                    itfName = arg.$["interface"];
                }

                if (i !== 0) {
                    argArray += ", ";
                }

                argArray += this[argType](argName, optional).marshallGen;
            }
        }
        argArray += "]";

        if (itfName) {
            out.write(util.format("\t\treturn this._connection._marshallConstructor(this._id, %d, \"%s\", %s);\n", opcode, itfName, argArray));
        } else {
            out.write(util.format("\t\tthis._connection._marshall(this._id, %d, %s);\n", opcode, argArray));
        }

        out.write("\t}\n");
    }

    _parseInterface(out, protocolItf) {
        const itfName = protocolItf.$.name;
        let itfVersion = 1;

        if (protocolItf.$.hasOwnProperty("version")) {
            itfVersion = parseInt(protocolItf.$.version);
        }

        console.log(util.format("Processing interface %s v%d", itfName, itfVersion));

        for (let i = 1; i <= itfVersion; i++) {

            //class docs
            const description = protocolItf.description;
            if (description) {
                description.forEach((val) => {
                    out.write("\n/**\n");
                    if (val.hasOwnProperty("_")) {
                        val._.split("\n").forEach((line) => {
                            out.write(" *" + line + "\n");
                        });
                    }
                    out.write(" */\n");
                });
            }

            //class
            if (i === 1) {
                out.write(util.format("wfc.%s = class %s extends wfc.WObject {\n", itfName, itfName));
            } else {
                const className = util.format("%sV%d", itfName, i);
                if (i === 2) {
                    out.write(util.format("wfc.%s = class %s extends wfc.%s {\n", className, className, itfName));
                } else {
                    out.write(util.format("wfc.%s = class %s extends wfc.%sV%d {\n", className, className, itfName, i - 1));
                }
            }

            //requests
            if (protocolItf.hasOwnProperty("request")) {
                const itfRequests = protocolItf.request;
                for (let j = 0; j < itfRequests.length; j++) {
                    this._parseItfRequest(out, itfRequests[j], j + 1, i);
                }
            }

            //constructor
            out.write("\n\tconstructor(connection) {\n");
            out.write("\t\tsuper(connection, {\n");
            out.write(util.format("\t\t\tname: \"%s\",\n", itfName));
            out.write(util.format("\t\t\tversion: %d,\n", i));
            //events
            if (protocolItf.hasOwnProperty("event")) {

                const itfEvents = protocolItf.event;
                for (let j = 0; j < itfEvents.length; j++) {
                    const itfEvent = itfEvents[j];
                    let since = "1";
                    if (itfEvent.$.hasOwnProperty("since")) {
                        since = itfEvent.$.since;
                    }

                    if (parseInt(since) <= i) {
                        this._parseItfEvent(out, itfEvent);
                    }
                }
            }
            out.write("\t\t});\n");
            out.write("\t}\n\n");

            //glue event functions
            if (protocolItf.hasOwnProperty("event")) {
                const itfEvents = protocolItf.event;
                for (let j = 0; j < itfEvents.length; j++) {
                    const itfEvent = itfEvents[j];
                    let since = "1";
                    if (itfEvent.$.hasOwnProperty("since")) {
                        since = itfEvent.$.since;
                    }

                    if (parseInt(since) === i) {
                        this._generateIfEventGlue(out, itfEvent, j + 1);
                    }
                }
            }

            out.write("};\n");
        }
    }

    _parseProtocol(jsonProtocol) {
        const protocolName = jsonProtocol.protocol.$.name;
        const out = fs.createWriteStream(util.format("westfield-client-%s.js", protocolName));
        out.on('open', (fd) => {
            out.write("/*\n");
            jsonProtocol.protocol.copyright.forEach((val) => {
                val.split("\n").forEach((line) => {
                    out.write(" *" + line + "\n");
                });
            });
            out.write(" */\n");

            jsonProtocol.protocol.interface.forEach((itf) => {
                this._parseInterface(out, itf);
            });

            console.log('Done');
        });
    }

    parse() {
        fs.readFile(this.protocolFile, (err, data) => {
            if (err) throw err;
            new xml2js.Parser().parseString(data, (err, result) => {
                if (err) throw err;

                //uncomment to see the protocol as json output
                //console.log(util.inspect(result, false, null));

                this._parseProtocol(result);
            });
        });
    }

    constructor(protocolFile) {
        this.protocolFile = protocolFile;
    }
};

const configurationFile = 'generator/config.json';
const configuration = JSON.parse(fs.readFileSync(configurationFile));

configuration.protocols.forEach((protocol) => {
    new wfg.ProtocolParser(protocol).parse();
});
<|endoftext|>