<commit_before>/* global require console */

var c        = require('mysql-promise')();
let fs       = require('fs');
let poke     = require('./poke-utils');
let request  = require('request-promise-native');
let tripcode = require('tripcode');
let settings = JSON.parse(fs.readFileSync('settings.json'));
let p        = require('util').promisify;

c.configure(settings.db);

let total = 0;

c.query('SELECT COUNT(*) FROM Sets').then(rows => {
	total = rows[0]['COUNT(*)'];
	total = parseInt(total);
	module.exports.total = total;
});

let getAllSets			= async	()							=> await c.query('select * from Sets');
let memesInReplay		= async rid							=> await c.query('select * from memes.Sets where id in (select idset from memes.sets_in_replays where idreplay = ?)', [rid]);
let getReplays			= async manual						=> await c.query('select * from replays where manual = ? order by id desc;', [manual]);
let getChampFromTrip	= async trip						=> await c.query('select * from memes.champs where trip = ? order by id desc;', [trip]);
let getChamps			= async ()							=> await c.query('select * from memes.champs order by wins desc;');
let createChampFromTrip = async (name, trip)				=> await c.query('insert into memes.champs (name, trip) values (?, ?) ', [name || '', trip]);
let addReplay			= async data						=> await c.query('insert into replays (link, description, champ, trip, manual) values (?, ?, ?, ?, ?);', [data.link, data.description, data.champ || '', data.trip || '', data.manual || false]);
let getSetsPage			= async (setPerPage, pageNumber)	=> await c.query('select * from Sets order by id desc limit ? offset ?;', [~~setPerPage, ~~(setPerPage * pageNumber)]);
let addSetToReplay		= async (setid, rid)				=> await c.query('insert into memes.sets_in_replays (idreplay, idset) values (?, ?)', [rid, setid]);
let updateChampAvatar	= async (trip, aid)					=> await c.query('update memes.champs set avatar = ? where trip = ?', [aid, trip]);
let updateChampName		= async (trip, aid)					=> await c.query('update memes.champs set name = ? where trip = ?', [aid, trip]);
let getSetById			= async id							=> await c.query('select * from Sets where id = ?', [id]);
let getSetByNo			= async no							=> await c.query('select * from Sets limit 1 offset ?', [no]);

let registerChampResult = async (battleData, hasWon) => {
	let replayurl;

	try {
		let b = await request.get('https://play.pokemonshowdown.com/~~showdown/action.php?act=ladderget&user=' + encodeURIComponent(battleData.champ.showdown_name));
		b = JSON.parse(b.substr(1));
		b = ~~b.filter(e => e.formatid == 'gen7ou')[0].elo;
		// no need to sync
		c.query('update memes.champs set elo = ? where trip = ?', [b, battleData.champ.champ_trip]);
		// might be useful to store this
		c.query('update memes.champs set showdown_name = ? where trip = ?', [battleData.champ.showdown_name, battleData.champ.champ_trip]);
	}
	catch(e) {
		console.log(e);
	}
	if (hasWon) {
		poke.saveReplay(battleData.champ.champ_battle, () => {
			console.log('replay saved (' + battleData.champ.champ_battle + ')');
		});
		replayurl = 'http://replay.pokemonshowdown.com/' + battleData.roomid;
	}

	let inc = hasWon ? 'wins' : 'loses';
	let champ = await getChampFromTrip(battleData.champ.champ_trip);
	if (champ.length == 0) {
		await createChampFromTrip(battleData.champ.champ_name, battleData.champ.champ_trip)
	}

	await c.query('update memes.champs set ' + inc + ' = ' + inc + ' + 1 where trip = ?', [battleData.champ.champ_trip]);
	updateChampAvatar(battleData.champ.champ_trip, battleData.champ.avatar.substr(battleData.champ.avatar[0] == '#'));
	updateChampName(battleData.champ.champ_trip, battleData.champ_name);
	if (!hasWon)
		return;
	let info = await addReplay({
		link: replayurl,
		description: 'Automatically uploaded replay. Champ: ' + battleData.champ.champ_name + ' ' + battleData.champ.champ_trip,
		champ: battleData.champ.champ_name,
		trip: battleData.champ.champ_trip
	});

	for(var i = 0; i < battleData.memes.length; ++i) {
		let sets = await getSetsByPropertyExact({name: battleData.memes[i].name});
		if (sets.length >= 1) {
			sets = sets[0];
			addSetToReplay(sets.id, info.insertId);
		}
	}
}

let getSetsByProperty = async props => {
	let querystr = 'select * from Sets where ';
	let data = [];
	querystr += Object.keys(props).map(i => '?? like ?').join(' and ');
	Object.keys(props).forEach(i => data.push(i, '%' + props[i] + '%'));
	return await c.query(querystr, data);
}

let getSetsByPropertyExact = async props => {
	let querystr = 'select * from Sets where ';
	let data = [];
	querystr += Object.keys(props).map(i => '?? like ?').join(' and ');
	Object.keys(props).forEach(i => data.push(i, props[i]));
	return await c.query(querystr, data);
}

let getSetsByName = async name => {
	let pattern = '%' + name + '%';
	let sets = await c.query('select * from Sets where name like ? or species like ? or move_1 like ? or move_2 like ? or move_3 like ? or move_4 like ?',
							 [pattern,
							  pattern, pattern, pattern, pattern,
							  pattern]);
	return sets;
}

let createNewSet = async (request) => {
	let row = {};
	row.hash = tripcode(request.body.trip);
	row.format = "gen7ou";
	let formats = ["gen7ou", "gen7anythinggoes", "ubers", "uu", "ru",
				   "nu", "pu", "lc", "cap"];
	if (formats.includes(request.body.format))
		row.format = request.body.format;
	row.creator = request.body.creat.substr(0, 23);
	row.description = request.body.desc.substr(0, 230);
	row.date_added = +new Date();

	let pok = poke.parseSet(request.body.set);
	for(var i in pok)
		row[i] = pok[i];
	let data = ['date_added', 'format', 'creator', 'hash', 'name', 'species',
				'gender', 'item', 'ability', 'shiny', 'level', 'happiness', 'nature',
				'move_1', 'move_2', 'move_3', 'move_4', 'hp_ev', 'atk_ev', 'def_ev',
				'spa_ev', 'spd_ev', 'spe_ev', 'hp_iv', 'atk_iv', 'def_iv', 'spa_iv',
				'spd_iv', 'spe_iv', 'description'];
	let data_arr = [];
	let querystr =
		'INSERT INTO Sets (' + data.map(attr => '??').join(', ')
		+ ') VALUES (' + data.map(attr => '?').join(', ') + ')';

	data_arr.push(...data, ...data.map(attr => row[attr]));

	let rows = await c.query(querystr, data_arr);
	module.exports.total++;
	let set = await getSetById(rows.insertId);
	set = poke.formatSetFromRow(set[0]);
	let errors = await poke.checkSet(set);
	if (errors) {
		deleteSet({params: {id: set.id},
				   body: {trip: settings.admin_pass}});
		throw errors;
	} else {
		return rows;
	}
}

let updateSet = async (request) => {
	let row = await getSetById(request.params.id);
	row = row[0];
	if (request.body.trip == '' || (request.body.trip != settings.admin_pass && row.hash != tripcode(request.body.trip)))
		throw 'Wrong tripcode';

	row.format = "gen7ou";
	let formats = ["gen7ou", "gen7anythinggoes", "ubers", "uu", "ru",
				   "nu", "pu", "lc", "cap"];
	if (formats.includes(request.body.format))
		row.format = request.body.format;
	row.description = request.body.desc.substr(0, 230);
	row.date_added = +new Date();

	try {
		let pok = poke.parseSet(request.body.set);
		for(var i in pok)
			row[i] = pok[i];
		let set = poke.formatSetFromRow(row);
		let errors = await poke.checkSet(set);
		if (errors) {
			throw errors;
		}
	}
	catch(e) {
		throw e;
	}

	let data = ['date_added', 'format', 'creator', 'hash', 'name', 'species',
				'gender', 'item', 'ability', 'shiny', 'level', 'happiness', 'nature',
				'move_1', 'move_2', 'move_3', 'move_4', 'hp_ev', 'atk_ev', 'def_ev',
				'spa_ev', 'spd_ev', 'spe_ev', 'hp_iv', 'atk_iv', 'def_iv', 'spa_iv',
				'spd_iv', 'spe_iv', 'description'];

	let data_arr = [];

	let querystr = 'UPDATE Sets SET ';

	querystr += data.map(attr => '?? = ?').join(', ');
	querystr += ' WHERE id = ?';

	data.map(attr => data_arr.push(attr, row[attr]));
	data_arr.push(request.params.id);
	let rows = await c.query(querystr, data_arr);
	return rows.info;
}

let deleteSet = async request => {
	let row = await getSetById(request.params.id);
	row = row[0];
	if (request.body.trip == '' ||
		(request.body.trip != settings.admin_pass &&
		 row.hash != tripcode(request.body.trip)))
		throw 'Wrong tripcode';
	let rows = await c.query('DELETE FROM Sets WHERE id = ?', [request.params.id]);
	module.exports.total--;
	return rows.info;
}

module.exports.getAllSets				= getAllSets;
module.exports.memesInReplay			= memesInReplay;
module.exports.getReplays				= getReplays;
module.exports.getChampFromTrip			= getChampFromTrip;
module.exports.getChamps				= getChamps;
module.exports.createChampFromTrip		= createChampFromTrip;
module.exports.addReplay				= addReplay;
module.exports.getSetsPage				= getSetsPage;
module.exports.addSetToReplay			= addSetToReplay;
module.exports.updateChampAvatar		= updateChampAvatar;
module.exports.registerChampResult		= registerChampResult;
module.exports.getSetById				= getSetById;
module.exports.getSetByNo				= getSetByNo;
module.exports.getSetsByProperty		= getSetsByProperty;
module.exports.getSetsByPropertyExact	= getSetsByPropertyExact;
module.exports.getSetsByName			= getSetsByName;
module.exports.createNewSet				= createNewSet;
module.exports.updateSet				= updateSet;
module.exports.deleteSet				= deleteSet;
module.exports.c                        = c;
<commit_msg>A mere typo<commit_after>/* global require console */

var c        = require('mysql-promise')();
let fs       = require('fs');
let poke     = require('./poke-utils');
let request  = require('request-promise-native');
let tripcode = require('tripcode');
let settings = JSON.parse(fs.readFileSync('settings.json'));
let p        = require('util').promisify;

c.configure(settings.db);

let total = 0;

c.query('SELECT COUNT(*) FROM Sets').then(rows => {
	total = rows[0]['COUNT(*)'];
	total = parseInt(total);
	module.exports.total = total;
});

let getAllSets			= async	()							=> await c.query('select * from Sets');
let memesInReplay		= async rid							=> await c.query('select * from memes.Sets where id in (select idset from memes.sets_in_replays where idreplay = ?)', [rid]);
let getReplays			= async manual						=> await c.query('select * from replays where manual = ? order by id desc;', [manual]);
let getChampFromTrip	= async trip						=> await c.query('select * from memes.champs where trip = ? order by id desc;', [trip]);
let getChamps			= async ()							=> await c.query('select * from memes.champs order by wins desc;');
let createChampFromTrip = async (name, trip)				=> await c.query('insert into memes.champs (name, trip) values (?, ?) ', [name || '', trip]);
let addReplay			= async data						=> await c.query('insert into replays (link, description, champ, trip, manual) values (?, ?, ?, ?, ?);', [data.link, data.description, data.champ || '', data.trip || '', data.manual || false]);
let getSetsPage			= async (setPerPage, pageNumber)	=> await c.query('select * from Sets order by id desc limit ? offset ?;', [~~setPerPage, ~~(setPerPage * pageNumber)]);
let addSetToReplay		= async (setid, rid)				=> await c.query('insert into memes.sets_in_replays (idreplay, idset) values (?, ?)', [rid, setid]);
let updateChampAvatar	= async (trip, aid)					=> await c.query('update memes.champs set avatar = ? where trip = ?', [aid, trip]);
let updateChampName		= async (trip, aid)					=> {
	console.log("UPDTATECHAMPNAME", trip, aid);
	return await c.query('update memes.champs set name = ? where trip = ?', [aid, trip]);
}
let getSetById			= async id							=> await c.query('select * from Sets where id = ?', [id]);
let getSetByNo			= async no							=> await c.query('select * from Sets limit 1 offset ?', [no]);

let registerChampResult = async (battleData, hasWon) => {
	let replayurl;

	try {
		let b = await request.get('https://play.pokemonshowdown.com/~~showdown/action.php?act=ladderget&user=' + encodeURIComponent(battleData.champ.showdown_name));
		b = JSON.parse(b.substr(1));
		b = ~~b.filter(e => e.formatid == 'gen7ou')[0].elo;
		// no need to sync
		c.query('update memes.champs set elo = ? where trip = ?', [b, battleData.champ.champ_trip]);
		// might be useful to store this
		c.query('update memes.champs set showdown_name = ? where trip = ?', [battleData.champ.showdown_name, battleData.champ.champ_trip]);
	}
	catch(e) {
		console.log(e);
	}
	if (hasWon) {
		poke.saveReplay(battleData.champ.champ_battle, () => {
			console.log('replay saved (' + battleData.champ.champ_battle + ')');
		});
		replayurl = 'http://replay.pokemonshowdown.com/' + battleData.roomid;
	}

	let inc = hasWon ? 'wins' : 'loses';
	let champ = await getChampFromTrip(battleData.champ.champ_trip);
	if (champ.length == 0) {
		await createChampFromTrip(battleData.champ.champ_name, battleData.champ.champ_trip)
	}

	await c.query('update memes.champs set ' + inc + ' = ' + inc + ' + 1 where trip = ?', [battleData.champ.champ_trip]);
	console.log(battleData);
	updateChampAvatar(battleData.champ.champ_trip, battleData.champ.avatar.substr(battleData.champ.avatar[0] == '#'));
	updateChampName(battleData.champ.champ_trip, battleData.champ.champ_name);
	if (!hasWon)
		return;
	let info = await addReplay({
		link: replayurl,
		description: 'Automatically uploaded replay. Champ: ' + battleData.champ.champ_name + ' ' + battleData.champ.champ_trip,
		champ: battleData.champ.champ_name,
		trip: battleData.champ.champ_trip
	});

	for(var i = 0; i < battleData.memes.length; ++i) {
		let sets = await getSetsByPropertyExact({name: battleData.memes[i].name});
		if (sets.length >= 1) {
			sets = sets[0];
			addSetToReplay(sets.id, info.insertId);
		}
	}
}

let getSetsByProperty = async props => {
	let querystr = 'select * from Sets where ';
	let data = [];
	querystr += Object.keys(props).map(i => '?? like ?').join(' and ');
	Object.keys(props).forEach(i => data.push(i, '%' + props[i] + '%'));
	return await c.query(querystr, data);
}

let getSetsByPropertyExact = async props => {
	let querystr = 'select * from Sets where ';
	let data = [];
	querystr += Object.keys(props).map(i => '?? like ?').join(' and ');
	Object.keys(props).forEach(i => data.push(i, props[i]));
	return await c.query(querystr, data);
}

let getSetsByName = async name => {
	let pattern = '%' + name + '%';
	let sets = await c.query('select * from Sets where name like ? or species like ? or move_1 like ? or move_2 like ? or move_3 like ? or move_4 like ?',
							 [pattern,
							  pattern, pattern, pattern, pattern,
							  pattern]);
	return sets;
}

let createNewSet = async (request) => {
	let row = {};
	row.hash = tripcode(request.body.trip);
	row.format = "gen7ou";
	let formats = ["gen7ou", "gen7anythinggoes", "ubers", "uu", "ru",
				   "nu", "pu", "lc", "cap"];
	if (formats.includes(request.body.format))
		row.format = request.body.format;
	row.creator = request.body.creat.substr(0, 23);
	row.description = request.body.desc.substr(0, 230);
	row.date_added = +new Date();

	let pok = poke.parseSet(request.body.set);
	for(var i in pok)
		row[i] = pok[i];
	let data = ['date_added', 'format', 'creator', 'hash', 'name', 'species',
				'gender', 'item', 'ability', 'shiny', 'level', 'happiness', 'nature',
				'move_1', 'move_2', 'move_3', 'move_4', 'hp_ev', 'atk_ev', 'def_ev',
				'spa_ev', 'spd_ev', 'spe_ev', 'hp_iv', 'atk_iv', 'def_iv', 'spa_iv',
				'spd_iv', 'spe_iv', 'description'];
	let data_arr = [];
	let querystr =
		'INSERT INTO Sets (' + data.map(attr => '??').join(', ')
		+ ') VALUES (' + data.map(attr => '?').join(', ') + ')';

	data_arr.push(...data, ...data.map(attr => row[attr]));

	let rows = await c.query(querystr, data_arr);
	module.exports.total++;
	let set = await getSetById(rows.insertId);
	set = poke.formatSetFromRow(set[0]);
	let errors = await poke.checkSet(set);
	if (errors) {
		deleteSet({params: {id: set.id},
				   body: {trip: settings.admin_pass}});
		throw errors;
	} else {
		return rows;
	}
}

let updateSet = async (request) => {
	let row = await getSetById(request.params.id);
	row = row[0];
	if (request.body.trip == '' || (request.body.trip != settings.admin_pass && row.hash != tripcode(request.body.trip)))
		throw 'Wrong tripcode';

	row.format = "gen7ou";
	let formats = ["gen7ou", "gen7anythinggoes", "ubers", "uu", "ru",
				   "nu", "pu", "lc", "cap"];
	if (formats.includes(request.body.format))
		row.format = request.body.format;
	row.description = request.body.desc.substr(0, 230);
	row.date_added = +new Date();

	try {
		let pok = poke.parseSet(request.body.set);
		for(var i in pok)
			row[i] = pok[i];
		let set = poke.formatSetFromRow(row);
		let errors = await poke.checkSet(set);
		if (errors) {
			throw errors;
		}
	}
	catch(e) {
		throw e;
	}

	let data = ['date_added', 'format', 'creator', 'hash', 'name', 'species',
				'gender', 'item', 'ability', 'shiny', 'level', 'happiness', 'nature',
				'move_1', 'move_2', 'move_3', 'move_4', 'hp_ev', 'atk_ev', 'def_ev',
				'spa_ev', 'spd_ev', 'spe_ev', 'hp_iv', 'atk_iv', 'def_iv', 'spa_iv',
				'spd_iv', 'spe_iv', 'description'];

	let data_arr = [];

	let querystr = 'UPDATE Sets SET ';

	querystr += data.map(attr => '?? = ?').join(', ');
	querystr += ' WHERE id = ?';

	data.map(attr => data_arr.push(attr, row[attr]));
	data_arr.push(request.params.id);
	let rows = await c.query(querystr, data_arr);
	return rows.info;
}

let deleteSet = async request => {
	let row = await getSetById(request.params.id);
	row = row[0];
	if (request.body.trip == '' ||
		(request.body.trip != settings.admin_pass &&
		 row.hash != tripcode(request.body.trip)))
		throw 'Wrong tripcode';
	let rows = await c.query('DELETE FROM Sets WHERE id = ?', [request.params.id]);
	module.exports.total--;
	return rows.info;
}

module.exports.getAllSets				= getAllSets;
module.exports.memesInReplay			= memesInReplay;
module.exports.getReplays				= getReplays;
module.exports.getChampFromTrip			= getChampFromTrip;
module.exports.getChamps				= getChamps;
module.exports.createChampFromTrip		= createChampFromTrip;
module.exports.addReplay				= addReplay;
module.exports.getSetsPage				= getSetsPage;
module.exports.addSetToReplay			= addSetToReplay;
module.exports.updateChampAvatar		= updateChampAvatar;
module.exports.registerChampResult		= registerChampResult;
module.exports.getSetById				= getSetById;
module.exports.getSetByNo				= getSetByNo;
module.exports.getSetsByProperty		= getSetsByProperty;
module.exports.getSetsByPropertyExact	= getSetsByPropertyExact;
module.exports.getSetsByName			= getSetsByName;
module.exports.createNewSet				= createNewSet;
module.exports.updateSet				= updateSet;
module.exports.deleteSet				= deleteSet;
module.exports.c                        = c;
<|endoftext|>


<commit_before>var should = require("should");
var path = require("path");
var fs = require("fs");
var vm = require("vm");
var Test = require("mocha/lib/test");

var webpack = require("../lib/webpack");

describe("TestCases", function() {
	var casesPath = path.join(__dirname, "cases");
	var categories = fs.readdirSync(casesPath);
	categories = categories.map(function(cat) {
		return {
			name: cat,
			tests: fs.readdirSync(path.join(casesPath, cat)).filter(function(folder) {
				return folder.indexOf("_") < 0;
			})
		};
	});
	categories.forEach(function(category) {
		describe(category.name, function() {
			category.tests.forEach(function(testName) {
				var suite = describe(testName, function() {});
				it("should compile " + testName, function(done) {
					var testDirectory = path.join(casesPath, category.name, testName);
					var outputDirectory = path.join(__dirname, "js", category.name, testName);
					webpack({
						context: casesPath,
						entry: "./" + category.name + "/" + testName +"/index",
						target: "async-node",
						devtool: "eval",
						output: {
							pathinfo: true,
							path: outputDirectory,
							filename: "bundle.js"
						},
						module: {
							loaders: [
								{ test: /\.json$/, loader: "json" },
								{ test: /\.coffee$/, loader: "coffee" },
								{ test: /\.jade$/, loader: "jade" }
							]
						}
					}, function(err, stats) {
						if(err) return done(err);
						var jsonStats = stats.toJson();
						if(checkArrayExpectation(testDirectory, jsonStats, "error", "Error", done)) return;
						if(checkArrayExpectation(testDirectory, jsonStats, "warning", "Warning", done)) return;
						var exportedTest = 0;
						function _it(title, fn) {
							var test = new Test(title, fn);
							suite.addTest(test);
							exportedTest++;
							return test;
						}
						function _require(module) {
							if(module.substr(0, 2) === "./") {
								var p = path.join(outputDirectory, module);
								var fn = vm.runInThisContext("(function(require, module, exports, __dirname, it) {" + fs.readFileSync(p, "utf-8") + "\n})", p);
								var module = { exports: {} };
								fn.call(module.exports, _require, module, module.exports, outputDirectory, _it);
								return module.exports;
							} else return require(module);
						}
						_require("./bundle.js");
						if(exportedTest === 0) return done(new Error("No tests exported by test case"));
						done();
					});
				});
			});
		});
	});
	function checkArrayExpectation(testDirectory, object, kind, upperCaseKind, done) {
		var array = object[kind+"s"].slice().sort();
		if(fs.existsSync(path.join(testDirectory, kind+ "s.js"))) {
			var expected = require(path.join(testDirectory, kind + "s.js"));
			if(expected.length < array.length)
				return done(new Error("More " + kind + "s while compiling than expected:\n\n" + array.join("\n\n"))), true;
			else if(expected.length > array.length)
				return done(new Error("Less " + kind + "s while compiling than expected:\n\n" + array.join("\n\n"))), true;
			for(var i = 0; i < array.length; i++) {
				if(Array.isArray(expected[i])) {
					for(var j = 0; j < expected[i].length; j++) {
						if(!expected[i][j].test(array[i]))
							return done(new Error(upperCaseKind + " " + i + ": " + array[i] + " doesn't match " + expected[i][j].toString())), true;
					}
				} else if(!expected[i].test(array[i]))
					return done(new Error(upperCaseKind + " " + i + ": " + array[i] + " doesn't match " + expected[i].toString())), true;
			}
		} else if(array.length > 0) {
			return done(new Error(upperCaseKind + "s while compiling:\n\n" + array.join("\n\n"))), true;
		}
	}
});<commit_msg>test optimize combinations<commit_after>var should = require("should");
var path = require("path");
var fs = require("fs");
var vm = require("vm");
var Test = require("mocha/lib/test");

var webpack = require("../lib/webpack");

describe("TestCases", function() {
	var casesPath = path.join(__dirname, "cases");
	var categories = fs.readdirSync(casesPath);
	categories = categories.map(function(cat) {
		return {
			name: cat,
			tests: fs.readdirSync(path.join(casesPath, cat)).filter(function(folder) {
				return folder.indexOf("_") < 0;
			})
		};
	});
	[
		{ name: "normal" },
		{ name: "minimized", optimize: { minimize: true } },
		{ name: "deduped", optimize: { dedupe: true } },
		{ name: "minimized-deduped", optimize: { minimize: true, dedupe: true } },
		{ name: "optimized", optimize: { minimize: true, dedupe: true, occurenceOrder: true } }
	].forEach(function(config) {
		describe(config.name, function() {
			categories.forEach(function(category) {
				describe(category.name, function() {
					category.tests.forEach(function(testName) {
						var suite = describe(testName, function() {});
						it("should compile " + testName, function(done) {
							var testDirectory = path.join(casesPath, category.name, testName);
							var outputDirectory = path.join(__dirname, "js", config.name, category.name, testName);
							webpack({
								context: casesPath,
								entry: "./" + category.name + "/" + testName +"/index",
								target: "async-node",
								devtool: "eval",
								output: {
									pathinfo: true,
									path: outputDirectory,
									filename: "bundle.js"
								},
								optimize: config.optimize,
								module: {
									loaders: [
										{ test: /\.json$/, loader: "json" },
										{ test: /\.coffee$/, loader: "coffee" },
										{ test: /\.jade$/, loader: "jade" }
									]
								}
							}, function(err, stats) {
								if(err) return done(err);
								var jsonStats = stats.toJson();
								if(checkArrayExpectation(testDirectory, jsonStats, "error", "Error", done)) return;
								if(checkArrayExpectation(testDirectory, jsonStats, "warning", "Warning", done)) return;
								var exportedTest = 0;
								function _it(title, fn) {
									var test = new Test(title, fn);
									suite.addTest(test);
									exportedTest++;
									return test;
								}
								function _require(module) {
									if(module.substr(0, 2) === "./") {
										var p = path.join(outputDirectory, module);
										var fn = vm.runInThisContext("(function(require, module, exports, __dirname, it) {" + fs.readFileSync(p, "utf-8") + "\n})", p);
										var module = { exports: {} };
										fn.call(module.exports, _require, module, module.exports, outputDirectory, _it);
										return module.exports;
									} else return require(module);
								}
								_require("./bundle.js");
								if(exportedTest === 0) return done(new Error("No tests exported by test case"));
								done();
							});
						});
					});
				});
			});
		});
	});
	function checkArrayExpectation(testDirectory, object, kind, upperCaseKind, done) {
		var array = object[kind+"s"].slice().sort();
		if(fs.existsSync(path.join(testDirectory, kind+ "s.js"))) {
			var expected = require(path.join(testDirectory, kind + "s.js"));
			if(expected.length < array.length)
				return done(new Error("More " + kind + "s while compiling than expected:\n\n" + array.join("\n\n"))), true;
			else if(expected.length > array.length)
				return done(new Error("Less " + kind + "s while compiling than expected:\n\n" + array.join("\n\n"))), true;
			for(var i = 0; i < array.length; i++) {
				if(Array.isArray(expected[i])) {
					for(var j = 0; j < expected[i].length; j++) {
						if(!expected[i][j].test(array[i]))
							return done(new Error(upperCaseKind + " " + i + ": " + array[i] + " doesn't match " + expected[i][j].toString())), true;
					}
				} else if(!expected[i].test(array[i]))
					return done(new Error(upperCaseKind + " " + i + ": " + array[i] + " doesn't match " + expected[i].toString())), true;
			}
		} else if(array.length > 0) {
			return done(new Error(upperCaseKind + "s while compiling:\n\n" + array.join("\n\n"))), true;
		}
	}
});<|endoftext|>


<commit_before>import React from 'react';
import { shallow, mount } from 'enzyme';
import Button from '../src/Button';
import mocker from './helper/new-mocker';

describe('Button', () => {
  let wrapper;

  beforeEach(() => {
    wrapper = shallow(<Button waves="light">Stuff</Button>);
  });

  test('renders', () => {
    expect(wrapper).toMatchSnapshot();
  });

  test('should output a button', () => {
    expect(wrapper.find('button')).toHaveLength(1);
  });

  test('should output a component with btn class', () => {
    expect(wrapper.find('.btn')).toHaveLength(1);
  });

  test('should apply waves', () => {
    expect(wrapper.find('.waves-effect')).toHaveLength(1);
  });

  test('should apply large styles', () => {
    wrapper = shallow(<Button large>Stuff</Button>);
    expect(wrapper.find('.btn-large')).toHaveLength(1);
  });

  test('should apply small styles', () => {
    wrapper = shallow(<Button small>Stuff</Button>);
    expect(wrapper.find('.btn-small')).toHaveLength(1);
  });

  test('should apply floating styles', () => {
    wrapper = shallow(<Button floating>Stuff</Button>);
    expect(wrapper.find('.btn-floating')).toHaveLength(1);
  });

  test('should apply flat styles', () => {
    wrapper = shallow(<Button flat>Stuff</Button>);
    expect(wrapper.find('.btn-flat')).toHaveLength(1);
  });

  test('should apply FAB hover', () => {
    wrapper = shallow(<Button fab="vertical">Stuff</Button>);
    wrapper.simulate('hover');
    expect(wrapper.find('.fixed-action-btn active'));
  });

  test('should apply FAB click-only', () => {
    wrapper = shallow(
      <Button fab="horizontal" fabClickOnly>
        Stuff
      </Button>
    );
    wrapper.simulate('click');
    expect(wrapper.find('.fixed-action-btn active'));
  });

  describe('with a disabled prop', () => {
    let wrapper = mount(<Button disabled>Stuff</Button>);
    test('should have a disabled class', () => {
      expect(wrapper.find('.disabled')).toHaveLength(1);
    });

    test('should have a disabled attribute', () => {
      expect(wrapper.prop('disabled')).toEqual(true);
    });
  });

  describe('with a tooltip', () => {
    const tooltipInitMock = jest.fn();
    const tooltipInstanceDestroyMock = jest.fn();
    const tooltipMock = {
      init: (el, options) => {
        tooltipInitMock(options);
        return {
          destroy: tooltipInstanceDestroyMock
        };
      }
    };
    const restore = mocker('Tooltip', tooltipMock);
    const tooltip = 'Hello';
    const tooltipOptions = {
      position: 'top',
      delay: 50
    };

    beforeEach(() => {
      tooltipInitMock.mockClear();
    });

    afterAll(() => {
      restore();
    });

    test('initializes Button with tooltip', () => {
      wrapper = shallow(<Button tooltip={tooltip}>Stuff</Button>);
      expect(tooltipInitMock).toHaveBeenCalled();
    });

    test('initializes Button with tooltip options', () => {
      wrapper = shallow(
        <Button tooltip={tooltip} tooltipOptions={tooltipOptions}>
          Stuff
        </Button>
      );
      expect(tooltipInitMock).toHaveBeenCalledWith(tooltipOptions);
    });

    test('Destroyed when unmounted', () => {
      wrapper = shallow(<Button tooltip={tooltip}>Stuff</Button>);
      wrapper.unmount();
      expect(tooltipInstanceDestroyMock).toHaveBeenCalled();
    });
  });
});
<commit_msg>Add tests for FloatingActionButton in Button component<commit_after>import React from 'react';
import { shallow, mount } from 'enzyme';
import Button from '../src/Button';
import mocker from './helper/new-mocker';

describe('Button', () => {
  let wrapper;

  beforeEach(() => {
    wrapper = shallow(<Button waves="light">Stuff</Button>);
  });

  test('renders', () => {
    expect(wrapper).toMatchSnapshot();
  });

  test('should output a button', () => {
    expect(wrapper.find('button')).toHaveLength(1);
  });

  test('should output a component with btn class', () => {
    expect(wrapper.find('.btn')).toHaveLength(1);
  });

  test('should apply waves', () => {
    expect(wrapper.find('.waves-effect')).toHaveLength(1);
  });

  test('should apply large styles', () => {
    wrapper = shallow(<Button large>Stuff</Button>);
    expect(wrapper.find('.btn-large')).toHaveLength(1);
  });

  test('should apply small styles', () => {
    wrapper = shallow(<Button small>Stuff</Button>);
    expect(wrapper.find('.btn-small')).toHaveLength(1);
  });

  test('should apply floating styles', () => {
    wrapper = shallow(<Button floating>Stuff</Button>);
    expect(wrapper.find('.btn-floating')).toHaveLength(1);
  });

  test('should apply flat styles', () => {
    wrapper = shallow(<Button flat>Stuff</Button>);
    expect(wrapper.find('.btn-flat')).toHaveLength(1);
  });

  test('should apply FAB hover', () => {
    wrapper = shallow(<Button fab="vertical">Stuff</Button>);
    wrapper.simulate('hover');
    expect(wrapper.find('.fixed-action-btn active'));
  });

  test('should apply FAB click-only', () => {
    wrapper = shallow(
      <Button fab="horizontal" fabClickOnly>
        Stuff
      </Button>
    );
    wrapper.simulate('click');
    expect(wrapper.find('.fixed-action-btn active'));
  });

  describe('with a disabled prop', () => {
    let wrapper = mount(<Button disabled>Stuff</Button>);
    test('should have a disabled class', () => {
      expect(wrapper.find('.disabled')).toHaveLength(1);
    });

    test('should have a disabled attribute', () => {
      expect(wrapper.prop('disabled')).toEqual(true);
    });
  });

  describe('with a tooltip', () => {
    const tooltipInitMock = jest.fn();
    const tooltipInstanceDestroyMock = jest.fn();
    const tooltipMock = {
      init: (el, options) => {
        tooltipInitMock(options);
        return {
          destroy: tooltipInstanceDestroyMock
        };
      }
    };
    const restore = mocker('Tooltip', tooltipMock);
    const tooltip = 'Hello';
    const tooltipOptions = {
      position: 'top',
      delay: 50
    };

    beforeEach(() => {
      tooltipInitMock.mockClear();
    });

    afterAll(() => {
      restore();
    });

    test('initializes Button with tooltip', () => {
      wrapper = shallow(<Button tooltip={tooltip}>Stuff</Button>);
      expect(tooltipInitMock).toHaveBeenCalled();
    });

    test('initializes Button with tooltip options', () => {
      wrapper = shallow(
        <Button tooltip={tooltip} tooltipOptions={tooltipOptions}>
          Stuff
        </Button>
      );
      expect(tooltipInitMock).toHaveBeenCalledWith(tooltipOptions);
    });

    test('destroyed when unmounted', () => {
      wrapper = shallow(<Button tooltip={tooltip}>Stuff</Button>);
      wrapper.unmount();
      expect(tooltipInstanceDestroyMock).toHaveBeenCalled();
    });
  });

  describe('with fixed action button', () => {
    const fabInitMock = jest.fn();
    const fabInstanceDestroyMock = jest.fn();
    const fabMock = {
      init: (el, options) => {
        fabInitMock(options);
        return {
          destroy: fabInstanceDestroyMock
        };
      }
    };
    const restore = mocker('FloatingActionButton', fabMock);
    const fab = 'vertical';
    let wrapper;

    beforeEach(() => {
      fabInitMock.mockClear();
      wrapper = mount(
        <Button
          floating
          fab={fab}
          className="red"
          large
          style={{
            bottom: '45px',
            right: '24px'
          }}
        >
          <Button floating icon="insert_chart" className="red" />
          <Button floating icon="format_quote" className="yellow darken-1" />
          <Button floating icon="publish" className="green" />
          <Button floating icon="attach_file" className="blue" />
        </Button>
      );
    });

    afterAll(() => {
      restore();
    });

    test('initializes FloatingActionButton instance', () => {
      expect(fabInitMock).toHaveBeenCalled();
    });
    test('destroys FloatingActionButton instance when unmounted', () => {
      wrapper.unmount();
      expect(fabInstanceDestroyMock).toHaveBeenCalled();
    });
  });
});
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

// Do some basic tests.
couchTests.basics = function(debug) {
  var result = JSON.parse(CouchDB.request("GET", "/").responseText);
  T(result.couchdb == "Welcome");

  var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
  db.deleteDb();

  // bug COUCHDB-100: DELETE on non-existent DB returns 500 instead of 404
  db.deleteDb();

  db.createDb();

  // PUT on existing DB should return 412 instead of 500
  xhr = CouchDB.request("PUT", "/test_suite_db/");
  T(xhr.status == 412);
  if (debug) debugger;

  // creating a new DB should return Location header
  // and it should work for dbs with slashes (COUCHDB-411)
  var dbnames = ["test_suite_db", "test_suite_db%2Fwith_slashes"];
  dbnames.forEach(function(dbname) {
    xhr = CouchDB.request("DELETE", "/" + dbname);
    xhr = CouchDB.request("PUT", "/" + dbname);
    TEquals(dbname,
      xhr.getResponseHeader("Location").substr(-dbname.length),
      "should return Location header to newly created document");
    TEquals(CouchDB.protocol,
      xhr.getResponseHeader("Location").substr(0, CouchDB.protocol.length),
      "should return absolute Location header to newly created document");
  });

  // Get the database info, check the db_name
  T(db.info().db_name == "test_suite_db");
  T(CouchDB.allDbs().indexOf("test_suite_db") != -1);

  // Get the database info, check the doc_count
  T(db.info().doc_count == 0);

  // create a document and save it to the database
  var doc = {_id:"0",a:1,b:1};
  var result = db.save(doc);

  T(result.ok==true); // return object has an ok member with a value true
  T(result.id); // the _id of the document is set.
  T(result.rev); // the revision id of the document is set.

  // Verify the input doc is now set with the doc id and rev
  // (for caller convenience).
  T(doc._id == result.id && doc._rev == result.rev);

  var id = result.id; // save off the id for later

  // make sure the revs_info status is good
  var doc = db.open(id, {revs_info:true});
  T(doc._revs_info[0].status == "available");

  // make sure you can do a seq=true option
  var doc = db.open(id, {local_seq:true});
  T(doc._local_seq == 1);

  // Create some more documents.
  // Notice the use of the ok member on the return result.
  T(db.save({_id:"1",a:2,b:4}).ok);
  T(db.save({_id:"2",a:3,b:9}).ok);
  T(db.save({_id:"3",a:4,b:16}).ok);

  // Check the database doc count
  T(db.info().doc_count == 4);

  // Test a simple map functions

  // create a map function that selects all documents whose "a" member
  // has a value of 4, and then returns the document's b value.
  var mapFunction = function(doc){
    if (doc.a==4)
      emit(null, doc.b);
  };

  results = db.query(mapFunction);

  // verify only one document found and the result value (doc.b).
  T(results.total_rows == 1 && results.rows[0].value == 16);

  // reopen document we saved earlier
  existingDoc = db.open(id);

  T(existingDoc.a==1);

  //modify and save
  existingDoc.a=4;
  db.save(existingDoc);

  // redo the map query
  results = db.query(mapFunction);

  // the modified document should now be in the results.
  T(results.total_rows == 2);

  // write 2 more documents
  T(db.save({a:3,b:9}).ok);
  T(db.save({a:4,b:16}).ok);

  results = db.query(mapFunction);

  // 1 more document should now be in the result.
  T(results.total_rows == 3);
  T(db.info().doc_count == 6);

  var reduceFunction = function(keys, values){
    return sum(values);
  };

  results = db.query(mapFunction, reduceFunction);

  T(results.rows[0].value == 33);

  // delete a document
  T(db.deleteDoc(existingDoc).ok);

  // make sure we can't open the doc
  T(db.open(existingDoc._id) == null);

  results = db.query(mapFunction);

  // 1 less document should now be in the results.
  T(results.total_rows == 2);
  T(db.info().doc_count == 5);

  // make sure we can still open the old rev of the deleted doc
  T(db.open(existingDoc._id, {rev: existingDoc._rev}) != null);
  // make sure restart works
  T(db.ensureFullCommit().ok);
  restartServer();

  // make sure we can still open
  T(db.open(existingDoc._id, {rev: existingDoc._rev}) != null);

  // test that the POST response has a Location header
  var xhr = CouchDB.request("POST", "/test_suite_db", {
    body: JSON.stringify({"foo":"bar"}),
    headers: {"Content-Type": "application/json"}
  });
  var resp = JSON.parse(xhr.responseText);
  T(resp.ok);
  var loc = xhr.getResponseHeader("Location");
  T(loc, "should have a Location header");
  var locs = loc.split('/');
  T(locs[4] == resp.id);
  T(locs[3] == "test_suite_db");

  // test that that POST's with an _id aren't overriden with a UUID.
  var xhr = CouchDB.request("POST", "/test_suite_db", {
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({"_id": "oppossum", "yar": "matey"})
  });
  var resp = JSON.parse(xhr.responseText);
  T(resp.ok);
  T(resp.id == "oppossum");
  var doc = db.open("oppossum");
  T(doc.yar == "matey");

  // document put's should return a Location header
  var xhr = CouchDB.request("PUT", "/test_suite_db/newdoc", {
    body: JSON.stringify({"a":1})
  });
  TEquals("/test_suite_db/newdoc",
    xhr.getResponseHeader("Location").substr(-21),
    "should return Location header to newly created document");
  TEquals(CouchDB.protocol,
    xhr.getResponseHeader("Location").substr(0, CouchDB.protocol.length),
    "should return absolute Location header to newly created document");

  // deleting a non-existent doc should be 404
  xhr = CouchDB.request("DELETE", "/test_suite_db/doc-does-not-exist");
  T(xhr.status == 404);

  // Check for invalid document members
  bad_docs = [
    ["goldfish", {"_zing": 4}],
    ["zebrafish", {"_zoom": "hello"}],
    ["mudfish", {"zane": "goldfish", "_fan": "something smells delicious"}],
    ["tastyfish", {"_bing": {"wha?": "soda can"}}]
  ];
  var test_doc = function(info) {
  var data = JSON.stringify(info[1]);
    xhr = CouchDB.request("PUT", "/test_suite_db/" + info[0], {body: data});
    T(xhr.status == 500);
    result = JSON.parse(xhr.responseText);
    T(result.error == "doc_validation");

    xhr = CouchDB.request("POST", "/test_suite_db/", {
      headers: {"Content-Type": "application/json"},
      body: data
    });
    T(xhr.status == 500);
    result = JSON.parse(xhr.responseText);
    T(result.error == "doc_validation");
  };
  bad_docs.forEach(test_doc);

  // Check some common error responses.
  // PUT body not an object
  xhr = CouchDB.request("PUT", "/test_suite_db/bar", {body: "[]"});
  T(xhr.status == 400);
  result = JSON.parse(xhr.responseText);
  T(result.error == "bad_request");
  T(result.reason == "Document must be a JSON object");

  // Body of a _bulk_docs is not an object
  xhr = CouchDB.request("POST", "/test_suite_db/_bulk_docs", {body: "[]"});
  T(xhr.status == 400);
  result = JSON.parse(xhr.responseText);
  T(result.error == "bad_request");
  T(result.reason == "Request body must be a JSON object");

  // Body of an _all_docs  multi-get is not a {"key": [...]} structure.
  xhr = CouchDB.request("POST", "/test_suite_db/_all_docs", {body: "[]"});
  T(xhr.status == 400);
  result = JSON.parse(xhr.responseText);
  T(result.error == "bad_request");
  T(result.reason == "Request body must be a JSON object");
  var data = "{\"keys\": 1}";
  xhr = CouchDB.request("POST", "/test_suite_db/_all_docs", {body:data});
  T(xhr.status == 400);
  result = JSON.parse(xhr.responseText);
  T(result.error == "bad_request");
  T(result.reason == "`keys` member must be a array.");

  // oops, the doc id got lost in code nirwana
  xhr = CouchDB.request("DELETE", "/test_suite_db/?rev=foobarbaz");
  TEquals(400, xhr.status, "should return a bad request");
  result = JSON.parse(xhr.responseText);
  TEquals("bad_request", result.error);
  TEquals("You tried to DELETE a database with a ?=rev parameter. Did you mean to DELETE a document instead?", result.reason);
};
<commit_msg>HTTP proxy handler.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

// Do some basic tests.
couchTests.basics = function(debug) {
  var result = JSON.parse(CouchDB.request("GET", "/").responseText);
  T(result.couchdb == "Welcome");

  var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
  db.deleteDb();

  // bug COUCHDB-100: DELETE on non-existent DB returns 500 instead of 404
  db.deleteDb();

  db.createDb();

  // PUT on existing DB should return 412 instead of 500
  xhr = CouchDB.request("PUT", "/test_suite_db/");
  T(xhr.status == 412);
  if (debug) debugger;

  // creating a new DB should return Location header
  // and it should work for dbs with slashes (COUCHDB-411)
  var dbnames = ["test_suite_db", "test_suite_db%2Fwith_slashes"];
  dbnames.forEach(function(dbname) {
    xhr = CouchDB.request("DELETE", "/" + dbname);
    xhr = CouchDB.request("PUT", "/" + dbname);
    TEquals(dbname,
      xhr.getResponseHeader("Location").substr(-dbname.length),
      "should return Location header to newly created document");
    TEquals(CouchDB.protocol,
      xhr.getResponseHeader("Location").substr(0, CouchDB.protocol.length),
      "should return absolute Location header to newly created document");
  });

  // Get the database info, check the db_name
  T(db.info().db_name == "test_suite_db");
  T(CouchDB.allDbs().indexOf("test_suite_db") != -1);

  // Get the database info, check the doc_count
  T(db.info().doc_count == 0);

  // create a document and save it to the database
  var doc = {_id:"0",a:1,b:1};
  var result = db.save(doc);

  T(result.ok==true); // return object has an ok member with a value true
  T(result.id); // the _id of the document is set.
  T(result.rev); // the revision id of the document is set.

  // Verify the input doc is now set with the doc id and rev
  // (for caller convenience).
  T(doc._id == result.id && doc._rev == result.rev);

  var id = result.id; // save off the id for later

  // make sure the revs_info status is good
  var doc = db.open(id, {revs_info:true});
  T(doc._revs_info[0].status == "available");

  // make sure you can do a seq=true option
  var doc = db.open(id, {local_seq:true});
  T(doc._local_seq == 1);

  // Create some more documents.
  // Notice the use of the ok member on the return result.
  T(db.save({_id:"1",a:2,b:4}).ok);
  T(db.save({_id:"2",a:3,b:9}).ok);
  T(db.save({_id:"3",a:4,b:16}).ok);

  // Check the database doc count
  T(db.info().doc_count == 4);

  // Test a simple map functions

  // create a map function that selects all documents whose "a" member
  // has a value of 4, and then returns the document's b value.
  var mapFunction = function(doc){
    if (doc.a==4)
      emit(null, doc.b);
  };

  results = db.query(mapFunction);

  // verify only one document found and the result value (doc.b).
  T(results.total_rows == 1 && results.rows[0].value == 16);

  // reopen document we saved earlier
  existingDoc = db.open(id);

  T(existingDoc.a==1);

  //modify and save
  existingDoc.a=4;
  db.save(existingDoc);

  // redo the map query
  results = db.query(mapFunction);

  // the modified document should now be in the results.
  T(results.total_rows == 2);

  // write 2 more documents
  T(db.save({a:3,b:9}).ok);
  T(db.save({a:4,b:16}).ok);

  results = db.query(mapFunction);

  // 1 more document should now be in the result.
  T(results.total_rows == 3);
  T(db.info().doc_count == 6);

  var reduceFunction = function(keys, values){
    return sum(values);
  };

  results = db.query(mapFunction, reduceFunction);

  T(results.rows[0].value == 33);

  // delete a document
  T(db.deleteDoc(existingDoc).ok);

  // make sure we can't open the doc
  T(db.open(existingDoc._id) == null);

  results = db.query(mapFunction);

  // 1 less document should now be in the results.
  T(results.total_rows == 2);
  T(db.info().doc_count == 5);

  // make sure we can still open the old rev of the deleted doc
  T(db.open(existingDoc._id, {rev: existingDoc._rev}) != null);
  // make sure restart works
  T(db.ensureFullCommit().ok);
  restartServer();

  // make sure we can still open
  T(db.open(existingDoc._id, {rev: existingDoc._rev}) != null);

  // test that the POST response has a Location header
  var xhr = CouchDB.request("POST", "/test_suite_db", {
    body: JSON.stringify({"foo":"bar"}),
    headers: {"Content-Type": "application/json"}
  });
  var resp = JSON.parse(xhr.responseText);
  T(resp.ok);
  var loc = xhr.getResponseHeader("Location");
  T(loc, "should have a Location header");
  var locs = loc.split('/');
  T(locs[locs.length-1] == resp.id);
  T(locs[locs.length-2] == "test_suite_db");

  // test that that POST's with an _id aren't overriden with a UUID.
  var xhr = CouchDB.request("POST", "/test_suite_db", {
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({"_id": "oppossum", "yar": "matey"})
  });
  var resp = JSON.parse(xhr.responseText);
  T(resp.ok);
  T(resp.id == "oppossum");
  var doc = db.open("oppossum");
  T(doc.yar == "matey");

  // document put's should return a Location header
  var xhr = CouchDB.request("PUT", "/test_suite_db/newdoc", {
    body: JSON.stringify({"a":1})
  });
  TEquals("/test_suite_db/newdoc",
    xhr.getResponseHeader("Location").substr(-21),
    "should return Location header to newly created document");
  TEquals(CouchDB.protocol,
    xhr.getResponseHeader("Location").substr(0, CouchDB.protocol.length),
    "should return absolute Location header to newly created document");

  // deleting a non-existent doc should be 404
  xhr = CouchDB.request("DELETE", "/test_suite_db/doc-does-not-exist");
  T(xhr.status == 404);

  // Check for invalid document members
  bad_docs = [
    ["goldfish", {"_zing": 4}],
    ["zebrafish", {"_zoom": "hello"}],
    ["mudfish", {"zane": "goldfish", "_fan": "something smells delicious"}],
    ["tastyfish", {"_bing": {"wha?": "soda can"}}]
  ];
  var test_doc = function(info) {
  var data = JSON.stringify(info[1]);
    xhr = CouchDB.request("PUT", "/test_suite_db/" + info[0], {body: data});
    T(xhr.status == 500);
    result = JSON.parse(xhr.responseText);
    T(result.error == "doc_validation");

    xhr = CouchDB.request("POST", "/test_suite_db/", {
      headers: {"Content-Type": "application/json"},
      body: data
    });
    T(xhr.status == 500);
    result = JSON.parse(xhr.responseText);
    T(result.error == "doc_validation");
  };
  bad_docs.forEach(test_doc);

  // Check some common error responses.
  // PUT body not an object
  xhr = CouchDB.request("PUT", "/test_suite_db/bar", {body: "[]"});
  T(xhr.status == 400);
  result = JSON.parse(xhr.responseText);
  T(result.error == "bad_request");
  T(result.reason == "Document must be a JSON object");

  // Body of a _bulk_docs is not an object
  xhr = CouchDB.request("POST", "/test_suite_db/_bulk_docs", {body: "[]"});
  T(xhr.status == 400);
  result = JSON.parse(xhr.responseText);
  T(result.error == "bad_request");
  T(result.reason == "Request body must be a JSON object");

  // Body of an _all_docs  multi-get is not a {"key": [...]} structure.
  xhr = CouchDB.request("POST", "/test_suite_db/_all_docs", {body: "[]"});
  T(xhr.status == 400);
  result = JSON.parse(xhr.responseText);
  T(result.error == "bad_request");
  T(result.reason == "Request body must be a JSON object");
  var data = "{\"keys\": 1}";
  xhr = CouchDB.request("POST", "/test_suite_db/_all_docs", {body:data});
  T(xhr.status == 400);
  result = JSON.parse(xhr.responseText);
  T(result.error == "bad_request");
  T(result.reason == "`keys` member must be a array.");

  // oops, the doc id got lost in code nirwana
  xhr = CouchDB.request("DELETE", "/test_suite_db/?rev=foobarbaz");
  TEquals(400, xhr.status, "should return a bad request");
  result = JSON.parse(xhr.responseText);
  TEquals("bad_request", result.error);
  TEquals("You tried to DELETE a database with a ?=rev parameter. Did you mean to DELETE a document instead?", result.reason);
};
<|endoftext|>


<commit_before>var Cleverbot = require('cleverbot-node');
var Discordbot = require("discord.js");
var fs = require("fs")
var config = require("./config.json")
var availableAccounts = 0
var DBots = [new Discordbot.Client(),new Discordbot.Client(),new Discordbot.Client(),new Discordbot.Client(),new Discordbot.Client()]
var CBots = [new Cleverbot,new Cleverbot,new Cleverbot,new Cleverbot,new Cleverbot]
  , i = 0
  , callback = function callback(resp){
      setTimeout(function(str1, str2) {
        DBots[i].startTyping(config.botChannel);
        CBots[i].write(resp['message'],callback);
        DBots[i = ( ( i + 1 ) % availableAccounts)].sendMessage(config.botChannel, resp['message']);
      }, 2500);
      DBots[i].stopTyping(config.botChannel);
    };

Cleverbot.prepare(function(){
  callback({message:thing})
});

var things = config.startMessages

var thing = things[Math.floor(Math.random()*things.length)];

DBots[0].on("ready", function(){
  availableAccounts++
  console.log("[info] Bot 1 logged in as " + DBots[0].user.name + "#" + DBots[0].user.discriminator + " (" + DBots[0].user.id + ")")
});

DBots[1].on("ready", function(){
  availableAccounts++
  console.log("[info] Bot 2 logged in as " + DBots[1].user.name + "#" + DBots[1].user.discriminator + " (" + DBots[1].user.id + ")")
});

DBots[2].on("ready", function(){
  availableAccounts++
  console.log("[info] Bot 3 logged in as " + DBots[2].user.name + "#" + DBots[2].user.discriminator + " (" + DBots[2].user.id + ")")
});

DBots[3].on("ready", function(){
  availableAccounts++
  console.log("[info] Bot 4 logged in as " + DBots[3].user.name + "#" + DBots[3].user.discriminator + " (" + DBots[3].user.id + ")")
});

DBots[4].on("ready", function(){
  availableAccounts++
  console.log("[info] Bot 5 logged in as " + DBots[4].user.name + "#" + DBots[4].user.discriminator + " (" + DBots[4].user.id + ")")
});

DBots[0].on("message", function(message){
  if(message.sender.id === config.owner){
    if(startMSG != ""){
    fs.readFile("./config.json", "utf8" , function(err,ctx){
      var parts = ctx.split(config.startMessage)
        fs.writeFile("./config.json", parts[0] + startMSG + parts[1], function(){
          process.exit()
        });
      });
    }
    else{
      process.exit()
    }
  }
});

DBots[0].loginWithToken(config.bot1);
DBots[1].loginWithToken(config.bot2);
DBots[2].loginWithToken(config.bot3);
DBots[3].loginWithToken(config.bot4);
DBots[4].loginWithToken(config.bot5);
<commit_msg>yeah no fuck that<commit_after>var Cleverbot = require('cleverbot-node');
var Discordbot = require("discord.js");
var fs = require("fs")
var config = require("./config.json")
var availableAccounts = 0
var DBots = [new Discordbot.Client(),new Discordbot.Client(),new Discordbot.Client(),new Discordbot.Client(),new Discordbot.Client()]
var CBots = [new Cleverbot,new Cleverbot,new Cleverbot,new Cleverbot,new Cleverbot]
  , i = 0
  , callback = function callback(resp){
      setTimeout(function(str1, str2) {
        DBots[i].startTyping(config.botChannel);
        CBots[i].write(resp['message'],callback);
        DBots[i = ( ( i + 1 ) % availableAccounts)].sendMessage(config.botChannel, resp['message']);
      }, 2500);
      DBots[i].stopTyping(config.botChannel);
    };

Cleverbot.prepare(function(){
  callback({message:thing})
});

var things = config.startMessages

var thing = things[Math.floor(Math.random()*things.length)];

DBots[0].on("ready", function(){
  availableAccounts++
  console.log("[info] Bot 1 logged in as " + DBots[0].user.name + "#" + DBots[0].user.discriminator + " (" + DBots[0].user.id + ")")
});

DBots[1].on("ready", function(){
  availableAccounts++
  console.log("[info] Bot 2 logged in as " + DBots[1].user.name + "#" + DBots[1].user.discriminator + " (" + DBots[1].user.id + ")")
});

DBots[2].on("ready", function(){
  availableAccounts++
  console.log("[info] Bot 3 logged in as " + DBots[2].user.name + "#" + DBots[2].user.discriminator + " (" + DBots[2].user.id + ")")
});

DBots[3].on("ready", function(){
  availableAccounts++
  console.log("[info] Bot 4 logged in as " + DBots[3].user.name + "#" + DBots[3].user.discriminator + " (" + DBots[3].user.id + ")")
});

DBots[4].on("ready", function(){
  availableAccounts++
  console.log("[info] Bot 5 logged in as " + DBots[4].user.name + "#" + DBots[4].user.discriminator + " (" + DBots[4].user.id + ")")
});

DBots[0].loginWithToken(config.bot1);
DBots[1].loginWithToken(config.bot2);
DBots[2].loginWithToken(config.bot3);
DBots[3].loginWithToken(config.bot4);
DBots[4].loginWithToken(config.bot5);
<|endoftext|>


<commit_before>"use strict";
var assert = require('assert');

var Minesweeper = function(s) {
  var lines = s.split('\n');
  var xy = lines[0].split(' ');
  var x = xy[0] | 0;
  var y = xy[1] | 0;

  this.height = x;
  this.width = y;

  var grid = new Array(x);
  for (var i=0;i<x;++i) {
    grid[i] = new Array(y);
    for (var j=0;j<y;++j) {
      grid[i][j] = lines[i+1][j] === '*';
    }
  }

  this.at = function(i,j) {
    return grid[j][i];
  };

  return this;
};

describe('minesweeper', function() {

  var grid1 = '4 4\n*...\n....\n..*.\n....\n';
  var grid2 = '3 5\n**...\n.....\n.*...\n';

  describe('can be created from string', function() {
    it('can create from string', function() {
      var grid = new Minesweeper(grid1);
      assert(grid);
    });

    it('width and height are read correctly', function() {
      var grid = new Minesweeper(grid2);
      assert.equal(3,grid.height);
      assert.equal(5,grid.width);
    });

    it('has a grid', function() {
      var grid = new Minesweeper(grid2);
      assert(grid.at(0,0));
      assert(grid.at(1,0));
      assert(!grid.at(2,0));
    });

    it('says surrounding mines', function() {
      var grid = new Minesweeper(grid1);
      assert.equal('*', grid.val(0,0));
      assert.equal('2', grid.val(1,1));
    });
  });
});
<commit_msg>first part of the test is now passing, maybe that test did too much<commit_after>"use strict";
var assert = require('assert');

var Minesweeper = function(s) {
  var lines = s.split('\n');
  var xy = lines[0].split(' ');
  var x = xy[0] | 0;
  var y = xy[1] | 0;

  this.height = x;
  this.width = y;

  var grid = new Array(x);
  for (var i=0;i<x;++i) {
    grid[i] = new Array(y);
    for (var j=0;j<y;++j) {
      grid[i][j] = lines[i+1][j] === '*';
    }
  }

  this.at = function(i,j) {
    return grid[j][i];
  };

  this.val = function(i,j) {
    if (this.at(i,j)) {
      return '*';
    }
  };

  return this;
};

describe('minesweeper', function() {

  var grid1 = '4 4\n*...\n....\n..*.\n....\n';
  var grid2 = '3 5\n**...\n.....\n.*...\n';

  describe('can be created from string', function() {
    it('can create from string', function() {
      var grid = new Minesweeper(grid1);
      assert(grid);
    });

    it('width and height are read correctly', function() {
      var grid = new Minesweeper(grid2);
      assert.equal(3,grid.height);
      assert.equal(5,grid.width);
    });

    it('has a grid', function() {
      var grid = new Minesweeper(grid2);
      assert(grid.at(0,0));
      assert(grid.at(1,0));
      assert(!grid.at(2,0));
    });

    it('says surrounding mines', function() {
      var grid = new Minesweeper(grid1);
      assert.equal('*', grid.val(0,0));
      assert.equal('2', grid.val(1,1));
    });
  });
});
<|endoftext|>


<commit_before>function updateTotalForms(prefix, inc) {
    var $totalForms = $('#id_' + prefix + '-TOTAL_FORMS'),
        $maxForms = $('#id_' + prefix + '-MAX_NUM_FORMS'),
        inc = inc || 1,
        num = parseInt($totalForms.val(), 10) + inc;
    if ($maxForms.length && $maxForms.val().length) {
        var maxNum = parseInt($maxForms.val(), 10);
        if (num > maxNum) {
            return num - 1;
        }
    }
    $totalForms.val(num);
    return num;
}

/**
 * zAutoFormset: handles Django formsets with autocompletion like a champ!
 * by cvan
 */

(function($) {

$.zAutoFormset = function(o) {

    o = $.extend({
        delegate: document.body,   // Delegate (probably some nearby parent).

        forms: null,               // Where all the forms live (maybe a
).

        extraForm: '.extra-form',  // Selector for element that contains the
                                   // HTML for extra-form template.

        maxForms: 3,               // Maximum number of forms allowed.

        prefix: 'form',            // Formset prefix (Django default: 'form').

        hiddenField: null,         // This is the name of a (hidden) field
                                   // that will contain the value of the
                                   // formPK for each newly added form.

        removeClass: 'remove',     // Class for button triggering form removal.

        formSelector: 'li',        // Selector for each form container.

        formPK: 'id',              // Primary key for initial forms.

        src: null,                 // Source URL of JSON search results.

        input: null,               // Input field for autocompletion search.

        searchField: 'q',          // Name of form field for search query.

        minSearchLength: 3,        // Minimum character length for queries.

        width: 300,                // Width (pixels) of autocomplete dropdown.

        addedCB: null,             // Callback for each new form added.

        removedCB: null,           // Callback for each form removed.

        autocomplete: null         // Custom handler you can provide to handle
                                   // autocompletion yourself.
    }, o);

    var $delegate = $(o.delegate),
        $forms = o.forms ? $delegate.find(o.forms) : $delegate,
        $extraForm = $delegate.find(o.extraForm),
        formsetPrefix = o.prefix,
        hiddenField = o.hiddenField,
        removeClass = o.removeClass,
        formSelector = o.formSelector,
        formPK = o.formPK,
        src = o.src || $delegate.attr('data-src'),
        $input = o.input ? $(o.input) : $delegate.find('input.autocomplete'),
        searchField = o.searchField,
        minLength = o.minSearchLength,
        $maxForms = $('#id_' + formsetPrefix + '-MAX_NUM_FORMS'),
        width = o.width,
        addedCB = o.addedCB,
        removedCB = o.removedCB,
        autocomplete = o.autocomplete,
        maxItems;

        if ($maxForms.length && $maxForms.val()) {
            maxItems = parseInt($maxForms.val(), 10);
        } else if (o.maxForms) {
            maxItems = o.maxForms;
        }

    function findItem(item) {
        if (item) {
            var $item = $forms.find('[name$=-' + hiddenField + '][value=' + item[formPK] + ']');
            if ($item.length) {
                var $f = $item.closest(formSelector);
                return {'exists': true, 'visible': $f.is(':visible'), 'item': $f};
            }
        }
        return {'exists': false, 'visible': false};
    }

    function clearInput() {
        $input.val('');
        $input.removeAttr('data-item');
        toggleInput();
    }

    function toggleInput() {
        if (!maxItems) {
            return;
        }
        var $visible = $forms.find(formSelector + ':visible').length;
        if ($visible >= maxItems) {
            $input.attr('disabled', true).slideUp();
            $('.ui-autocomplete').hide();
        } else if ($visible < maxItems) {
            $input.filter(':disabled').removeAttr('disabled').slideDown();
        }
    }

    function added() {
        var item = JSON.parse($input.attr('data-item'));

        // Check if this item has already been added.
        var dupe = findItem(item);
        if (dupe.exists) {
            if (!dupe.visible) {
                // Undelete the item.
                var $item = dupe.item;
                $item.find('input[name$=-DELETE]').removeAttr('checked');
                $item.slideDown(toggleInput);
            }
            clearInput();
            return;
        }

        clearInput();

        var formId = updateTotalForms(formsetPrefix, 1) - 1,
            emptyForm = $extraForm.html().replace(/__prefix__/g, formId);

        var $f;
        if (addedCB) {
            $f = addedCB(emptyForm, item);
        } else {
            $f = $(f);
        }

        $f.hide().appendTo($forms).slideDown(toggleInput);

        // Update hidden field.
        $forms.find(formSelector + ':last [name$=-' + hiddenField + ']')
              .val(item[formPK]);
    }

    function removed(el) {
        el.slideUp(toggleInput);
        // Mark as deleted.
        el.find('input[name$=-DELETE]').attr('checked', true);

        if (removedCB) {
            removedCB(el);
        }

        // If this was not an initial form (i.e., an extra form), delete the
        // form and decrement the TOTAL_FORMS count.
        if (!el.find('input[name$=-' + formPK + ']').length) {
            el.remove();
            updateTotalForms(formsetPrefix, -1);
        }
    }

    if (autocomplete) {
        autocomplete();
    } else {
        $input.autocomplete({
            minLength: minLength,
            width: width,
            source: function(request, response) {
                var d = {};
                d[searchField] = request.term;
                $.getJSON(src, d, response);
            },
            focus: function(event, ui) {
                event.preventDefault();
                $input.val(ui.item.name);
            },
            select: function(event, ui) {
                event.preventDefault();
                if (ui.item) {
                    $input.val(ui.item.name);
                    $input.attr('data-item', JSON.stringify(ui.item));
                    added();
                }
            }
        }).data('autocomplete')._renderItem = function(ul, item) {
            if (!findItem(item).visible) {
                var $a = $(format('{1}',
                                  [item.icons['32'], item.name]));
                return $('
').data('item.autocomplete', item)
                                .append($a).appendTo(ul);
            }
        };
    }

    toggleInput();

    $delegate.delegate('.' + removeClass, 'click', _pd(function() {
        removed($(this).closest(formSelector));
    }));

};

})(jQuery);
<commit_msg>Fix autocomplete in formset (bug 1214598).<commit_after>function updateTotalForms(prefix, inc) {
    var $totalForms = $('#id_' + prefix + '-TOTAL_FORMS'),
        $maxForms = $('#id_' + prefix + '-MAX_NUM_FORMS'),
        inc = inc || 1,
        num = parseInt($totalForms.val(), 10) + inc;
    if ($maxForms.length && $maxForms.val().length) {
        var maxNum = parseInt($maxForms.val(), 10);
        if (num > maxNum) {
            return num - 1;
        }
    }
    $totalForms.val(num);
    return num;
}

/**
 * zAutoFormset: handles Django formsets with autocompletion like a champ!
 * by cvan
 */

(function($) {

$.zAutoFormset = function(o) {

    o = $.extend({
        delegate: document.body,   // Delegate (probably some nearby parent).

        forms: null,               // Where all the forms live (maybe a
).

        extraForm: '.extra-form',  // Selector for element that contains the
                                   // HTML for extra-form template.

        maxForms: 3,               // Maximum number of forms allowed.

        prefix: 'form',            // Formset prefix (Django default: 'form').

        hiddenField: null,         // This is the name of a (hidden) field
                                   // that will contain the value of the
                                   // formPK for each newly added form.

        removeClass: 'remove',     // Class for button triggering form removal.

        formSelector: 'li',        // Selector for each form container.

        formPK: 'id',              // Primary key for initial forms.

        src: null,                 // Source URL of JSON search results.

        input: null,               // Input field for autocompletion search.

        searchField: 'q',          // Name of form field for search query.

        minSearchLength: 3,        // Minimum character length for queries.

        width: 300,                // Width (pixels) of autocomplete dropdown.

        addedCB: null,             // Callback for each new form added.

        removedCB: null,           // Callback for each form removed.

        autocomplete: null         // Custom handler you can provide to handle
                                   // autocompletion yourself.
    }, o);

    var $delegate = $(o.delegate),
        $forms = o.forms ? $delegate.find(o.forms) : $delegate,
        $extraForm = $delegate.find(o.extraForm),
        formsetPrefix = o.prefix,
        hiddenField = o.hiddenField,
        removeClass = o.removeClass,
        formSelector = o.formSelector,
        formPK = o.formPK,
        src = o.src || $delegate.attr('data-src'),
        $input = o.input ? $(o.input) : $delegate.find('input.autocomplete'),
        searchField = o.searchField,
        minLength = o.minSearchLength,
        $maxForms = $('#id_' + formsetPrefix + '-MAX_NUM_FORMS'),
        width = o.width,
        addedCB = o.addedCB,
        removedCB = o.removedCB,
        autocomplete = o.autocomplete,
        maxItems;

        if ($maxForms.length && $maxForms.val()) {
            maxItems = parseInt($maxForms.val(), 10);
        } else if (o.maxForms) {
            maxItems = o.maxForms;
        }

    function findItem(item) {
        if (item) {
            var $item = $forms.find('[name$=-' + hiddenField + '][value=' + item[formPK] + ']');
            if ($item.length) {
                var $f = $item.closest(formSelector);
                return {'exists': true, 'visible': $f.is(':visible'), 'item': $f};
            }
        }
        return {'exists': false, 'visible': false};
    }

    function clearInput() {
        $input.val('');
        $input.removeAttr('data-item');
        toggleInput();
    }

    function toggleInput() {
        if (!maxItems) {
            return;
        }
        var $visible = $forms.find(formSelector + ':visible').length;
        if ($visible >= maxItems) {
            $input.attr('disabled', true).slideUp();
            $('.ui-autocomplete').hide();
        } else if ($visible < maxItems) {
            $input.filter(':disabled').removeAttr('disabled').slideDown();
        }
    }

    function added() {
        var item = JSON.parse($input.attr('data-item'));

        // Check if this item has already been added.
        var dupe = findItem(item);
        if (dupe.exists) {
            if (!dupe.visible) {
                // Undelete the item.
                var $item = dupe.item;
                $item.find('input[name$=-DELETE]').removeAttr('checked');
                $item.slideDown(toggleInput);
            }
            clearInput();
            return;
        }

        clearInput();

        var formId = updateTotalForms(formsetPrefix, 1) - 1,
            emptyForm = $extraForm.html().replace(/__prefix__/g, formId);

        var $f;
        if (addedCB) {
            $f = addedCB(emptyForm, item);
        } else {
            $f = $(f);
        }

        $f.hide().appendTo($forms).slideDown(toggleInput);

        // Update hidden field.
        $forms.find(formSelector + ':last [name$=-' + hiddenField + ']')
              .val(item[formPK]);
    }

    function removed(el) {
        el.slideUp(toggleInput);
        // Mark as deleted.
        el.find('input[name$=-DELETE]').attr('checked', true);

        if (removedCB) {
            removedCB(el);
        }

        // If this was not an initial form (i.e., an extra form), delete the
        // form and decrement the TOTAL_FORMS count.
        if (!el.find('input[name$=-' + formPK + ']').length) {
            el.remove();
            updateTotalForms(formsetPrefix, -1);
        }
    }

    function _renderItem(ul, item) {
        if (!findItem(item).visible) {
            var $a = $(format('{1}',
                              [item.icons['32'], item.name]));
            return $('
').data('item.autocomplete', item)
                            .append($a).appendTo(ul);
        }
    }

    function _renderItemData(ul, item) {
        var rendered = _renderItem( ul, item );

        // We are overwriting `_renderItem` in some places and return
        // nothing in case of duplicate filtering.
        if (rendered) {
            rendered.data("ui-autocomplete-item", item);
        }
    }

    if (autocomplete) {
        autocomplete();
    } else {
        $input.autocomplete({
            minLength: minLength,
            width: width,
            source: function(request, response) {
                var d = {};
                d[searchField] = request.term;
                $.getJSON(src, d, response);
            },
            focus: function(event, ui) {
                event.preventDefault();
                $input.val(ui.item.name);
            },
            select: function(event, ui) {
                event.preventDefault();
                if (ui.item) {
                    $input.val(ui.item.name);
                    $input.attr('data-item', JSON.stringify(ui.item));
                    added();
                }
            }
        }).data('uiAutocomplete')._renderMenu = function(ul, items) {
            // Overwrite _renderMenu to patch in our custom `_renderItemData`
            // and `_renderItem` to allow for our custom list-filter.
            $.each(items, function(index, item) {
                _renderItemData(ul, item);
            });
        };
    }

    toggleInput();

    $delegate.delegate('.' + removeClass, 'click', _pd(function() {
        removed($(this).closest(formSelector));
    }));

};

})(jQuery);
<|endoftext|>


<commit_before>/**
 A **BuildableModel** is a {{#crossLink "Model"}}{{/crossLink}} that provides a fluent API through which you can
 build it incrementally.

 ## Usage

 A BuildableModel containing ten textured boxes with random sizes and positions:

 ````javascript
 var model = new xeogl.BuildableModel();

 // Add a BoxGeometry asset
 buildableModel.asset("boxGeometry", {
     type: "xeogl.BoxGeometry"
 });

 // Add a PhongMaterial asset
 buildableModel.asset("gridMaterial", {
     type: "xeogl.PhongMaterial",
     ambient: [0.9, 0.3, 0.9],
     shininess: 30,
     diffuseMap: {
         src: "textures/diffuse/gridMaterial.jpg"
     }
 });

 // Set the BoxGeometry asset as the current geometry
 buildableModel.geometry("boxGeometry");

 // Set the PhongMaterial asset as the current material
 buildableModel.material("gridMaterial");

 // Build ten entities with random sizes and positions,
 // that each get the current geometry and material
 for (var i = 0; i < 10; i++) {

     buildableModel.scale(Math.random() * 10 + 1, Math.random() * 10 + 1, Math.random() * 10 + 1);
     buildableModel.pos(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50);

     buildableModel.entity();
 }
 ````

 @class BuildableModel
 @module xeogl
 @submodule models
 @constructor
 @param [scene] {Scene} Parent {{#crossLink "Scene"}}Scene{{/crossLink}} - creates this BuildableModel in the default
 {{#crossLink "Scene"}}Scene{{/crossLink}} when omitted.
 @param [cfg] {*} Configs
 @param [cfg.id] {String} Optional ID, unique among all components in the parent {{#crossLink "Scene"}}Scene{{/crossLink}},
 generated automatically when omitted.
 @param [cfg.meta] {String:Object} Optional map of user-defined metadata to attach to this BuildableModel.
 @param [cfg.transform] {Number|String|Transform} A Local-to-World-space (modelling) {{#crossLink "Transform"}}{{/crossLink}} to attach to this BuildableModel.
 Must be within the same {{#crossLink "Scene"}}{{/crossLink}} as this BuildableModel. Internally, the given
 {{#crossLink "Transform"}}{{/crossLink}} will be inserted above each top-most {{#crossLink "Transform"}}Transform{{/crossLink}}
 that the BuildableModel attaches to its {{#crossLink "Entity"}}Entities{{/crossLink}}.
 @extends Model
 */
(function () {

    "use strict";

    xeogl.BuildableModel = xeogl.Model.extend({

        type: "xeogl.BuildableModel",

        _init: function (cfg) {

            this._super(cfg);

            this._material = null;
            this._geometry = null;
            this._pos = xeogl.math.vec3([0, 0, 0]);
            this._scale = xeogl.math.vec3([1, 1, 1]);
            this._angles = xeogl.math.vec3([0, 0, 0]);
            this._axis = [0, 1, 2];
            this._assetCfgs = {};
            this._assets = {};
        },

        /**
         * Adds an asset to this BuildableModel.
         *
         * The asset is given as a configuration object, to be lazy-instantiated as soon as an entity is built from
         * it with {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * ### Usage
         *
         * Adding a {{#crossLink "PhongMaterial"}}{{/crossLink}} asset with ID "uvGrid":
         *
         * ````javascript
         * buildableModel.asset("gridMaterial", {
         *     type: "xeogl.PhongMaterial",
         *     ambient: [0.9, 0.3, 0.9],
         *     shininess: 30,
         *     diffuseMap: {
         *         src: "textures/diffuse/uvGrid2.jpg"
         *     }
         * });
         * ````
         *
         * Adding a {{#crossLink "BoxGeometry"}}{{/crossLink}} asset with ID "boxGeometry":
         *
         * ````javascript
         * buildableModel.asset("boxGeometry", {
         *     type: "xeogl.BoxGeometry",
         *     xSize: 1.0,
         *     ySize: 1.0,
         *     zSize: 1.0
         * });
         * ````
         *
         * @method asset
         * @param {String|Number} assetId A unique ID for the asset.
         * @param {*} cfg Configuration object for the asset.
         */
        asset: function (assetId, cfg) {
            this._assetCfgs[assetId] = cfg;
            delete this._assets[assetId];
        },

        /**
         * Sets the {{#crossLink "Geometry"}}{{/crossLink}} asset that will be added to
         * each {{#crossLink "Entity"}}{{/crossLink}} subsequently created with
         * {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * The given ID must belong to a {{#crossLink "Geometry"}}{{/crossLink}} asset that was added previously with
         * {{#crossLink "BuildableModel/asset:method"}}asset(){{/crossLink}}.
         *
         * @method geometry
         * @param {String|Number} assetId The asset ID.
         */
        geometry: function (assetId) {
            this._geometry = assetId;
        },

        /**
         * Sets the {{#crossLink "Material"}}{{/crossLink}} asset that will be added to
         * each {{#crossLink "Entity"}}{{/crossLink}} subsequently created with
         * {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * The given ID must belong to a {{#crossLink "Material"}}{{/crossLink}} asset that was added previously with
         * {{#crossLink "BuildableModel/asset:method"}}asset(){{/crossLink}}.
         *
         * @method material
         * @param {String|Number} assetId The asset ID.
         */
        material: function (assetId) {
            this._material = assetId;
        },

        /**
         * Sets the 3D position of each {{#crossLink "Entity"}}{{/crossLink}} subsequently created with
         * {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * @method pos
         * @param {Number} x Position on X-axis.
         * @param {Number} y Position on Y-axis.
         * @param {Number} z Position on Z-axis.
         */
        pos: function (x, y, z) {
            this._pos[0] = x;
            this._pos[1] = y;
            this._pos[2] = z;
        },

        /**
         * Sets the 3D scale of each {{#crossLink "Entity"}}{{/crossLink}} subsequently created with
         * {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * @method scale
         * @param {Number} x Scale on X-axis.
         * @param {Number} y Scale on Y-axis.
         * @param {Number} z Scale on Z-axis.
         */
        scale: function (x, y, z) {
            this._scale[0] = x;
            this._scale[1] = y;
            this._scale[2] = z;
        },

        /**
         * Sets the 3D Euler rotation angles for each {{#crossLink "Entity"}}{{/crossLink}} subsequently created
         * with {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * @method angles
         * @param {Number} x Angle on X-axis in degrees.
         * @param {Number} y Angle on Y-axis in degrees.
         * @param {Number} z Angle on Z-axis in degrees.
         */
        angles: function (x, y, z) {
            this._angles[0] = x;
            this._angles[1] = y;
            this._angles[2] = z;
        },

        /**
         * Sets the order of 3D rotations for each {{#crossLink "Entity"}}{{/crossLink}} subsequently created
         * with {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * ### Usage
         *
         * The X, Y and Z axis are identified as ````0, 1, 2```` respectively.
         *
         * ````Javascript
         * buildableModel.axis(0,1,2); // X, Y, Z
         * buildableModel.axis(2,0,1); // Z, X, Y
         * buildableModel.axis(1,2,0); // Y, Z, X
         * ````
         *
         * @method axis
         * @param {Number} a Indicates the first rotation axis.
         * @param {Number} b Indicates the second rotation axis.
         * @param {Number} c Indicates the third rotation axis.
         */
        axis: function (a, b, c) {
            this._axis[0] = a;
            this._axis[1] = b;
            this._axis[2] = c;
        },

        /**
         * Creates an {{#crossLink "Entity"}}{{/crossLink}} with whatever assets and states are currently
         * set on this BuildableModel.
         *
         * @method entity
         * @param {String|Number} [id] A unique ID for the new {{#crossLink "Entity"}}{{/crossLink}}.
         */
        entity: function (id) {
            this.add({
                type: "xeogl.Entity",
                id: id,
                material: this._getAsset(this._material),
                geometry: this._getAsset(this._geometry),
                transform: {
                    type: "xeogl.Scale",
                    xyz: this._scale,
                    parent: this.create({
                        type: "xeogl.Translate",
                        xyz: this._pos
                    })
                }
            });
        },

        _getAsset: function (assetId) {
            if (assetId === null) {
                return;
            }
            var asset = this._assets[assetId];
            if (!asset) {
                var assetCfg = this._assetCfgs[assetId];
                if (!assetCfg) {
                    this.error("Unknown asset: " + assetId);
                    return;
                }
                asset = this.create(assetCfg);
                this._assets[assetId] = asset;
                this.add(asset);
            }
            return asset;
        },

        /**
         * Removes all assets and {{#crossLink "Entity"}}Entities{{/crossLink}} from this BuildableModel.
         * @method clear
         */
        clear: function () {
            this._super();
            this._assets = {};
        },

        /**
         * Resets the state of this BuildableModel to defaults.
         * @method reset
         */
        reset: function () {
            this.pos(0, 0, 0);
            this.scale(1, 1, 1);
            this.angles(0, 0, 0);
            this.axis(0, 1, 2);
            this.material(null);
            this.geometry(null);
        },

        _getJSON: function () {
            var json = this._super();
            // json.assets = this._assetCfgs;
            // json.entities = this._entities;
            return json;
        }
    });
})();
<commit_msg>BuildableModel doc tweaks<commit_after>/**
 A **BuildableModel** is a {{#crossLink "Model"}}{{/crossLink}} that provides a fluent API through which you can
 build it incrementally.

 ## Examples

 * [Generating a city with a BuildableModel](../../examples/#models_BuildableModel_city)</li>

 ## Usage

 A BuildableModel containing ten textured boxes with random sizes and positions:

 ````javascript
 var model = new xeogl.BuildableModel();

 // Add a BoxGeometry asset
 buildableModel.asset("boxGeometry", {
     type: "xeogl.BoxGeometry"
 });

 // Add a PhongMaterial asset
 buildableModel.asset("gridMaterial", {
     type: "xeogl.PhongMaterial",
     ambient: [0.9, 0.3, 0.9],
     shininess: 30,
     diffuseMap: {
         src: "textures/diffuse/gridMaterial.jpg"
     }
 });

 // Set the BoxGeometry asset as the current geometry
 buildableModel.geometry("boxGeometry");

 // Set the PhongMaterial asset as the current material
 buildableModel.material("gridMaterial");

 // Build ten entities with random sizes and positions,
 // that each get the current geometry and material
 for (var i = 0; i < 10; i++) {

     buildableModel.scale(Math.random() * 10 + 1, Math.random() * 10 + 1, Math.random() * 10 + 1);
     buildableModel.pos(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50);

     buildableModel.entity();
 }
 ````

 @class BuildableModel
 @module xeogl
 @submodule models
 @constructor
 @param [scene] {Scene} Parent {{#crossLink "Scene"}}Scene{{/crossLink}} - creates this BuildableModel in the default
 {{#crossLink "Scene"}}Scene{{/crossLink}} when omitted.
 @param [cfg] {*} Configs
 @param [cfg.id] {String} Optional ID, unique among all components in the parent {{#crossLink "Scene"}}Scene{{/crossLink}},
 generated automatically when omitted.
 @param [cfg.meta] {String:Object} Optional map of user-defined metadata to attach to this BuildableModel.
 @param [cfg.transform] {Number|String|Transform} A Local-to-World-space (modelling) {{#crossLink "Transform"}}{{/crossLink}} to attach to this BuildableModel.
 Must be within the same {{#crossLink "Scene"}}{{/crossLink}} as this BuildableModel. Internally, the given
 {{#crossLink "Transform"}}{{/crossLink}} will be inserted above each top-most {{#crossLink "Transform"}}Transform{{/crossLink}}
 that the BuildableModel attaches to its {{#crossLink "Entity"}}Entities{{/crossLink}}.
 @extends Model
 */
(function () {

    "use strict";

    xeogl.BuildableModel = xeogl.Model.extend({

        type: "xeogl.BuildableModel",

        _init: function (cfg) {

            this._super(cfg);

            this._material = null;
            this._geometry = null;
            this._pos = xeogl.math.vec3([0, 0, 0]);
            this._scale = xeogl.math.vec3([1, 1, 1]);
            this._angles = xeogl.math.vec3([0, 0, 0]);
            this._axis = [0, 1, 2];
            this._assetCfgs = {};
            this._assets = {};
        },

        /**
         * Adds an asset to this BuildableModel.
         *
         * The asset is given as a configuration object, to be lazy-instantiated as soon as an entity is built from
         * it with {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * ### Usage
         *
         * Adding a {{#crossLink "PhongMaterial"}}{{/crossLink}} asset with ID "uvGrid":
         *
         * ````javascript
         * buildableModel.asset("gridMaterial", {
         *     type: "xeogl.PhongMaterial",
         *     ambient: [0.9, 0.3, 0.9],
         *     shininess: 30,
         *     diffuseMap: {
         *         src: "textures/diffuse/uvGrid2.jpg"
         *     }
         * });
         * ````
         *
         * Adding a {{#crossLink "BoxGeometry"}}{{/crossLink}} asset with ID "boxGeometry":
         *
         * ````javascript
         * buildableModel.asset("boxGeometry", {
         *     type: "xeogl.BoxGeometry",
         *     xSize: 1.0,
         *     ySize: 1.0,
         *     zSize: 1.0
         * });
         * ````
         *
         * @method asset
         * @param {String|Number} assetId A unique ID for the asset.
         * @param {*} cfg Configuration object for the asset.
         */
        asset: function (assetId, cfg) {
            this._assetCfgs[assetId] = cfg;
            delete this._assets[assetId];
        },

        /**
         * Sets the {{#crossLink "Geometry"}}{{/crossLink}} asset that will be added to
         * each {{#crossLink "Entity"}}{{/crossLink}} subsequently created with
         * {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * The given ID must belong to a {{#crossLink "Geometry"}}{{/crossLink}} asset that was added previously with
         * {{#crossLink "BuildableModel/asset:method"}}asset(){{/crossLink}}.
         *
         * @method geometry
         * @param {String|Number} assetId The asset ID.
         */
        geometry: function (assetId) {
            this._geometry = assetId;
        },

        /**
         * Sets the {{#crossLink "Material"}}{{/crossLink}} asset that will be added to
         * each {{#crossLink "Entity"}}{{/crossLink}} subsequently created with
         * {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * The given ID must belong to a {{#crossLink "Material"}}{{/crossLink}} asset that was added previously with
         * {{#crossLink "BuildableModel/asset:method"}}asset(){{/crossLink}}.
         *
         * @method material
         * @param {String|Number} assetId The asset ID.
         */
        material: function (assetId) {
            this._material = assetId;
        },

        /**
         * Sets the 3D position of each {{#crossLink "Entity"}}{{/crossLink}} subsequently created with
         * {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * @method pos
         * @param {Number} x Position on X-axis.
         * @param {Number} y Position on Y-axis.
         * @param {Number} z Position on Z-axis.
         */
        pos: function (x, y, z) {
            this._pos[0] = x;
            this._pos[1] = y;
            this._pos[2] = z;
        },

        /**
         * Sets the 3D scale of each {{#crossLink "Entity"}}{{/crossLink}} subsequently created with
         * {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * @method scale
         * @param {Number} x Scale on X-axis.
         * @param {Number} y Scale on Y-axis.
         * @param {Number} z Scale on Z-axis.
         */
        scale: function (x, y, z) {
            this._scale[0] = x;
            this._scale[1] = y;
            this._scale[2] = z;
        },

        /**
         * Sets the 3D Euler rotation angles for each {{#crossLink "Entity"}}{{/crossLink}} subsequently created
         * with {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * @method angles
         * @param {Number} x Angle on X-axis in degrees.
         * @param {Number} y Angle on Y-axis in degrees.
         * @param {Number} z Angle on Z-axis in degrees.
         */
        angles: function (x, y, z) {
            this._angles[0] = x;
            this._angles[1] = y;
            this._angles[2] = z;
        },

        /**
         * Sets the order of 3D rotations for each {{#crossLink "Entity"}}{{/crossLink}} subsequently created
         * with {{#crossLink "BuildableModel/entity:method"}}entity(){{/crossLink}}.
         *
         * ### Usage
         *
         * The X, Y and Z axis are identified as ````0, 1, 2```` respectively.
         *
         * ````Javascript
         * buildableModel.axis(0,1,2); // X, Y, Z
         * buildableModel.axis(2,0,1); // Z, X, Y
         * buildableModel.axis(1,2,0); // Y, Z, X
         * ````
         *
         * @method axis
         * @param {Number} a Indicates the first rotation axis.
         * @param {Number} b Indicates the second rotation axis.
         * @param {Number} c Indicates the third rotation axis.
         */
        axis: function (a, b, c) {
            this._axis[0] = a;
            this._axis[1] = b;
            this._axis[2] = c;
        },

        /**
         * Creates an {{#crossLink "Entity"}}{{/crossLink}} with whatever assets and states are currently
         * set on this BuildableModel.
         *
         * @method entity
         * @param {String|Number} [id] A unique ID for the new {{#crossLink "Entity"}}{{/crossLink}}.
         */
        entity: function (id) {
            this.add({
                type: "xeogl.Entity",
                id: id,
                material: this._getAsset(this._material),
                geometry: this._getAsset(this._geometry),
                transform: {
                    type: "xeogl.Scale",
                    xyz: this._scale,
                    parent: this.create({
                        type: "xeogl.Translate",
                        xyz: this._pos
                    })
                }
            });
        },

        _getAsset: function (assetId) {
            if (assetId === null) {
                return;
            }
            var asset = this._assets[assetId];
            if (!asset) {
                var assetCfg = this._assetCfgs[assetId];
                if (!assetCfg) {
                    this.error("Unknown asset: " + assetId);
                    return;
                }
                asset = this.create(assetCfg);
                this._assets[assetId] = asset;
                this.add(asset);
            }
            return asset;
        },

        /**
         * Removes all assets and {{#crossLink "Entity"}}Entities{{/crossLink}} from this BuildableModel.
         * @method clear
         */
        clear: function () {
            this._super();
            this._assets = {};
        },

        /**
         * Resets the state of this BuildableModel to defaults.
         * @method reset
         */
        reset: function () {
            this.pos(0, 0, 0);
            this.scale(1, 1, 1);
            this.angles(0, 0, 0);
            this.axis(0, 1, 2);
            this.material(null);
            this.geometry(null);
        },

        _getJSON: function () {
            var json = this._super();
            // json.assets = this._assetCfgs;
            // json.entities = this._entities;
            return json;
        }
    });
})();
<|endoftext|>


<commit_before>/**
* Listener Callbacks
*/
var pageActionListener = function(tab) {
	var destination,
		commentURL,
		tabId,
		tabName;

	// retrieve comment from tabList
	tabId 	   = tab.id;
	tabName    = "tab_" + tabId;
	commentURL = tabList[ tabName ];

	// create URL of comments page
	destination = "http://news.ycombinator.com/" + commentURL;

	// navigate tab to new url
	// chrome.tabs.update(tabId, {url: destination});

	// save comment URL to window object
	chrome.tabs.executeScript(tabId, {
		code: "window.postMessage( {commentURL: '" + commentURL + "'}, '*' );"
	}, null);
}

var messageListener = function(message, sender, sendResponse) {
    var tabName;

    clickFlag = true;
    mostRecentComment = message;

}

var tabUpdateListener = function(tabId, changeInfo, tab) {
	var isLoading,
		tabName;

	isLoading = changeInfo.status;

	if ( clickFlag && isLoading ) {

		// add comment url to tab object.
		console.log(tab);
		tabName = "tab_" + tabId;
        tabList[ tabName ] = mostRecentComment;

		// inject script
		chrome.tabs.executeScript(tabId, {
		  code: "document.body.appendChild(document.createElement('script')).src='" +
		    chrome.extension.getURL("inject.js") +"';"
		}, null);

		// show page action
		chrome.pageAction.show( tabId );

		// turn clickFlag off
		clickFlag = false;
	}
}

var stripHeaders = function( info ) {
    var headers = info.responseHeaders;
    for (var i=headers.length-1; i>=0; --i) {
        var header = headers[i].name.toLowerCase();
        if (header == 'x-frame-options' || header == 'frame-options') {
            headers.splice(i, 1); // Remove header
        }
    }
    return {responseHeaders: headers};
}

/**
* Vars and Events
*/
var tabList = Object(),
	mostRecentComment,
	clickFlag;

// Add listener for pageaction
chrome.pageAction.onClicked.addListener( pageActionListener );
// listens for messages passed when chrome storage is altered
chrome.runtime.onMessage.addListener( messageListener );
// tab change listener runs URL checking function
chrome.tabs.onUpdated.addListener( tabUpdateListener );
// webRequest listener strips out yt headers preventing iframe loading
chrome.webRequest.onHeadersReceived.addListener( stripHeaders ,
    {
        urls: [ '*://*/*' ], // Pattern to match all http(s) pages
        types: [ 'sub_frame' ]
    },
    ['blocking', 'responseHeaders']
);
<commit_msg>Refactored request headers listener.<commit_after>/**
* Listener Callbacks
*/
var pageActionListener = function(tab) {
	var destination,
		commentURL,
		tabId,
		tabName;

	// retrieve comment from tabList
	tabId 	   = tab.id;
	tabName    = "tab_" + tabId;
	commentURL = tabList[ tabName ];

	// create URL of comments page
	destination = "http://news.ycombinator.com/" + commentURL;

	// navigate tab to new url
	// chrome.tabs.update(tabId, {url: destination});

	// save comment URL to window object
	chrome.tabs.executeScript(tabId, {
		code: "window.postMessage( {commentURL: '" + commentURL + "'}, '*' );"
	}, null);
}

var messageListener = function(message, sender, sendResponse) {
    var tabName;

    clickFlag = true;
    mostRecentComment = message;

}

var tabUpdateListener = function(tabId, changeInfo, tab) {
	var isLoading,
		tabName;

	isLoading = changeInfo.status;

	if ( clickFlag && isLoading ) {

		// add comment url to tab object.
		console.log(tab);
		tabName = "tab_" + tabId;
        tabList[ tabName ] = mostRecentComment;

		// inject script
		chrome.tabs.executeScript(tabId, {
		  code: "document.body.appendChild(document.createElement('script')).src='" +
		    chrome.extension.getURL("inject.js") +"';"
		}, null);

		// show page action
		chrome.pageAction.show( tabId );

		// turn clickFlag off
		clickFlag = false;
	}
}

var stripHeaders = function( info ) {
    var headers = info.responseHeaders;
    for (var i=headers.length-1; i>=0; --i) {
        var header = headers[i].name.toLowerCase();
        if (header == 'x-frame-options' || header == 'frame-options') {
            headers.splice(i, 1); // Remove header
        }
    }
    return {responseHeaders: headers};
}

/**
* Vars and Events
*/
var tabList = Object(),
	mostRecentComment,
	clickFlag,
	requestFilter,
	requestOptions;

// Add listener for pageaction
chrome.pageAction.onClicked.addListener( pageActionListener );
// listens for messages passed when chrome storage is altered
chrome.runtime.onMessage.addListener( messageListener );
// tab change listener runs URL checking function
chrome.tabs.onUpdated.addListener( tabUpdateListener );

// filter request URLs
requestFilter = {
    urls: [ '*://*/*' ], // Pattern to match all http(s) pages
    types: [ 'sub_frame' ]
};
// make request blocking
requestOptions = ['blocking', 'responseHeaders'];
// webRequest listener strips out yt headers preventing iframe loading
chrome.webRequest.onHeadersReceived.addListener( stripHeaders, requestFilter, requestOptions );
<|endoftext|>