<commit_before>var _ = require('underscore');

// Given an Error (eg, 'new Error'), return the stack associated with
// that error as an array. More recently called functions appear first
// and each element is an object with keys:
// - file: filename as it appears in the stack
// - line: 1-indexed line number in file, as a Number
// - column: 1-indexed column in line, as a Number
// - func: name of the function in the frame (maybe null)
//
// Accomplishes this by parsing the text representation of the stack
// with regular expressions. Unlikely to work anywhere but v8.
//
// If a function on the stack has been marked with mark(), don't
// return anything past that function. We call this the "user portion"
// of the stack.
exports.parse = function (err) {
  var frames = err.stack.split('\n');

  frames.shift(); // at least the first line is the exception

  // XXX assumes this can only happen once; I don't actually know enough about
  // fibers to know if it can happen multiple times
  var indexOfFiberSplit = frames.indexOf("    - - - - -");

  if (indexOfFiberSplit === -1) {
    // This is a normal stack trace, not a split fiber stack trace
    return parseStackFrames(frames);
  }

  var outsideFiber = parseStackFrames(frames);
  var insideFiber = parseStackFrames(frames.slice(indexOfFiberSplit + 1));

  return insideFiber.concat(outsideFiber);
};

// Decorator. Mark the point at which a stack trace returned by
// parse() should stop: no frames earlier than this point will be
// included in the parsed stack. Confusingly, in the argot of the
// times, you'd say that frames "higher up" than this or "above" this
// will not be returned, but you'd also say that those frames are "at
// the bottom of the stack". Frames below the bottom are the outer
// context of the framework running the user's code.
exports.markBottom = function (f) {
  return function __bottom_mark__ () {
    return f.apply(this, arguments);
  };
};

// Decorator. Mark the point at which a stack trace returned by
// parse() should begin: no frames later than this point will be
// included in the parsed stack. The opposite of markBottom().
// Frames above the top are helper functions defined by the
// framework and executed by user code whose internal behavior
// should not be exposed.
exports.markTop = function (f) {
  return function __top_mark__ () {
    return f.apply(this, arguments);
  };
};

function parseStackFrames(frames) {
  var stop = false;
  var ret = [];
  _.each(frames, function (frame) {
    if (stop)
      return;
    var m;
    if (m =
        frame.match(/^\s*at\s*((new )?.+?)\s*(\[as\s*([^\]]*)\]\s*)?\((.*?)(:(\d+))?(:(\d+))?\)\s*$/)) {
      // https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
      // "    at My.Function (/path/to/myfile.js:532:39)"
      // "    at Array.forEach (native)"
      // "    at new My.Class (file.js:1:2)"
      // "    at [object Object].main.registerCommand.name [as func] (meteor/tools/commands.js:1225:19)"
      // "    at __top_mark__ [as matchErr] (meteor/tools/parse-stack.js:82:14)"
      //
      // In that last example, it is not at all clear to me what the
      // 'as' stanza refers to, but it is in m[3] if you find a use for it.
      if (m[1].match(/(?:^|\.)__top_mark__$/)) {
        // m[1] could be Object.__top_mark__ or something like that
        // depending on where exactly you put the function returned by
        // markTop
        ret = [];
        return;
      }
      if (m[1].match(/(?:^|\.)__bottom_mark__$/)) {
        stop = true;
        return;
      }
      ret.push({
        func: m[1],
        file: m[5],
        line: m[7] ? +m[7] : undefined,
        column: m[9] ? +m[9] : undefined
      });
    } else if (m = frame.match(/^\s*at\s+(.+?)(:(\d+))?(:(\d+))?\s*$/)) {
      // "    at /path/to/myfile.js:532:39"
      ret.push({
        file: m[1],
        line: m[3] ? +m[3] : undefined,
        column: m[5] ? +m[5] : undefined
      });
    } else if (m = frame.match(/^\s*-\s*-\s*-\s*-\s*-\s*$/)) {
      // "    - - - - -"
      // This is something added when you throw an Error through a future. The
      // stack above the dashes is the stack of the 'wait' call; the stack below
      // is the stack inside the fiber where the Error is originally
      // constructed. Taking just the former seems good for now, but in the
      // future we may want to sew them together (possibly in the opposite
      // order?)
      stop = true;
    } else if (_.isEmpty(ret)) {
      // We haven't found any stack frames, so probably we have newlines in the
      // error message. Just skip this line.
    } else {
      throw new Error("Couldn't parse stack frame: '" + frame + "'");
    }
  });

  return ret;
}
<commit_msg>Improve comments about Future stack traces<commit_after>var _ = require('underscore');

// Given an Error (eg, 'new Error'), return the stack associated with
// that error as an array. More recently called functions appear first
// and each element is an object with keys:
// - file: filename as it appears in the stack
// - line: 1-indexed line number in file, as a Number
// - column: 1-indexed column in line, as a Number
// - func: name of the function in the frame (maybe null)
//
// Accomplishes this by parsing the text representation of the stack
// with regular expressions. Unlikely to work anywhere but v8.
//
// If a function on the stack has been marked with mark(), don't
// return anything past that function. We call this the "user portion"
// of the stack.
exports.parse = function (err) {
  var frames = err.stack.split('\n');

  frames.shift(); // at least the first line is the exception

  // "    - - - - -"
  // This is something added when you throw an Error through a Future. The
  // stack above the dashes is the stack of the 'wait' call; the stack below
  // is the stack inside the fiber where the Error is originally
  // constructed.
  // XXX This code assumes that the stack trace can only be split once. It's not
  // clear whether this can happen multiple times.
  var indexOfFiberSplit = frames.indexOf("    - - - - -");

  if (indexOfFiberSplit === -1) {
    // This is a normal stack trace, not a split fiber stack trace
    return parseStackFrames(frames);
  }

  // If this is a split stack trace from a future, parse the frames above and
  // below the split separately.
  var outsideFiber = parseStackFrames(frames);
  var insideFiber = parseStackFrames(frames.slice(indexOfFiberSplit + 1));

  // Put the frames below the split at the top of the printed stack trace, since
  // they are more likely to contain the code that actually threw the error.
  return insideFiber.concat(outsideFiber);
};

// Decorator. Mark the point at which a stack trace returned by
// parse() should stop: no frames earlier than this point will be
// included in the parsed stack. Confusingly, in the argot of the
// times, you'd say that frames "higher up" than this or "above" this
// will not be returned, but you'd also say that those frames are "at
// the bottom of the stack". Frames below the bottom are the outer
// context of the framework running the user's code.
exports.markBottom = function (f) {
  return function __bottom_mark__ () {
    return f.apply(this, arguments);
  };
};

// Decorator. Mark the point at which a stack trace returned by
// parse() should begin: no frames later than this point will be
// included in the parsed stack. The opposite of markBottom().
// Frames above the top are helper functions defined by the
// framework and executed by user code whose internal behavior
// should not be exposed.
exports.markTop = function (f) {
  return function __top_mark__ () {
    return f.apply(this, arguments);
  };
};

function parseStackFrames(frames) {
  var stop = false;
  var ret = [];
  _.each(frames, function (frame) {
    if (stop)
      return;
    var m;
    if (m =
        frame.match(/^\s*at\s*((new )?.+?)\s*(\[as\s*([^\]]*)\]\s*)?\((.*?)(:(\d+))?(:(\d+))?\)\s*$/)) {
      // https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
      // "    at My.Function (/path/to/myfile.js:532:39)"
      // "    at Array.forEach (native)"
      // "    at new My.Class (file.js:1:2)"
      // "    at [object Object].main.registerCommand.name [as func] (meteor/tools/commands.js:1225:19)"
      // "    at __top_mark__ [as matchErr] (meteor/tools/parse-stack.js:82:14)"
      //
      // In that last example, it is not at all clear to me what the
      // 'as' stanza refers to, but it is in m[3] if you find a use for it.
      if (m[1].match(/(?:^|\.)__top_mark__$/)) {
        // m[1] could be Object.__top_mark__ or something like that
        // depending on where exactly you put the function returned by
        // markTop
        ret = [];
        return;
      }
      if (m[1].match(/(?:^|\.)__bottom_mark__$/)) {
        stop = true;
        return;
      }
      ret.push({
        func: m[1],
        file: m[5],
        line: m[7] ? +m[7] : undefined,
        column: m[9] ? +m[9] : undefined
      });
    } else if (m = frame.match(/^\s*at\s+(.+?)(:(\d+))?(:(\d+))?\s*$/)) {
      // "    at /path/to/myfile.js:532:39"
      ret.push({
        file: m[1],
        line: m[3] ? +m[3] : undefined,
        column: m[5] ? +m[5] : undefined
      });
    } else if (m = frame.match(/^\s*-\s*-\s*-\s*-\s*-\s*$/)) {
      // Stop parsing if we reach a stack split from a Future
      stop = true;
    } else if (_.isEmpty(ret)) {
      // We haven't found any stack frames, so probably we have newlines in the
      // error message. Just skip this line.
    } else {
      throw new Error("Couldn't parse stack frame: '" + frame + "'");
    }
  });

  return ret;
}
<|endoftext|>


<commit_before>var Discord = require("discord.js");
var config = require("./config");

var client = new Discord.Client();
var botUser;

client.on("message", function(message) {
	if(message.content.toLowerCase().indexOf("hello") > -1 && message.isMentioned(botUser)) {
		return client.sendMessage(message.channel, 'Hello ' + message.author);
	}
	else if(message.content.toLowerCase().indexOf("who gta") > -1) {
		return message.reply("oooh oooh me! I'll play!")
	}

	else if(message.content.charAt(0) == config.cmdprefix) {
		var spacePos = message.content.indexOf(" ");
		//var cmd = spacePos > -1 ? message.content.substring(1, spacePos) : message.content.substring(1);

		var cmdArray = message.content.substring(1).split(" ");
		var cmd = cmdArray[0];

		var params;

		if(cmdArray.length > 1) {
			params = new Array(cmdArray.length-1);
			for(var i = 1; i < cmdArray.length; i++) {
				params[i-1] = cmdArray[i];
			}
		}

		switch(cmd){
			case 'ping':
				client.reply(message, "pong");
				break;
			case 'help':
				client.sendMessage(message.channel, "You need help " + message.author);
				break;
			case 'bh':
				playBennyHill(message);
				client.deleteMessage(message);
				break;
			case 'blame':
				client.sendMessage(message.channel, "I blame Yury");
				break;
			case 'ge':
				var item = message.content.substring(spacePos+1);
				var fixedItem = item.replace(/ /g, "+");
				client.sendMessage(message.channel, "http://services.runescape.com/m=itemdb_rs/results?query=" + fixedItem);
				break;
			case 'config':
				var server = message.server;
				if(client.memberHasRole(message.author, server.roles.get("name", "Admin"))) {
					config[params[0]] = params[1];
					message.reply("Updated config");
				}
				else {
					message.reply("*sticks fingers in ears* lalala I'm not listening!");
				}

		}
	}
});

//Hilarity ensues
function playBennyHill(message) {
	var voiceChannel = message.author.voiceChannel;
	if(voiceChannel != null) {
		client.joinVoiceChannel(voiceChannel, function(error, voiceConnection){
			if(error) {
				return console.error(error);
			}
			voiceConnection.playFile(config.bennyHill, function(error, intent) {
				if(error) {
					return console.error(error);
				}
				intent.on("error", function(error) {
					return console.error(error);
				});
				intent.once("end", function() {
					client.leaveVoiceChannel(voiceConnection);
				});
			});
		});
	}
	else {
		client.sendMessage(message.channel, "*starts humming*");
	}
}

//Called once the bot is logged in and ready to use.
client.on("ready", function() {
	client.setPlayingGame(config.playing);
	botUser = client.users.get("username", "DeixBot");
	/*for (var i = 0; i < client.servers.length; i++) {
		var server = client.servers[i];
		var msg = "S'up " + server.name + "!";
		client.sendMessage(server.defaultChannel, msg);
	}*/
});

//Handle a CTRL+C to actually shutdown somewhat cleanly
process.on("SIGINT", function() {
	client.logout();
	/*for (var i = 0; i < client.servers.length; i++){
		var server = client.servers[i];
		client.sendMessage(server.defaultChannel, "Peace out!", function(i){
			if(i + 1 == client.servers.length){
				client.logout();
			}
		});
	}*/
});

client.loginWithToken(config.discord.key);
<commit_msg>Fixed config command and added github link<commit_after>var Discord = require("discord.js");
var config = require("./config");

var client = new Discord.Client();
var botUser;

client.on("message", function(message) {
	if(message.content.toLowerCase().indexOf("hello") > -1 && message.isMentioned(botUser)) {
		return client.sendMessage(message.channel, 'Hello ' + message.author);
	}
	else if(message.content.toLowerCase().indexOf("who gta") > -1) {
		return message.reply("oooh oooh me! I'll play!")
	}

	else if(message.content.charAt(0) == config.cmdprefix) {
		var spacePos = message.content.indexOf(" ");
		//var cmd = spacePos > -1 ? message.content.substring(1, spacePos) : message.content.substring(1);

		var cmdArray = message.content.substring(1).split(" ");
		var cmd = cmdArray[0];

		var params;

		if(cmdArray.length > 1) {
			params = new Array(cmdArray.length-1);
			for(var i = 1; i < cmdArray.length; i++) {
				params[i-1] = cmdArray[i];
			}
		}

		switch(cmd){
			case 'ping':
				client.reply(message, "pong");
				break;
			case 'help':
				client.sendMessage(message.channel, "You need help " + message.author);
				break;
			case 'bh':
				playBennyHill(message);
				client.deleteMessage(message);
				break;
			case 'blame':
				client.sendMessage(message.channel, "I blame Yury");
				break;
			case 'ge':
				var item = message.content.substring(spacePos+1);
				var fixedItem = item.replace(/ /g, "+");
				client.sendMessage(message.channel, "http://services.runescape.com/m=itemdb_rs/results?query=" + fixedItem);
				break;
			case 'config':
				var server = message.server;
				if(client.memberHasRole(message.author, server.roles.get("name", "Admin"))) {
					config[params[0]] = params[1];
					message.reply("Updated config");
				}
				else {
					message.reply("*sticks fingers in ears* lalala I'm not listening!");
				}
				break;
			case 'botissues':
				client.sendMessage(message.channel, "https://github.com/Deixel/DeixBot/issues");
				break;
		}
	}
});

//Hilarity ensues
function playBennyHill(message) {
	var voiceChannel = message.author.voiceChannel;
	if(voiceChannel != null) {
		client.joinVoiceChannel(voiceChannel, function(error, voiceConnection){
			if(error) {
				return console.error(error);
			}
			voiceConnection.playFile(config.bennyHill, function(error, intent) {
				if(error) {
					return console.error(error);
				}
				intent.on("error", function(error) {
					return console.error(error);
				});
				intent.once("end", function() {
					client.leaveVoiceChannel(voiceConnection);
				});
			});
		});
	}
	else {
		client.sendMessage(message.channel, "*starts humming*");
	}
}

//Called once the bot is logged in and ready to use.
client.on("ready", function() {
	client.setPlayingGame(config.playing);
	botUser = client.users.get("username", "DeixBot");
	/*for (var i = 0; i < client.servers.length; i++) {
		var server = client.servers[i];
		var msg = "S'up " + server.name + "!";
		client.sendMessage(server.defaultChannel, msg);
	}*/
});

//Handle a CTRL+C to actually shutdown somewhat cleanly
process.on("SIGINT", function() {
	client.logout();
	/*for (var i = 0; i < client.servers.length; i++){
		var server = client.servers[i];
		client.sendMessage(server.defaultChannel, "Peace out!", function(i){
			if(i + 1 == client.servers.length){
				client.logout();
			}
		});
	}*/
});

client.loginWithToken(config.discord.key);
<|endoftext|>


<commit_before>import test from 'tape';
import PybossaPlayer from '../player';

const containerId = 'player-container';
const youtubeUrl = 'https://www.youtube.com/watch?v=M4TH8rU8wZw';

function setUp() {
  const body = document.body;
  if (!document.getElementsByTagName('script')) {
    const fakeScript = document.createElement('script');
    body.appendChild(fakeScript);
  }
  if (!document.getElementById('containerId')) {
    const container = document.createElement('div');
    container.setAttribute('id', containerId);
    body.appendChild(container);
  }
}

test('Youtube player accepts a callback that is fired when ready', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    assert.pass("Player is ready");
    assert.end();
    player.destroy();
  });
});

test('Youtube player.destroy() removes the player from DOM', (assert) => {
  setUp();
  assert.plan(2);
  const player = PybossaPlayer(youtubeUrl, containerId);

  assert.ok(document.getElementsByTagName('iframe')[0]);

  player.destroy();

  assert.notOk(document.getElementsByTagName('iframe')[0]);
});

test('Youtube player.duration() returns duration when ready', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    setTimeout(function() {
      assert.equals(player.duration(), 465);
      assert.end();
      player.destroy();
    }, 100);
  });
});

test('Youtube player.duration() returns 0 when not ready', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  assert.equals(player.duration(), 0);
  player.destroy();
});

test('Youtube player.setCurrentTime(n) sets playback time to second n', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.setCurrentTime(2);
    setTimeout(function() {
      assert.equals(player.currentTime(), 2);
      assert.end();
      player.destroy();
    }, 100);
  });
});

test('Youtube player.ended() returns false if not ended', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    assert.equals(player.ended(), false);
    assert.end();
    player.destroy();
  });
});

test('Youtube player volume returns new volume after calling setVolume', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.setVolume(0.5);
    setTimeout(function() {
      assert.equals(player.volume(), 0.5);
      assert.end();
      player.destroy();
    }, 100);
  });
});

test('Youtube player muted() after muting and unmuting', (assert) => {
  setUp();
  assert.plan(2);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.mute();
    setTimeout(function() {
      assert.equals(player.muted(), true);
      player.unmute();
      setTimeout(function() {
        assert.equals(player.muted(), false);
        assert.end();
        player.destroy();
      }, 100);
    }, 100);
  });
});

test('Youtube player unmute() preserves volume prior to muted state', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.setVolume(0.5);
    player.mute();
    player.unmute();
    setTimeout(function() {
      assert.equals(player.volume(), 0.5);
      assert.end();
      player.destroy();
    }, 100);
  });
});

test('Youtube player.onEnded() accepts a callback fired when playback ends', (assert) => {
  setUp();
  assert.plan(2);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.onEnded(function() {
      assert.pass("player ended");
      assert.equals(player.ended(), true);
      assert.end();
      player.destroy();
    });
    player.setCurrentTime(464.4);
    player.play();
  });
});

test('Youtube player.onPlay() accepts a callback fired when playback starts', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.onPlay(function() {
      assert.pass("Play event fired");
      assert.end();
      player.destroy();
    });
    player.play();
  });
});

test('Youtube player.onPause() accepts a callback fired when playback pauses', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.onPlay(function () {
      player.pause();
    });
    player.onPause(function() {
      assert.pass("Pause event fired");
      assert.end();
      player.destroy();
    });
    player.play();
  });
});

test('Youtube player.onPlayTimeChange() accepts a callback fired when playtime changes', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.onPlayTimeChange(function() {
      assert.pass("PlayTimeChange event fired");
      player.pause();
      assert.end();
      player.destroy();
    });
    player.play();
  });
});
<commit_msg>Test youtube urls<commit_after>import test from 'tape';
import PybossaPlayer from '../player';
import YoutubePlayer from '../players/youtube';

const containerId = 'player-container';
const youtubeUrl = 'https://www.youtube.com/watch?v=M4TH8rU8wZw';

function setUp() {
  const body = document.body;
  if (!document.getElementsByTagName('script')) {
    const fakeScript = document.createElement('script');
    body.appendChild(fakeScript);
  }
  if (!document.getElementById('containerId')) {
    const container = document.createElement('div');
    container.setAttribute('id', containerId);
    body.appendChild(container);
  }
}

test('Youtube player accepts a callback that is fired when ready', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    assert.pass("Player is ready");
    assert.end();
    player.destroy();
  });
});

test('Youtube player.destroy() removes the player from DOM', (assert) => {
  setUp();
  assert.plan(2);
  const player = PybossaPlayer(youtubeUrl, containerId);

  assert.ok(document.getElementsByTagName('iframe')[0]);

  player.destroy();

  assert.notOk(document.getElementsByTagName('iframe')[0]);
});

test('Youtube player.duration() returns duration when ready', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    setTimeout(function() {
      assert.equals(player.duration(), 465);
      assert.end();
      player.destroy();
    }, 100);
  });
});

test('Youtube player.duration() returns 0 when not ready', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  assert.equals(player.duration(), 0);
  player.destroy();
});

test('Youtube player.setCurrentTime(n) sets playback time to second n', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.setCurrentTime(2);
    setTimeout(function() {
      assert.equals(player.currentTime(), 2);
      assert.end();
      player.destroy();
    }, 100);
  });
});

test('Youtube player.ended() returns false if not ended', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    assert.equals(player.ended(), false);
    assert.end();
    player.destroy();
  });
});

test('Youtube player volume returns new volume after calling setVolume', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.setVolume(0.5);
    setTimeout(function() {
      assert.equals(player.volume(), 0.5);
      assert.end();
      player.destroy();
    }, 100);
  });
});

test('Youtube player muted() after muting and unmuting', (assert) => {
  setUp();
  assert.plan(2);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.mute();
    setTimeout(function() {
      assert.equals(player.muted(), true);
      player.unmute();
      setTimeout(function() {
        assert.equals(player.muted(), false);
        assert.end();
        player.destroy();
      }, 100);
    }, 100);
  });
});

test('Youtube player unmute() preserves volume prior to muted state', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.setVolume(0.5);
    player.mute();
    player.unmute();
    setTimeout(function() {
      assert.equals(player.volume(), 0.5);
      assert.end();
      player.destroy();
    }, 100);
  });
});

test('Youtube player.onEnded() accepts a callback fired when playback ends', (assert) => {
  setUp();
  assert.plan(2);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.onEnded(function() {
      assert.pass("player ended");
      assert.equals(player.ended(), true);
      assert.end();
      player.destroy();
    });
    player.setCurrentTime(464.4);
    player.play();
  });
});

test('Youtube player.onPlay() accepts a callback fired when playback starts', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.onPlay(function() {
      assert.pass("Play event fired");
      assert.end();
      player.destroy();
    });
    player.play();
  });
});

test('Youtube player.onPause() accepts a callback fired when playback pauses', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.onPlay(function () {
      player.pause();
    });
    player.onPause(function() {
      assert.pass("Pause event fired");
      assert.end();
      player.destroy();
    });
    player.play();
  });
});

test('Youtube player.onPlayTimeChange() accepts a callback fired when playtime changes', (assert) => {
  setUp();
  assert.plan(1);
  const player = PybossaPlayer(youtubeUrl, containerId);

  player.onReady(function() {
    player.onPlayTimeChange(function() {
      assert.pass("PlayTimeChange event fired");
      player.pause();
      assert.end();
      player.destroy();
    });
    player.play();
  });
});

test('Youtube player recognises Youtube URLs', (assert) => {
  let urls = [
    '//www.youtube-nocookie.com/embed/up_lNV-yoK4?rel=0',
    'http://www.youtube.com/user/Scobleizer#p/u/1/1p3vcRhsYGo',
    'http://www.youtube.com/watch?v=cKZDdG9FTKY&feature=channel',
    'http://www.youtube.com/watch?v=yZ-K7nCVnBI&playnext_from=TL&videos=osPknwzXEas&feature=sub',
    'http://www.youtube.com/ytscreeningroom?v=NRHVzbJVx8I',
    'http://www.youtube.com/user/SilkRoadTheatre#p/a/u/2/6dwqZw0j_jY',
    'http://youtu.be/6dwqZw0j_jY',
    'http://www.youtube.com/watch?v=6dwqZw0j_jY&feature=youtu.be',
    'http://youtu.be/afa-5HQHiAs',
    'http://www.youtube.com/user/Scobleizer#p/u/1/1p3vcRhsYGo?rel=0',
    'http://www.youtube.com/watch?v=cKZDdG9FTKY&feature=channel',
    'http://www.youtube.com/watch?v=yZ-K7nCVnBI&playnext_from=TL&videos=osPknwzXEas&feature=sub',
    'http://www.youtube.com/ytscreeningroom?v=NRHVzbJVx8I',
    'http://www.youtube.com/embed/nas1rJpm7wY?rel=0',
    'http://www.youtube.com/watch?v=peFZbP64dsU',
    'http://youtube.com/v/dQw4w9WgXcQ?feature=youtube_gdata_player',
    'http://youtube.com/vi/dQw4w9WgXcQ?feature=youtube_gdata_player',
    'http://youtube.com/?v=dQw4w9WgXcQ&feature=youtube_gdata_player',
    'http://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=youtube_gdata_player',
    'http://youtube.com/?vi=dQw4w9WgXcQ&feature=youtube_gdata_player',
    'http://youtube.com/watch?v=dQw4w9WgXcQ&feature=youtube_gdata_player',
    'http://youtube.com/watch?vi=dQw4w9WgXcQ&feature=youtube_gdata_player',
    'http://youtu.be/dQw4w9WgXcQ?feature=youtube_gdata_player'
  ];

  let youtubePlayer = YoutubePlayer();

  for (let i = 0; i < urls.length; ++i) {
      assert.ok(youtubePlayer.isYoutubeLink(urls[i]));
  }
  assert.end();
});
<|endoftext|>


<commit_before>function display(matches) {
  var tags = Object.keys(matches);

  // make a container for each query tag
  tags.forEach(function(tag) {
    // make container
    var container      = document.createElement('ul'),
        sectionHeading = document.createTextNode(tag);
        container.appendChild(sectionHeading);
        container.id   = tag;

    // append container to DOM
    var displayDiv = document.getElementById('display');
        displayDiv.appendChild(container);

    // insert query tag children into container
    insertItems(container, matches[tag], 'li');
  });
}

// generic
function insertItems(parentElement, matchedItems, tagType) {
  matchedItems.forEach(function(matchedItem) {
    var newEl         = document.createElement(tagType),
        contentString = stringifyItemConents(matchedItem),
        itemContents  = document.createTextNode(contentString);

    newEl.appendChild(itemContents);
    parentElement.appendChild(newEl);
  });

  function stringifyItemConents(example) {
    var stringifiedContents = "";
    var keys = Object.keys(example);
    keys.forEach(function(key) {
      stringifiedContents += key + ": " + example[key] + "\n";
    });

    return stringifiedContents;
  }
}
<commit_msg>wipe the display div on every new user call<commit_after>function display(matches) {
  var displayDiv = document.getElementById('display');

  if (displayDiv.hasChildNodes()) {
    while (displayDiv.firstChild) {
      displayDiv.removeChild(displayDiv.firstChild);
    }
  }

  var tags = Object.keys(matches);

  // make a container for each query tag
  tags.forEach(function(tag) {
    // make container
    var container      = document.createElement('ul'),
        sectionHeading = document.createTextNode(tag);
        container.appendChild(sectionHeading);
        container.id   = tag;

    // append container to DOM
    displayDiv.appendChild(container);

    // insert query tag children into container
    insertItems(container, matches[tag], 'li');
  });
}

// generic
function insertItems(parentElement, matchedItems, tagType) {
  matchedItems.forEach(function(matchedItem) {
    var newEl         = document.createElement(tagType),
        contentString = stringifyItemConents(matchedItem),
        itemContents  = document.createTextNode(contentString);

    newEl.appendChild(itemContents);
    parentElement.appendChild(newEl);
  });

  function stringifyItemConents(example) {
    var stringifiedContents = "";
    var keys = Object.keys(example);
    keys.forEach(function(key) {
      stringifiedContents += key + ": " + example[key] + "\n";
    });

    return stringifiedContents;
  }
}
<|endoftext|>


<commit_before>module.exports = {
    baseURL: 'http://localhost:2030',
    browser: 'firefox',
}
<commit_msg>Name integration tests<commit_after>module.exports = {
    name: 'OpenFisca Legislation explorer',
    baseURL: 'http://localhost:2030',
    browser: 'firefox',
}
<|endoftext|>


<commit_before>/**
 * @venus-library jasmine
 * @venus-include ../src/functions.js
 * @venus-include ../src/EntityInterface.js
 * @venus-code ../src/Entity.js
 */

describe('entity', function () {

    it('should set an attribute', function () {

        var e = new Sy.Entity();

        e.set('foo', 'bar');

        expect(e.get('foo')).toEqual('bar');

    });

    it('should register a new index', function () {

        var e = new Sy.Entity();

        e.register('foo');

        expect(e.indexes.indexOf('foo')).not.toEqual(-1);

    });

    it('should register a connection to another entity', function () {

        var e = new Sy.Entity();

        namespace('App.Bundle.Foo.Entity');

        App.Bundle.Foo.Entity.Bar = function () {};
        App.Bundle.Foo.Entity.Bar.prototype = Object.create(Sy.Entity.prototype);

        e.register('foobar', 'Foo::Bar');

        expect(e.indexes.indexOf('foo')).not.toEqual(-1);
        expect(e.connections.foobar).toEqual(App.Bundle.Foo.Entity.Bar);

    });

    it('should throw an error when entity relation alias name format is invalid', function () {

        var e = new Sy.Entity();

        expect(function () {
            e.register('foobaz', 'invalidFormat');
        }).toThrow('Invalid entity name format');

    });

    it('should lock the entity properties', function () {

        var f = function () {
                Sy.Entity.call(this);
            },
            e;

        f.prototype = Object.create(Sy.Entity.prototype);

        e = new f();

        e.lock(['foo', 'bar']);

        expect(Object.isSealed(e.attributes)).toBe(true);

    });

    it('should prevent a property to be set when entity locked', function () {

        var f = function () {
                Sy.Entity.call(this);
            },
            e;

        f.prototype = Object.create(Sy.Entity.prototype);

        e = new f();

        e.lock(['foo', 'bar']);
        e.set('baz', 'baz');

        expect(e.get('baz')).toEqual(undefined);

    });

    it('should return a plain object of entity data', function () {

        var e = new Sy.Entity();

        e.set('uuid', 'foo');
        e.set('foo', 'bar');

        expect(e.getRaw()).toEqual({uuid: 'foo', foo: 'bar'});

    });

    it('should return itself', function () {

        var e = new Sy.Entity();

        expect(e.set('foo', 'bar')).toEqual(e);
        expect(e.register('foo')).toEqual(e);
        expect(e.lock(['foo'])).toEqual(e);

    });

    it('should create a connection entity if set data as string', function () {

        var e = new Sy.Entity();

        namespace('App.Bundle.Foo.Entity');

        App.Bundle.Foo.Entity.Baz = function () {
            Sy.Entity.call(this);
        };
        App.Bundle.Foo.Entity.Baz.prototype = Object.create(Sy.Entity.prototype);

        e.register('foobarbaz', 'Foo::Baz');
        e.set('foobarbaz', 'foo');

        expect(e.get('foobarbaz') instanceof App.Bundle.Foo.Entity.Baz).toBe(true);
        expect(e.get('foobarbaz').get('uuid')).toEqual('foo');

    });

});<commit_msg>removed UT for Entity.getRaw<commit_after>/**
 * @venus-library jasmine
 * @venus-include ../src/functions.js
 * @venus-include ../src/EntityInterface.js
 * @venus-code ../src/Entity.js
 */

describe('entity', function () {

    it('should set an attribute', function () {

        var e = new Sy.Entity();

        e.set('foo', 'bar');

        expect(e.get('foo')).toEqual('bar');

    });

    it('should register a new index', function () {

        var e = new Sy.Entity();

        e.register('foo');

        expect(e.indexes.indexOf('foo')).not.toEqual(-1);

    });

    it('should register a connection to another entity', function () {

        var e = new Sy.Entity();

        namespace('App.Bundle.Foo.Entity');

        App.Bundle.Foo.Entity.Bar = function () {};
        App.Bundle.Foo.Entity.Bar.prototype = Object.create(Sy.Entity.prototype);

        e.register('foobar', 'Foo::Bar');

        expect(e.indexes.indexOf('foo')).not.toEqual(-1);
        expect(e.connections.foobar).toEqual(App.Bundle.Foo.Entity.Bar);

    });

    it('should throw an error when entity relation alias name format is invalid', function () {

        var e = new Sy.Entity();

        expect(function () {
            e.register('foobaz', 'invalidFormat');
        }).toThrow('Invalid entity name format');

    });

    it('should lock the entity properties', function () {

        var f = function () {
                Sy.Entity.call(this);
            },
            e;

        f.prototype = Object.create(Sy.Entity.prototype);

        e = new f();

        e.lock(['foo', 'bar']);

        expect(Object.isSealed(e.attributes)).toBe(true);

    });

    it('should prevent a property to be set when entity locked', function () {

        var f = function () {
                Sy.Entity.call(this);
            },
            e;

        f.prototype = Object.create(Sy.Entity.prototype);

        e = new f();

        e.lock(['foo', 'bar']);
        e.set('baz', 'baz');

        expect(e.get('baz')).toEqual(undefined);

    });

    it('should return itself', function () {

        var e = new Sy.Entity();

        expect(e.set('foo', 'bar')).toEqual(e);
        expect(e.register('foo')).toEqual(e);
        expect(e.lock(['foo'])).toEqual(e);

    });

    it('should create a connection entity if set data as string', function () {

        var e = new Sy.Entity();

        namespace('App.Bundle.Foo.Entity');

        App.Bundle.Foo.Entity.Baz = function () {
            Sy.Entity.call(this);
        };
        App.Bundle.Foo.Entity.Baz.prototype = Object.create(Sy.Entity.prototype);

        e.register('foobarbaz', 'Foo::Baz');
        e.set('foobarbaz', 'foo');

        expect(e.get('foobarbaz') instanceof App.Bundle.Foo.Entity.Baz).toBe(true);
        expect(e.get('foobarbaz').get('uuid')).toEqual('foo');

    });

});<|endoftext|>


<commit_before>describe("inject-pattern", function() {
    var pattern;

    requireDependencies(["patterns/inject"], function(cls) {
        pattern = cls;
    });

    // Reset the lab before each test
    beforeEach(function() {
        $("#lab *").remove();
    });

    describe("Functional tests", function() {

        describe("extract/verifyConfig", function() {
            var $a, $target;

            beforeEach(function() {
                $a = $('link');
                $target = $('
');

                $("#lab").append($a).append($target);
            });

            it("fall back to href id", function() {
                var cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs.length).toBe(1);
                expect(cfgs[0].source).toBe('#someid');
                expect(cfgs[0].target).toBe('#someid');
            });

            it("take first positional option as source and target", function() {
                var cfgs;

                $a.attr('data-pat-inject', '#otherid');
                $target.attr('id', 'otherid');
                cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs[0].source).toBe('#otherid');
                expect(cfgs[0].target).toBe('#otherid');
            });

            it("take two positional options as source and target resp.", function() {
                var cfgs;

                $a.attr('data-pat-inject', '#otherid; #yetanotherid');
                $target.attr('id', 'yetanotherid');
                cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs[0].source).toBe('#otherid');
                expect(cfgs[0].target).toBe('#yetanotherid');
            });

            it("create target if it doesn't exist", function() {
                var cfgs = pattern.extractConfig($a);

                $target.remove();
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                $target = $('#someid');
                this.after(function() { $target.remove(); });
                expect($target.length).toBeGreaterThan(0);
                expect($target.parent().prop('tagName')).toBe('BODY');
            });
        });
    });

    describe("DOM tests", function() {

        describe("inject on anchor", function() {
            var $a, $div, answer;

            answer = function(html) {
                expect($.ajax).toHaveBeenCalled();
                $.ajax.mostRecentCall.args[0]['success'](html);
            };

            beforeEach(function() {
                $a = $('link'),
                $div = $('
');
                $("#lab").append($a).append($div);

                spyOn($, "ajax");
            });

            it("fetches url on click", function() {
                pattern.init($a);

                $a.trigger("click");

                expect($.ajax).toHaveBeenCalled();
                expect($.ajax.mostRecentCall.args[0]['url']).toBe("test.html");
            });

            it("injects into existing div", function() {
                pattern.init($a);
                $a.trigger("click");
                answer('
replacement
');

                expect($div.html()).toBe("replacement");
            });

            it("injects multiple times", function() {
                pattern.init($a);
                $a.trigger("click");
                answer('
replacement
');
                expect($div.html()).toBe("replacement");

                $a.trigger("click");
                answer('
new replacement
');
                expect($div.html()).toBe("new replacement");
            });

            it("takes multiple source-target pairs", function() {
                $a.attr("data-pat-inject", "#someid1; #otherid1 && #someid2; #otherid2");
                $target1 = $('
');
                $target2 = $('
');
                $div.append($target1).append($target2);

                pattern.init($a);
                $a.trigger("click");
                answer(''
                       + '
repl1
'
                       + '
repl2
'
                       + '');

                expect($target1.html()).toBe("repl1");
                expect($target2.html()).toBe("repl2");
            });

            it("acts on other selectors as well", function() {
                $a.attr("data-pat-inject", "target: #someid > .someclass");
                $target1 = $('
');
                $target2 = $('
');
                $div.append($target1).append($target2);

                pattern.init($a);
                $a.trigger("click");
                answer(''
                       + '
repl
'
                       + '');

                expect($target1.html()).toBe("repl");
                expect($target2.html()).toBe("repl");
            });

            it("sets/unsets load class 'injecting'", function() {
                var callback = jasmine.createSpy("patterns-injected");
                $(document).on("patterns-injected", callback);

                pattern.init($a);
                $a.trigger("click");

                expect($div.hasClass("injecting")).toBeTruthy();

                answer(''
                       + '
repl
'
                       + '');
                expect($div.hasClass("injecting")).toBeFalsy();

                expect(callback).toHaveBeenCalled();
            });

            // XXX: Tests for ::element ::after, ...
        });

        describe("inject on forms", function() {
            // XXX
        });
    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>tests/inject: move answer helper to be useful for form tests as well<commit_after>describe("inject-pattern", function() {
    var pattern;

    requireDependencies(["patterns/inject"], function(cls) {
        pattern = cls;
    });

    // Reset the lab before each test
    beforeEach(function() {
        $("#lab *").remove();
    });

    describe("Functional tests", function() {

        describe("extract/verifyConfig", function() {
            var $a, $target;

            beforeEach(function() {
                $a = $('link');
                $target = $('
');

                $("#lab").append($a).append($target);
            });

            it("fall back to href id", function() {
                var cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs.length).toBe(1);
                expect(cfgs[0].source).toBe('#someid');
                expect(cfgs[0].target).toBe('#someid');
            });

            it("take first positional option as source and target", function() {
                var cfgs;

                $a.attr('data-pat-inject', '#otherid');
                $target.attr('id', 'otherid');
                cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs[0].source).toBe('#otherid');
                expect(cfgs[0].target).toBe('#otherid');
            });

            it("take two positional options as source and target resp.", function() {
                var cfgs;

                $a.attr('data-pat-inject', '#otherid; #yetanotherid');
                $target.attr('id', 'yetanotherid');
                cfgs = pattern.extractConfig($a);
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                expect(cfgs[0].source).toBe('#otherid');
                expect(cfgs[0].target).toBe('#yetanotherid');
            });

            it("create target if it doesn't exist", function() {
                var cfgs = pattern.extractConfig($a);

                $target.remove();
                expect(pattern.verifyConfig(cfgs)).toBeTruthy();

                $target = $('#someid');
                this.after(function() { $target.remove(); });
                expect($target.length).toBeGreaterThan(0);
                expect($target.parent().prop('tagName')).toBe('BODY');
            });
        });
    });

    describe("DOM tests", function() {
        var answer = function(html) {
            expect($.ajax).toHaveBeenCalled();
            $.ajax.mostRecentCall.args[0]['success'](html);
        };

        beforeEach(function() {
            spyOn($, "ajax");
        });

        describe("inject on anchor", function() {

            var $a, $div;

            beforeEach(function() {
                $a = $('link'),
                $div = $('
');
                $("#lab").append($a).append($div);
            });

            it("fetches url on click", function() {
                pattern.init($a);

                $a.trigger("click");

                expect($.ajax).toHaveBeenCalled();
                expect($.ajax.mostRecentCall.args[0]['url']).toBe("test.html");
            });

            it("injects into existing div", function() {
                pattern.init($a);
                $a.trigger("click");
                answer('
replacement
');

                expect($div.html()).toBe("replacement");
            });

            it("injects multiple times", function() {
                pattern.init($a);
                $a.trigger("click");
                answer('
replacement
');
                expect($div.html()).toBe("replacement");

                $a.trigger("click");
                answer('
new replacement
');
                expect($div.html()).toBe("new replacement");
            });

            it("takes multiple source-target pairs", function() {
                $a.attr("data-pat-inject", "#someid1; #otherid1 && #someid2; #otherid2");
                $target1 = $('
');
                $target2 = $('
');
                $div.append($target1).append($target2);

                pattern.init($a);
                $a.trigger("click");
                answer(''
                       + '
repl1
'
                       + '
repl2
'
                       + '');

                expect($target1.html()).toBe("repl1");
                expect($target2.html()).toBe("repl2");
            });

            it("acts on other selectors as well", function() {
                $a.attr("data-pat-inject", "target: #someid > .someclass");
                $target1 = $('
');
                $target2 = $('
');
                $div.append($target1).append($target2);

                pattern.init($a);
                $a.trigger("click");
                answer(''
                       + '
repl
'
                       + '');

                expect($target1.html()).toBe("repl");
                expect($target2.html()).toBe("repl");
            });

            it("sets/unsets load class 'injecting'", function() {
                var callback = jasmine.createSpy("patterns-injected");
                $(document).on("patterns-injected", callback);

                pattern.init($a);
                $a.trigger("click");

                expect($div.hasClass("injecting")).toBeTruthy();

                answer(''
                       + '
repl
'
                       + '');
                expect($div.hasClass("injecting")).toBeFalsy();

                expect(callback).toHaveBeenCalled();
            });

            // XXX: Tests for ::element ::after, ...
        });

        describe("inject on forms", function() {
            // XXX
        });
    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>


<commit_before>dojo.provide("dijit.tests.module");

try{
	dojo.require("dijit.tests._base.manager");
	dojo.require("dijit.tests._Templated");
	dojo.require("dijit.tests.widgetsInTemplate");
	dojo.require("dijit.tests.Container");
	dojo.require("dijit.tests.layout.ContentPane");
	dojo.require("dijit.tests.onklick");
}catch(e){
	doh.debug(e);
}

<commit_msg>Convert Form test to DOH format. Refs #3835.<commit_after>dojo.provide("dijit.tests.module");

try{
	dojo.require("dijit.tests._base.manager");
	dojo.require("dijit.tests._Templated");
	dojo.require("dijit.tests.widgetsInTemplate");
	dojo.require("dijit.tests.Container");
	dojo.require("dijit.tests.layout.ContentPane");
	dojo.require("dijit.tests.onklick");
	dojo.require("dijit.tests.form.Form");
}catch(e){
	doh.debug(e);
}

<|endoftext|>


<commit_before>import webpack from 'webpack'
import WebpackDevServer from 'webpack-dev-server'
import { spawn } from 'child_process'
import waitForPort from 'wait-for-port'
import fs from 'fs'
import path from 'path'
import mkdirp from 'mkdirp'
import minilog from 'minilog'
import _ from 'lodash'
import crypto from 'crypto'
const pkg = require('../package.json');

import configs from './webpack.config'

minilog.enable();

const logBack = minilog('webpack-for-backend');
const logFront = minilog('webpack-for-frontend');

const [ serverConfig, clientConfig, dllConfig ] = configs;
const __WINDOWS__ = /^win/.test(process.platform);

var server;
var startBackend = false;

process.on('exit', () => {
  if (server) {
    server.kill('SIGTERM');
  }
});

function createDirs(dir) {
  mkdirp.sync(dir);
}

function runServer(path) {
  if (startBackend) {
    startBackend = false;
    logBack('Starting backend');
    server = spawn('node', [path]);
    server.stdout.on('data', data => {
      process.stdout.write(data);
    });
    server.stderr.on('data', data => {
      process.stderr.write(data);
    });
    server.on('exit', code => {
      if (code === 250) {
        // App requested full reload
        startBackend = true;
      }
      logBack('Backend has been stopped');
      server = undefined;
      runServer(path);
    });
  }
}

function webpackReporter(log, err, stats) {
  if (err) {
    log(err.stack);
    throw new Error("Build error");
  }
  if (stats) {
    log(stats.toString({
      hash: false,
      version: false,
      timings: true,
      assets: false,
      chunks: false,
      modules: false,
      reasons: false,
      children: false,
      source: true,
      errors: true,
      errorDetails: true,
      warnings: true,
      publicPath: false,
      colors: true
    }));

    if (!__DEV__) {
      const dir = log === logFront ?
        pkg.app.frontendBuildDir :
        pkg.app.backendBuildDir;
      createDirs(dir);
      fs.writeFileSync(path.join(dir, 'stats.json'), JSON.stringify(stats.toJson()));
    }
  }
}

function startClient() {
  try {
    const reporter = (...args) => webpackReporter(logFront, ...args);

    if (__DEV__) {
      clientConfig.entry.bundle.push('webpack/hot/dev-server',
          `webpack-dev-server/client?http://localhost:${pkg.app.webpackDevPort}/`);
      clientConfig.plugins.push(new webpack.optimize.OccurenceOrderPlugin(),
          new webpack.HotModuleReplacementPlugin(),
          new webpack.NoErrorsPlugin());
      clientConfig.output.path = '/';
      clientConfig.debug = true;
      startWebpackDevServer(clientConfig, reporter);
    } else {
      const compiler = webpack(clientConfig);

      compiler.run(reporter);
    }
  } catch (err) {
    logFront(err.stack);
  }
}

var backendReloadCount = 0;
function increaseBackendReloadCount() {
  fs.writeFileSync(path.join(pkg.app.backendBuildDir, 'backend_reload_count.js'),
    `module.exports = {reloadCount: ${backendReloadCount}};\n`);
  backendReloadCount++;
}

function startServer() {
  try {
    const reporter = (...args) => webpackReporter(logBack, ...args);

    if (__DEV__) {
      if (__WINDOWS__) {
        serverConfig.entry.index.push('webpack/hot/poll?1000');
      } else {
        serverConfig.entry.index.push('webpack/hot/signal.js');
      }
      serverConfig.plugins.push(new webpack.optimize.OccurenceOrderPlugin(),
        new webpack.HotModuleReplacementPlugin());
      serverConfig.debug = true;
      if (pkg.app.frontendRefreshOnBackendChange) {
        increaseBackendReloadCount();
      }
    }

    const compiler = webpack(serverConfig);

    if (__DEV__) {
      compiler.plugin('compilation', compilation => {
        compilation.plugin('after-optimize-assets', assets => {
          // Patch webpack-generated original source files path, by stripping hash after filename
          const mapKey = _.findKey(assets, (v, k) => k.endsWith('.map'));
          if (mapKey) {
            var srcMap = JSON.parse(assets[mapKey]._value);
            for (var idx in srcMap.sources) {
              srcMap.sources[idx] = srcMap.sources[idx].split(';')[0];
            }
            assets[mapKey]._value = JSON.stringify(srcMap);
          }
        });
      });

      compiler.watch({}, reporter);

      compiler.plugin('done', stats => {
        const { output } = serverConfig;
        startBackend = true;
        if (server) {
          if (!__WINDOWS__) {
            server.kill('SIGUSR2');
          }

          if (pkg.app.frontendRefreshOnBackendChange) {
            for(let module of stats.compilation.modules) {
              if(module.built && module.resource &&
                module.resource.indexOf(path.resolve('./src/server')) === 0) {
                // Force front-end refresh on back-end change
                logBack.debug('Force front-end current page refresh, due to change in backend at:', module.resource);
                increaseBackendReloadCount();
                break;
              }
            }
          }
        } else {
          runServer(path.join(output.path, 'index.js'));
        }
      });
    } else {
      compiler.run(reporter);
    }
  } catch (err) {
    logBack(err.stack);
  }
}

function startWebpackDevServer(clientConfig, reporter) {
  let compiler = webpack(clientConfig);

  compiler.plugin('done', stats => {
    const dir = pkg.app.frontendBuildDir;
    createDirs(dir);
    if (stats.compilation.assets['assets.json']) {
      const assetsMap = JSON.parse(stats.compilation.assets['assets.json'].source());
      _.each(stats.toJson().assetsByChunkName, (assets, bundle) => {
        const bundleJs = assets.constructor === Array ? assets[0] : assets;
        assetsMap[`${bundle}.js`] = bundleJs;
        if (assets.length > 1) {
          assetsMap[`${bundle}.js.map`] = `${bundleJs}.map`;
        }
      });
      if (pkg.app.webpackDll) {
        let json = JSON.parse(fs.readFileSync(path.join(pkg.app.frontendBuildDir, 'vendor_dll_hashes.json')));
        assetsMap['vendor.js'] = json.name;
      }
      fs.writeFileSync(path.join(dir, 'assets.json'), JSON.stringify(assetsMap));
    }
  });

  waitForPort('localhost', pkg.app.apiPort, function(err) {
    if (err) throw new Error(err);

    const app = new WebpackDevServer(compiler, {
      hot: true,
      contentBase: '/',
      publicPath: clientConfig.output.publicPath,
      headers: { 'Access-Control-Allow-Origin': '*' },
      proxy: {
        '*': `http://localhost:${pkg.app.apiPort}`
      },
      noInfo: true,
      reporter: ({state, stats}) => {
        if (state) {
          logFront("bundle is now VALID.");
        } else {
          logFront("bundle is now INVALID.");
        }
        reporter(null, stats);
      }
    });

    logFront(`Webpack dev server listening on ${pkg.app.webpackDevPort}`);
    app.listen(pkg.app.webpackDevPort);
  });
}

function useWebpackDll() {
  console.log("Using Webpack DLL vendor bundle");
  const jsonPath = path.join('..', pkg.app.frontendBuildDir, 'vendor_dll.json');
  clientConfig.plugins.push(new webpack.DllReferencePlugin({
    context:  process.cwd(),
    manifest: require(jsonPath)
  }));
  serverConfig.plugins.push(new webpack.DllReferencePlugin({
    context:  process.cwd(),
    manifest: require(jsonPath)
  }));
}

function isDllValid() {
  try {
    const hashesPath = path.join(pkg.app.frontendBuildDir, 'vendor_dll_hashes.json');
    if (!fs.existsSync(hashesPath)) {
      console.warn("Vendor DLL does not exists");
      return false;
    }
    let meta = JSON.parse(fs.readFileSync(hashesPath));
    if (!fs.existsSync(path.join(pkg.app.frontendBuildDir, meta.name))) {
      console.warn("Vendor DLL does not exists");
      return false;
    }
    if (!_.isEqual(meta.modules, dllConfig.entry.vendor)) {
      console.warn('Modules bundled into vendor DLL changed, need to rebuild it');
      return false;
    }

    let json = JSON.parse(fs.readFileSync(path.join(pkg.app.frontendBuildDir, 'vendor_dll.json')));

    for (let filename of Object.keys(json.content)) {
      const hash = crypto.createHash('md5').update(fs.readFileSync(filename)).digest('hex');
      if (meta.hashes[filename] !== hash) {
        console.warn(`Hash for vendor DLL file ${filename} changed, need to rebuild vendor bundle`);
        return false;
      }
    }

    return true;
  } catch (e) {
    console.warn('Error checking vendor bundle, regenerating it...', e);

    return false;
  }
}

function buildDll() {
  return new Promise((done) => {
    if (!isDllValid()) {
      console.log("Generating vendor DLL bundle...");

      const compiler = webpack(dllConfig);

      compiler.run((err, stats) => {
        let json = JSON.parse(fs.readFileSync(path.join(pkg.app.frontendBuildDir, 'vendor_dll.json')));
        const meta = {name: _.keys(stats.compilation.assets)[0], hashes: {}, modules: dllConfig.entry.vendor};
        for (let filename of Object.keys(json.content)) {
          meta.hashes[filename] = crypto.createHash('md5').update(fs.readFileSync(filename)).digest('hex');
          fs.writeFileSync(path.join(pkg.app.frontendBuildDir, 'vendor_dll_hashes.json'), JSON.stringify(meta));
        }
        done();
      });
    } else {
      done();
    }
  });
}

function startWebpack() {
  startServer();
  startClient();
}

if (!__DEV__ || !pkg.app.webpackDll) {
  startWebpack();
} else {
  buildDll().then(function() {
    useWebpackDll();
    startWebpack();
  });
}<commit_msg>Ensure that dir exitst before writing backend_reload_count.js<commit_after>import webpack from 'webpack'
import WebpackDevServer from 'webpack-dev-server'
import { spawn } from 'child_process'
import waitForPort from 'wait-for-port'
import fs from 'fs'
import path from 'path'
import mkdirp from 'mkdirp'
import minilog from 'minilog'
import _ from 'lodash'
import crypto from 'crypto'
const pkg = require('../package.json');

import configs from './webpack.config'

minilog.enable();

const logBack = minilog('webpack-for-backend');
const logFront = minilog('webpack-for-frontend');

const [ serverConfig, clientConfig, dllConfig ] = configs;
const __WINDOWS__ = /^win/.test(process.platform);

var server;
var startBackend = false;

process.on('exit', () => {
  if (server) {
    server.kill('SIGTERM');
  }
});

function createDirs(dir) {
  mkdirp.sync(dir);
}

function runServer(path) {
  if (startBackend) {
    startBackend = false;
    logBack('Starting backend');
    server = spawn('node', [path]);
    server.stdout.on('data', data => {
      process.stdout.write(data);
    });
    server.stderr.on('data', data => {
      process.stderr.write(data);
    });
    server.on('exit', code => {
      if (code === 250) {
        // App requested full reload
        startBackend = true;
      }
      logBack('Backend has been stopped');
      server = undefined;
      runServer(path);
    });
  }
}

function webpackReporter(log, err, stats) {
  if (err) {
    log(err.stack);
    throw new Error("Build error");
  }
  if (stats) {
    log(stats.toString({
      hash: false,
      version: false,
      timings: true,
      assets: false,
      chunks: false,
      modules: false,
      reasons: false,
      children: false,
      source: true,
      errors: true,
      errorDetails: true,
      warnings: true,
      publicPath: false,
      colors: true
    }));

    if (!__DEV__) {
      const dir = log === logFront ?
        pkg.app.frontendBuildDir :
        pkg.app.backendBuildDir;
      createDirs(dir);
      fs.writeFileSync(path.join(dir, 'stats.json'), JSON.stringify(stats.toJson()));
    }
  }
}

function startClient() {
  try {
    const reporter = (...args) => webpackReporter(logFront, ...args);

    if (__DEV__) {
      clientConfig.entry.bundle.push('webpack/hot/dev-server',
          `webpack-dev-server/client?http://localhost:${pkg.app.webpackDevPort}/`);
      clientConfig.plugins.push(new webpack.optimize.OccurenceOrderPlugin(),
          new webpack.HotModuleReplacementPlugin(),
          new webpack.NoErrorsPlugin());
      clientConfig.output.path = '/';
      clientConfig.debug = true;
      startWebpackDevServer(clientConfig, reporter);
    } else {
      const compiler = webpack(clientConfig);

      compiler.run(reporter);
    }
  } catch (err) {
    logFront(err.stack);
  }
}

var backendReloadCount = 0;
function increaseBackendReloadCount() {
  createDirs(pkg.app.backendBuildDir);
  fs.writeFileSync(path.join(pkg.app.backendBuildDir, 'backend_reload_count.js'),
    `module.exports = {reloadCount: ${backendReloadCount}};\n`);
  backendReloadCount++;
}

function startServer() {
  try {
    const reporter = (...args) => webpackReporter(logBack, ...args);

    if (__DEV__) {
      if (__WINDOWS__) {
        serverConfig.entry.index.push('webpack/hot/poll?1000');
      } else {
        serverConfig.entry.index.push('webpack/hot/signal.js');
      }
      serverConfig.plugins.push(new webpack.optimize.OccurenceOrderPlugin(),
        new webpack.HotModuleReplacementPlugin());
      serverConfig.debug = true;
      if (pkg.app.frontendRefreshOnBackendChange) {
        increaseBackendReloadCount();
      }
    }

    const compiler = webpack(serverConfig);

    if (__DEV__) {
      compiler.plugin('compilation', compilation => {
        compilation.plugin('after-optimize-assets', assets => {
          // Patch webpack-generated original source files path, by stripping hash after filename
          const mapKey = _.findKey(assets, (v, k) => k.endsWith('.map'));
          if (mapKey) {
            var srcMap = JSON.parse(assets[mapKey]._value);
            for (var idx in srcMap.sources) {
              srcMap.sources[idx] = srcMap.sources[idx].split(';')[0];
            }
            assets[mapKey]._value = JSON.stringify(srcMap);
          }
        });
      });

      compiler.watch({}, reporter);

      compiler.plugin('done', stats => {
        const { output } = serverConfig;
        startBackend = true;
        if (server) {
          if (!__WINDOWS__) {
            server.kill('SIGUSR2');
          }

          if (pkg.app.frontendRefreshOnBackendChange) {
            for(let module of stats.compilation.modules) {
              if(module.built && module.resource &&
                module.resource.indexOf(path.resolve('./src/server')) === 0) {
                // Force front-end refresh on back-end change
                logBack.debug('Force front-end current page refresh, due to change in backend at:', module.resource);
                increaseBackendReloadCount();
                break;
              }
            }
          }
        } else {
          runServer(path.join(output.path, 'index.js'));
        }
      });
    } else {
      compiler.run(reporter);
    }
  } catch (err) {
    logBack(err.stack);
  }
}

function startWebpackDevServer(clientConfig, reporter) {
  let compiler = webpack(clientConfig);

  compiler.plugin('done', stats => {
    const dir = pkg.app.frontendBuildDir;
    createDirs(dir);
    if (stats.compilation.assets['assets.json']) {
      const assetsMap = JSON.parse(stats.compilation.assets['assets.json'].source());
      _.each(stats.toJson().assetsByChunkName, (assets, bundle) => {
        const bundleJs = assets.constructor === Array ? assets[0] : assets;
        assetsMap[`${bundle}.js`] = bundleJs;
        if (assets.length > 1) {
          assetsMap[`${bundle}.js.map`] = `${bundleJs}.map`;
        }
      });
      if (pkg.app.webpackDll) {
        let json = JSON.parse(fs.readFileSync(path.join(pkg.app.frontendBuildDir, 'vendor_dll_hashes.json')));
        assetsMap['vendor.js'] = json.name;
      }
      fs.writeFileSync(path.join(dir, 'assets.json'), JSON.stringify(assetsMap));
    }
  });

  waitForPort('localhost', pkg.app.apiPort, function(err) {
    if (err) throw new Error(err);

    const app = new WebpackDevServer(compiler, {
      hot: true,
      contentBase: '/',
      publicPath: clientConfig.output.publicPath,
      headers: { 'Access-Control-Allow-Origin': '*' },
      proxy: {
        '*': `http://localhost:${pkg.app.apiPort}`
      },
      noInfo: true,
      reporter: ({state, stats}) => {
        if (state) {
          logFront("bundle is now VALID.");
        } else {
          logFront("bundle is now INVALID.");
        }
        reporter(null, stats);
      }
    });

    logFront(`Webpack dev server listening on ${pkg.app.webpackDevPort}`);
    app.listen(pkg.app.webpackDevPort);
  });
}

function useWebpackDll() {
  console.log("Using Webpack DLL vendor bundle");
  const jsonPath = path.join('..', pkg.app.frontendBuildDir, 'vendor_dll.json');
  clientConfig.plugins.push(new webpack.DllReferencePlugin({
    context:  process.cwd(),
    manifest: require(jsonPath)
  }));
  serverConfig.plugins.push(new webpack.DllReferencePlugin({
    context:  process.cwd(),
    manifest: require(jsonPath)
  }));
}

function isDllValid() {
  try {
    const hashesPath = path.join(pkg.app.frontendBuildDir, 'vendor_dll_hashes.json');
    if (!fs.existsSync(hashesPath)) {
      console.warn("Vendor DLL does not exists");
      return false;
    }
    let meta = JSON.parse(fs.readFileSync(hashesPath));
    if (!fs.existsSync(path.join(pkg.app.frontendBuildDir, meta.name))) {
      console.warn("Vendor DLL does not exists");
      return false;
    }
    if (!_.isEqual(meta.modules, dllConfig.entry.vendor)) {
      console.warn('Modules bundled into vendor DLL changed, need to rebuild it');
      return false;
    }

    let json = JSON.parse(fs.readFileSync(path.join(pkg.app.frontendBuildDir, 'vendor_dll.json')));

    for (let filename of Object.keys(json.content)) {
      const hash = crypto.createHash('md5').update(fs.readFileSync(filename)).digest('hex');
      if (meta.hashes[filename] !== hash) {
        console.warn(`Hash for vendor DLL file ${filename} changed, need to rebuild vendor bundle`);
        return false;
      }
    }

    return true;
  } catch (e) {
    console.warn('Error checking vendor bundle, regenerating it...', e);

    return false;
  }
}

function buildDll() {
  return new Promise((done) => {
    if (!isDllValid()) {
      console.log("Generating vendor DLL bundle...");

      const compiler = webpack(dllConfig);

      compiler.run((err, stats) => {
        let json = JSON.parse(fs.readFileSync(path.join(pkg.app.frontendBuildDir, 'vendor_dll.json')));
        const meta = {name: _.keys(stats.compilation.assets)[0], hashes: {}, modules: dllConfig.entry.vendor};
        for (let filename of Object.keys(json.content)) {
          meta.hashes[filename] = crypto.createHash('md5').update(fs.readFileSync(filename)).digest('hex');
          fs.writeFileSync(path.join(pkg.app.frontendBuildDir, 'vendor_dll_hashes.json'), JSON.stringify(meta));
        }
        done();
      });
    } else {
      done();
    }
  });
}

function startWebpack() {
  startServer();
  startClient();
}

if (!__DEV__ || !pkg.app.webpackDll) {
  startWebpack();
} else {
  buildDll().then(function() {
    useWebpackDll();
    startWebpack();
  });
}<|endoftext|>


<commit_before>'use strict';

var chai = require('chai');
chai.use(require('chai-as-promised'));
chai.use(require('dirty-chai'));
var expect = chai.expect;

describe.skip('search page', function() {
  before(function() {
    browser.get('http://localhost:9000');
    element(by.model('home.searchInput')).sendKeys('chocolat', protractor.Key.ENTER);
  });

  it('should have its own controller', function() {
    expect(element(by.css('[ng-controller]')).isPresent()).to.eventually.equal(true);
    expect(element(by.css('[ng-controller]')).getAttribute('ng-controller')).to.eventually.equal('SearchController as search');
  });

  it('should have a given title', function() {
    expect(browser.getTitle()).to.eventually.equal('Chocolat : nos recettes de chocolat délicieuses');
  });

  it('should display the breadcrumbs', function() {
    expect(element(by.id('mrm_locationbar')).isPresent()).to.eventually.equal(true);
  });

  describe('to home page', function() {
    afterEach(function() {
      browser.get('http://localhost:9000');
      element(by.model('home.searchInput')).sendKeys('chocolat', protractor.Key.ENTER);
    });

    it('should go to home page on click on the breadcrumbs', function() {
      var link = element(by.id('mrm_locationbar')).element(by.tagName('a'));
      link.click()
      expect(browser.getLocationAbsUrl()).to.eventually.match(/\/$/);
    });
  });

  it('should display a search input, with a given placeholder initialized to my search value', function() {
    expect(element(by.model('search.input')).getTagName()).to.eventually.equal('input');
    expect(element(by.model('search.input')).getAttribute('type')).to.eventually.equal('text');
    expect(element(by.model('search.input')).isDisplayed()).to.eventually.equal(true);
    expect(element(by.model('search.input')).getAttribute('placeholder')).to.eventually.exist();
    expect(element(by.model('search.input')).getAttribute('value')).to.eventually.equal('chocolat');
  });

  it('should display a search button', function() {
    expect(element(by.id('searchButton')).isDisplayed()).to.eventually.equal(true);
  });

  describe('new search', function() {
    afterEach(function() {
      browser.get('http://localhost:9000');
      element(by.model('home.searchInput')).sendKeys('chocolat', protractor.Key.ENTER);
    });

    it('should make a new search on click on the search button if a new text has been set', function() {
      element(by.model('search.input')).clear().sendKeys('durian', protractor.Key.ENTER);
      expect(element(by.model('search.input')).getAttribute('value')).to.eventually.equal('durian');
      expect(element(by.id('searchSummary')).getText()).to.eventually.match(/durian/);
      expect(element.all(by.repeater('result in search.searchResult.elements')).count()).to.eventually.equal(1);
    expect(browser.getTitle()).to.eventually.equal('Durian : nos recettes de durian délicieuses');
    });

    it('should not make a new search on click on the search button if no new text has been set', function() {
      element(by.model('search.input')).clear().sendKeys('chocolat', protractor.Key.ENTER);
      expect(element(by.model('search.input')).getAttribute('value')).not.to.eventually.equal('durian');
      expect(element(by.id('searchSummary')).getText()).not.to.eventually.match(/durian/);
    });

    it('should not make a new search on click on the search button if no new text has been set', function() {
      element(by.model('search.input')).clear().sendKeys(protractor.Key.ENTER);
      expect(element(by.id('searchSummary')).getText()).not.to.eventually.match(/Recherche pour ""/);
    });
  });

  describe('empty search', function() {
    afterEach(function() {
      browser.get('http://localhost:9000');
      element(by.model('home.searchInput')).sendKeys('chocolat', protractor.Key.ENTER);
    });

    it('should display no element and suggestion but not total number', function() {
      element(by.model('search.input')).clear().sendKeys('else', protractor.Key.ENTER);
      expect(element(by.id('searchSummary')).getText()).to.eventually.match(/ucun résultat/);
      expect(element(by.id('searchSummary')).getText()).to.eventually.match(/orthographe/);
      expect(element(by.id('searchSummary')).getText()).not.to.eventually.match(/0 \/ 0/);
    });

    it('should display all suggestions, which launch a new search', function() {
      element(by.model('search.input')).clear().sendKeys('else', protractor.Key.ENTER);
      expect(element(by.id('searchSummary')).getText()).to.eventually.match(/chocolat ou durian/);

      element(by.id('searchSummary')).all(by.tagName('a')).get(0).click();
      expect(element(by.model('search.input')).getAttribute('value')).to.eventually.equal('chocolat');
    });

    it('should not display pagination', function() {
      element(by.model('search.input')).clear().sendKeys('else', protractor.Key.ENTER);
      expect(element.all(by.className('m_resultat_liste_pagination')).count()).to.eventually.equal(0);
    });
  });

  it('should display a summary for the current search that contains the searched item, the number of elements found and displayed', function() {
    expect(element(by.id('searchSummary')).isDisplayed()).to.eventually.equal(true);
    expect(element(by.id('searchSummary')).getText()).to.eventually.match(/chocolat/);
    expect(element(by.id('searchSummary')).getText()).to.eventually.match(/10/);
    expect(element(by.id('searchSummary')).getText()).to.eventually.match(/30334/);
  });

  it('should not display the no element info nor the suggestion if some elements found', function() {
    expect(element(by.id('searchSummary')).getText()).not.to.eventually.match(/ucun résultat/);
    expect(element(by.id('searchSummary')).getText()).not.to.eventually.match(/orthographe/);
  });

  it('should display the 12 first recipes found', function() {
    expect(element.all(by.repeater('result in search.searchResult.elements')).count()).to.eventually.equal(12);
  });

  /*it('should highlight searched keyword', function() {
    expect(element.all(by.repeater('result in search.searchResult.elements')).get(1).element(by.class('m_texte_resultat')).getText()).to.eventually.match(/chocolat/i);
  });*/

  it('should display pagination', function() {
    expect(element(by.className('m_resultat_liste_pagination')).isDisplayed()).to.eventually.equal(true);
  });

  describe('to detail page', function() {
    afterEach(function() {
      browser.get('http://localhost:9000');
      element(by.model('home.searchInput')).sendKeys('chocolat', protractor.Key.ENTER);
    });

    it('should go to detail page on click on a result', function() {
      element.all(by.repeater('result in search.searchResult.elements')).get(7).all(by.tagName('a')).get(0).click();
      expect(browser.getLocationAbsUrl()).to.eventually.match(/\/recipe\//);
    });
  });
});<commit_msg>fix breadcrumbs test<commit_after>'use strict';

var chai = require('chai');
chai.use(require('chai-as-promised'));
chai.use(require('dirty-chai'));
var expect = chai.expect;

describe.skip('search page', function() {
  before(function() {
    browser.get('http://localhost:9000');
    element(by.model('home.searchInput')).sendKeys('chocolat', protractor.Key.ENTER);
  });

  it('should have its own controller', function() {
    expect(element(by.css('[ng-controller]')).isPresent()).to.eventually.equal(true);
    expect(element(by.css('[ng-controller]')).getAttribute('ng-controller')).to.eventually.equal('SearchController as search');
  });

  it('should have a given title', function() {
    expect(browser.getTitle()).to.eventually.equal('Chocolat : nos recettes de chocolat délicieuses');
  });

  it('should display the breadcrumbs', function() {
    expect(element(by.id('mrm_locationbar')).isPresent()).to.eventually.equal(true);
  });

  describe('to home page', function() {
    afterEach(function() {
      browser.get('http://localhost:9000');
      element(by.model('home.searchInput')).sendKeys('chocolat', protractor.Key.ENTER);
    });

    it('should go to home page on click on the breadcrumbs', function() {
      var link = element(by.id('mrm_locationbar')).element(by.css('a:first'));
      link.click();
      expect(browser.getLocationAbsUrl()).to.eventually.match(/\/$/);
    });
  });

  it('should display a search input, with a given placeholder initialized to my search value', function() {
    expect(element(by.model('search.input')).getTagName()).to.eventually.equal('input');
    expect(element(by.model('search.input')).getAttribute('type')).to.eventually.equal('text');
    expect(element(by.model('search.input')).isDisplayed()).to.eventually.equal(true);
    expect(element(by.model('search.input')).getAttribute('placeholder')).to.eventually.exist();
    expect(element(by.model('search.input')).getAttribute('value')).to.eventually.equal('chocolat');
  });

  it('should display a search button', function() {
    expect(element(by.id('searchButton')).isDisplayed()).to.eventually.equal(true);
  });

  describe('new search', function() {
    afterEach(function() {
      browser.get('http://localhost:9000');
      element(by.model('home.searchInput')).sendKeys('chocolat', protractor.Key.ENTER);
    });

    it('should make a new search on click on the search button if a new text has been set', function() {
      element(by.model('search.input')).clear().sendKeys('durian', protractor.Key.ENTER);
      expect(element(by.model('search.input')).getAttribute('value')).to.eventually.equal('durian');
      expect(element(by.id('searchSummary')).getText()).to.eventually.match(/durian/);
      expect(element.all(by.repeater('result in search.searchResult.elements')).count()).to.eventually.equal(1);
    expect(browser.getTitle()).to.eventually.equal('Durian : nos recettes de durian délicieuses');
    });

    it('should not make a new search on click on the search button if no new text has been set', function() {
      element(by.model('search.input')).clear().sendKeys('chocolat', protractor.Key.ENTER);
      expect(element(by.model('search.input')).getAttribute('value')).not.to.eventually.equal('durian');
      expect(element(by.id('searchSummary')).getText()).not.to.eventually.match(/durian/);
    });

    it('should not make a new search on click on the search button if no new text has been set', function() {
      element(by.model('search.input')).clear().sendKeys(protractor.Key.ENTER);
      expect(element(by.id('searchSummary')).getText()).not.to.eventually.match(/Recherche pour ""/);
    });
  });

  describe('empty search', function() {
    afterEach(function() {
      browser.get('http://localhost:9000');
      element(by.model('home.searchInput')).sendKeys('chocolat', protractor.Key.ENTER);
    });

    it('should display no element and suggestion but not total number', function() {
      element(by.model('search.input')).clear().sendKeys('else', protractor.Key.ENTER);
      expect(element(by.id('searchSummary')).getText()).to.eventually.match(/ucun résultat/);
      expect(element(by.id('searchSummary')).getText()).to.eventually.match(/orthographe/);
      expect(element(by.id('searchSummary')).getText()).not.to.eventually.match(/0 \/ 0/);
    });

    it('should display all suggestions, which launch a new search', function() {
      element(by.model('search.input')).clear().sendKeys('else', protractor.Key.ENTER);
      expect(element(by.id('searchSummary')).getText()).to.eventually.match(/chocolat ou durian/);

      element(by.id('searchSummary')).all(by.tagName('a')).get(0).click();
      expect(element(by.model('search.input')).getAttribute('value')).to.eventually.equal('chocolat');
    });

    it('should not display pagination', function() {
      element(by.model('search.input')).clear().sendKeys('else', protractor.Key.ENTER);
      expect(element.all(by.className('m_resultat_liste_pagination')).count()).to.eventually.equal(0);
    });
  });

  it('should display a summary for the current search that contains the searched item, the number of elements found and displayed', function() {
    expect(element(by.id('searchSummary')).isDisplayed()).to.eventually.equal(true);
    expect(element(by.id('searchSummary')).getText()).to.eventually.match(/chocolat/);
    expect(element(by.id('searchSummary')).getText()).to.eventually.match(/10/);
    expect(element(by.id('searchSummary')).getText()).to.eventually.match(/30334/);
  });

  it('should not display the no element info nor the suggestion if some elements found', function() {
    expect(element(by.id('searchSummary')).getText()).not.to.eventually.match(/ucun résultat/);
    expect(element(by.id('searchSummary')).getText()).not.to.eventually.match(/orthographe/);
  });

  it('should display the 12 first recipes found', function() {
    expect(element.all(by.repeater('result in search.searchResult.elements')).count()).to.eventually.equal(12);
  });

  /*it('should highlight searched keyword', function() {
    expect(element.all(by.repeater('result in search.searchResult.elements')).get(1).element(by.class('m_texte_resultat')).getText()).to.eventually.match(/chocolat/i);
  });*/

  it('should display pagination', function() {
    expect(element(by.className('m_resultat_liste_pagination')).isDisplayed()).to.eventually.equal(true);
  });

  describe('to detail page', function() {
    afterEach(function() {
      browser.get('http://localhost:9000');
      element(by.model('home.searchInput')).sendKeys('chocolat', protractor.Key.ENTER);
    });

    it('should go to detail page on click on a result', function() {
      element.all(by.repeater('result in search.searchResult.elements')).get(7).all(by.tagName('a')).get(0).click();
      expect(browser.getLocationAbsUrl()).to.eventually.match(/\/recipe\//);
    });
  });
});<|endoftext|>


<commit_before>const argv = require('minimist')(process.argv.slice(2))
const async = require('async')
const tape = require('tape')
const testing = require('ethereumjs-testing')
const FORK_CONFIG = argv.fork || 'Byzantium'
const skip = [
  'CreateHashCollision', // impossible hash collision on generating address
  'SuicidesMixingCoinbase', // sucides to the coinbase, since we run a blockLevel we create coinbase account.
  'TransactionMakeAccountBalanceOverflow',
  'RecursiveCreateContracts',
  'sha3_bigSize',
  'createJS_ExampleContract', // creates an account that already exsists
  'mload32bitBound_return',
  'mload32bitBound_return2',
  'QuadraticComplexitySolidity_CallDataCopy', // tests hash collisoin, sending from a contract
  'Call50000', // slow
  'Call50000_ecrec', // slow
  'Call50000_identity', // slow
  'Call50000_identity2', // slow
  'Call50000_sha256', // slow
  'Call50000_rip160', // slow
  'Call50000bytesContract50_1', // slow
  'Call50000bytesContract50_2',
  'Call1MB1024Calldepth', // slow
  'static_Call1MB1024Calldepth', // slow
  'static_Call50000', // slow
  'static_Call50000_ecrec',
  'static_Call50000_identity',
  'static_Call50000_identity2',
  'static_Call50000_rip160',
  'static_Return50000_2',
  'Callcode50000', // slow
  'Return50000', // slow
  'Return50000_2', // slow
  'uncleBlockAtBlock3AfterBlock3',
  'ForkUncle', // correct behaviour unspecified (?)
  'UncleFromSideChain', // same as ForkUncle, the TD is the same for two diffent branches so its not clear which one should be the finally chain
  'bcSimpleTransitionTest', // HF stuff
  'CALL_Bounds', // nodejs crash
  'CALLCODE_Bounds', // nodejs crash
  'CREATE_Bounds', // nodejs crash
  'CreateCollisionToEmpty', // temporary till fixed (2017-09-21)
  'TransactionCollisionToEmptyButCode', // temporary till fixed (2017-09-21)
  'TransactionCollisionToEmptyButNonce', // temporary till fixed (2017-09-21)
  'randomStatetest642', // temporary till fixed (2017-09-25)
  'DELEGATECALL_Bounds', // nodejs crash
  'RevertDepthCreateAddressCollision', // test case is wrong
  'zeroSigTransactionInvChainID', // metropolis test
  'randomStatetest643',
  'static_CreateHashCollision', // impossible hash collision on generating address
  'static_SuicidesMixingCoinbase', // sucides to the coinbase, since we run a blockLevel we create coinbase account.
  'static_TransactionMakeAccountBalanceOverflow',
  'static_RecursiveCreateContracts',
  'static_sha3_bigSize',
  'static_createJS_ExampleContract', // creates an account that already exsists
  'static_mload32bitBound_return',
  'static_mload32bitBound_return2',
  'static_QuadraticComplexitySolidity_CallDataCopy', // tests hash collisoin, sending from a contract
  'static_Call50000', // slow
  'static_Call50000_ecrec', // slow
  'static_Call50000_identity', // slow
  'static_Call50000_identity2', // slow
  'static_Call50000_sha256', // slow
  'static_Call50000_rip160', // slow
  'static_Call50000bytesContract50_1', // slow
  'static_Call50000bytesContract50_2',
  'static_Call1MB1024Calldepth', // slow
  'static_Callcode50000', // slow
  'static_Return50000', // slow
  'static_Return50000_2', // slow
  'static_uncleBlockAtBlock3AfterBlock3',
  'static_ForkUncle', // correct behaviour unspecified (?)
  'static_UncleFromSideChain', // same as ForkUncle, the TD is the same for two diffent branches so its not clear which one should be the finally chain
  'static_bcSimpleTransitionTest', // HF stuff
  'static_CALL_Bounds', // nodejs crash
  'static_CALLCODE_Bounds', // nodejs crash
  'static_CREATE_Bounds', // nodejs crash
  'static_DELEGATECALL_Bounds', // nodejs crash
  'static_RevertDepthCreateAddressCollision', // test case is wrong
  'static_zeroSigTransactionInvChainID', // metropolis test
  'zeroSigTransactionInvChainID' // metropolis test
]

/*
NOTE: VM tests have been disabled since they are generated using Frontier gas costs, and ethereumjs-vm doesn't support historical fork rules

TODO: some VM tests do not appear to be executing (don't print an "ok" statement):
...
# file: vmLogTest test: log0_emptyMem
ok 38984 valid gas usage
# file: vmLogTest test: log0_logMemStartTooHigh
# file: vmLogTest test: log0_logMemsizeTooHigh
# file: vmLogTest test: log0_logMemsizeZero
ok 38985 valid gas usage
# file: vmLogTest test: log0_nonEmptyMem
*/

const skipVM = [
  // slow performance tests
  'loop-mul',
  'loop-add-10M',
  'loop-divadd-10M',
  'loop-divadd-unr100-10M',
  'loop-exp-16b-100k',
  'loop-exp-1b-1M',
  'loop-exp-2b-100k',
  'loop-exp-32b-100k',
  'loop-exp-4b-100k',
  'loop-exp-8b-100k',
  'loop-exp-nop-1M',
  'loop-mulmod-2M',
  // some VM tests fail because the js runner executes CALLs
  // see https://github.com/ethereum/tests/wiki/VM-Tests  > Since these tests are meant only as a basic test of VM operation, the CALL and CREATE instructions are not actually executed.
  'ABAcalls0',
  'ABAcallsSuicide0',
  'ABAcallsSuicide1',
  'CallRecursiveBomb0',
  'CallToNameRegistrator0',
  'CallToPrecompiledContract',
  'CallToReturn1',
  'PostToNameRegistrator0',
  'PostToReturn1',
  'callcodeToNameRegistrator0',
  'callcodeToReturn1',
  'callstatelessToNameRegistrator0',
  'callstatelessToReturn1',
  'createNameRegistrator',
  'randomTest643' // TODO fix this
]

if (argv.r) {
  randomized(argv.r, argv.v)
} else if (argv.s) {
  runTests('GeneralStateTests', argv)
} else if (argv.v) {
  runTests('VMTests', argv)
} else if (argv.b) {
  runTests('BlockchainTests', argv)
} else if (argv.a) {
  runAll()
}

// randomized tests
// returns 1 if the tests fails
// returns 0 if the tests succeds
function randomized (stateTest) {
  const stateRunner = require('./stateRunner.js')
  let errored = false

  tape.createStream({
    objectMode: true
  }).on('data', function (row) {
    if (row.ok === false && !errored) {
      errored = true
      process.stdout.write('1')
      process.exit()
    }
  }).on('end', function () {
    process.stdout.write('0')
  })

  try {
    stateTest = JSON.parse(stateTest)
  } catch (e) {
    console.error('invalid json')
    process.exit()
  }

  var keys = Object.keys(stateTest)
  stateTest = stateTest[keys[0]]

  tape('', t => {
    stateRunner({}, stateTest, t, t.end)
  })
}

function runTests (name, runnerArgs, cb) {
  let testGetterArgs = {}
  testGetterArgs.skipTests = skip
  testGetterArgs.skipVM = skipVM
  testGetterArgs.forkConfig = FORK_CONFIG
  testGetterArgs.file = argv.file
  testGetterArgs.test = argv.test
  testGetterArgs.dir = argv.dir
  testGetterArgs.excludeDir = argv.excludeDir
  testGetterArgs.testsPath = argv.testsPath

  testGetterArgs.customStateTest = argv.customStateTest

  runnerArgs.forkConfig = FORK_CONFIG
  runnerArgs.jsontrace = argv.jsontrace
  runnerArgs.debug = argv.debug // for BlockchainTests

  // for GeneralStateTests
  runnerArgs.data = argv.data
  runnerArgs.gasLimit = argv.gas
  runnerArgs.value = argv.value

  // runnerArgs.vmtrace = true; // for VMTests

  if (argv.customStateTest) {
    const stateTestRunner = require('./GeneralStateTestsRunner.js')
    let fileName = argv.stateTestSource
    tape(name, t => {
      testing.getTestFromSource(fileName, (err, test) => {
        if (err) {
          return t.fail(err)
        }

        t.comment(`file: ${fileName} test: ${test.testName}`)
        stateTestRunner(runnerArgs, test, t, () => {
          t.end()
        })
      })
    })
  } else {
    tape(name, t => {
      const runner = require(`./${name}Runner.js`)
      testing.getTestsFromArgs(name, (fileName, testName, test) => {
        return new Promise((resolve, reject) => {
          if (name === 'VMTests') {
            // suppress some output of VMTests
            // t.comment(`file: ${fileName} test: ${testName}`)
            test.fileName = fileName
            test.testName = testName
            runner(runnerArgs, test, t, resolve)
          } else {
            t.comment(`file: ${fileName} test: ${testName}`)
            runner(runnerArgs, test, t, resolve)
          }
        }).catch(err => console.log(err))
      }, testGetterArgs).then(() => {
        t.end()
      })
    })
  }
}

function runAll () {
  require('./tester.js')
  require('./cacheTest.js')
  require('./genesishashes.js')
  async.series([
    // runTests.bind(this, 'VMTests', {}), // VM tests disabled since we don't support Frontier gas costs
    runTests.bind(this, 'GeneralStateTests', {}),
    runTests.bind(this, 'BlockchainTests', {})
  ])
}
<commit_msg>another typo<commit_after>const argv = require('minimist')(process.argv.slice(2))
const async = require('async')
const tape = require('tape')
const testing = require('ethereumjs-testing')
const FORK_CONFIG = argv.fork || 'Byzantium'
const skip = [
  'CreateHashCollision', // impossible hash collision on generating address
  'SuicidesMixingCoinbase', // sucides to the coinbase, since we run a blockLevel we create coinbase account.
  'TransactionMakeAccountBalanceOverflow',
  'RecursiveCreateContracts',
  'sha3_bigSize',
  'createJS_ExampleContract', // creates an account that already exsists
  'mload32bitBound_return',
  'mload32bitBound_return2',
  'QuadraticComplexitySolidity_CallDataCopy', // tests hash collisoin, sending from a contract
  'Call50000', // slow
  'Call50000_ecrec', // slow
  'Call50000_identity', // slow
  'Call50000_identity2', // slow
  'Call50000_sha256', // slow
  'Call50000_rip160', // slow
  'Call50000bytesContract50_1', // slow
  'Call50000bytesContract50_2',
  'Call1MB1024Calldepth', // slow
  'static_Call1MB1024Calldepth', // slow
  'static_Call50000', // slow
  'static_Call50000_ecrec',
  'static_Call50000_identity',
  'static_Call50000_identity2',
  'static_Call50000_rip160',
  'static_Return50000_2',
  'Callcode50000', // slow
  'Return50000', // slow
  'Return50000_2', // slow
  'uncleBlockAtBlock3AfterBlock3',
  'ForkUncle', // correct behaviour unspecified (?)
  'UncleFromSideChain', // same as ForkUncle, the TD is the same for two diffent branches so its not clear which one should be the finally chain
  'bcSimpleTransitionTest', // HF stuff
  'CALL_Bounds', // nodejs crash
  'CALLCODE_Bounds', // nodejs crash
  'CREATE_Bounds', // nodejs crash
  'CreateCollisionToEmpty', // temporary till fixed (2017-09-21)
  'TransactionCollisionToEmptyButCode', // temporary till fixed (2017-09-21)
  'TransactionCollisionToEmptyButNonce', // temporary till fixed (2017-09-21)
  'randomStatetest642', // temporary till fixed (2017-09-25)
  'DELEGATECALL_Bounds', // nodejs crash
  'RevertDepthCreateAddressCollision', // test case is wrong
  'zeroSigTransactionInvChainID', // metropolis test
  'randomStatetest643',
  'static_CreateHashCollision', // impossible hash collision on generating address
  'static_SuicidesMixingCoinbase', // sucides to the coinbase, since we run a blockLevel we create coinbase account.
  'static_TransactionMakeAccountBalanceOverflow',
  'static_RecursiveCreateContracts',
  'static_sha3_bigSize',
  'static_createJS_ExampleContract', // creates an account that already exsists
  'static_mload32bitBound_return',
  'static_mload32bitBound_return2',
  'static_QuadraticComplexitySolidity_CallDataCopy', // tests hash collisoin, sending from a contract
  'static_Call50000', // slow
  'static_Call50000_ecrec', // slow
  'static_Call50000_identity', // slow
  'static_Call50000_identity2', // slow
  'static_Call50000_sha256', // slow
  'static_Call50000_rip160', // slow
  'static_Call50000bytesContract50_1', // slow
  'static_Call50000bytesContract50_2',
  'static_Call1MB1024Calldepth', // slow
  'static_Callcode50000', // slow
  'static_Return50000', // slow
  'static_Return50000_2', // slow
  'static_uncleBlockAtBlock3AfterBlock3',
  'static_ForkUncle', // correct behaviour unspecified (?)
  'static_UncleFromSideChain', // same as ForkUncle, the TD is the same for two diffent branches so its not clear which one should be the finally chain
  'static_bcSimpleTransitionTest', // HF stuff
  'static_CALL_Bounds', // nodejs crash
  'static_CALLCODE_Bounds', // nodejs crash
  'static_CREATE_Bounds', // nodejs crash
  'static_DELEGATECALL_Bounds', // nodejs crash
  'static_RevertDepthCreateAddressCollision', // test case is wrong
  'static_zeroSigTransactionInvChainID', // metropolis test
  'zeroSigTransactionInvChainID' // metropolis test
]

/*
NOTE: VM tests have been disabled since they are generated using Frontier gas costs, and ethereumjs-vm doesn't support historical fork rules

TODO: some VM tests do not appear to be executing (don't print an "ok" statement):
...
# file: vmLogTest test: log0_emptyMem
ok 38984 valid gas usage
# file: vmLogTest test: log0_logMemStartTooHigh
# file: vmLogTest test: log0_logMemsizeTooHigh
# file: vmLogTest test: log0_logMemsizeZero
ok 38985 valid gas usage
# file: vmLogTest test: log0_nonEmptyMem
*/

const skipVM = [
  // slow performance tests
  'loop-mul',
  'loop-add-10M',
  'loop-divadd-10M',
  'loop-divadd-unr100-10M',
  'loop-exp-16b-100k',
  'loop-exp-1b-1M',
  'loop-exp-2b-100k',
  'loop-exp-32b-100k',
  'loop-exp-4b-100k',
  'loop-exp-8b-100k',
  'loop-exp-nop-1M',
  'loop-mulmod-2M',
  // some VM tests fail because the js runner executes CALLs
  // see https://github.com/ethereum/tests/wiki/VM-Tests  > Since these tests are meant only as a basic test of VM operation, the CALL and CREATE instructions are not actually executed.
  'ABAcalls0',
  'ABAcallsSuicide0',
  'ABAcallsSuicide1',
  'CallRecursiveBomb0',
  'CallToNameRegistrator0',
  'CallToPrecompiledContract',
  'CallToReturn1',
  'PostToNameRegistrator0',
  'PostToReturn1',
  'callcodeToNameRegistrator0',
  'callcodeToReturn1',
  'callstatelessToNameRegistrator0',
  'callstatelessToReturn1',
  'createNameRegistrator',
  'randomTest643' // TODO fix this
]

if (argv.r) {
  randomized(argv.r, argv.v)
} else if (argv.s) {
  runTests('GeneralStateTests', argv)
} else if (argv.v) {
  runTests('VMTests', argv)
} else if (argv.b) {
  runTests('BlockchainTests', argv)
} else if (argv.a) {
  runAll()
}

// randomized tests
// returns 1 if the tests fails
// returns 0 if the tests succeds
function randomized (stateTest) {
  const stateRunner = require('./stateRunner.js')
  let errored = false

  tape.createStream({
    objectMode: true
  }).on('data', function (row) {
    if (row.ok === false && !errored) {
      errored = true
      process.stdout.write('1')
      process.exit()
    }
  }).on('end', function () {
    process.stdout.write('0')
  })

  try {
    stateTest = JSON.parse(stateTest)
  } catch (e) {
    console.error('invalid json')
    process.exit()
  }

  var keys = Object.keys(stateTest)
  stateTest = stateTest[keys[0]]

  tape('', t => {
    stateRunner({}, stateTest, t, t.end)
  })
}

function runTests (name, runnerArgs, cb) {
  let testGetterArgs = {}
  testGetterArgs.skipTests = skip
  testGetterArgs.skipVM = skipVM
  testGetterArgs.forkConfig = FORK_CONFIG
  testGetterArgs.file = argv.file
  testGetterArgs.test = argv.test
  testGetterArgs.dir = argv.dir
  testGetterArgs.excludeDir = argv.excludeDir
  testGetterArgs.testsPath = argv.testsPath

  testGetterArgs.customStateTest = argv.customStateTest

  runnerArgs.forkConfig = FORK_CONFIG
  runnerArgs.jsontrace = argv.jsontrace
  runnerArgs.debug = argv.debug // for BlockchainTests

  // for GeneralStateTests
  runnerArgs.data = argv.data
  runnerArgs.gasLimit = argv.gas
  runnerArgs.value = argv.value

  // runnerArgs.vmtrace = true; // for VMTests

  if (argv.customStateTest) {
    const stateTestRunner = require('./GeneralStateTestsRunner.js')
    let fileName = argv.customStateTest
    tape(name, t => {
      testing.getTestFromSource(fileName, (err, test) => {
        if (err) {
          return t.fail(err)
        }

        t.comment(`file: ${fileName} test: ${test.testName}`)
        stateTestRunner(runnerArgs, test, t, () => {
          t.end()
        })
      })
    })
  } else {
    tape(name, t => {
      const runner = require(`./${name}Runner.js`)
      testing.getTestsFromArgs(name, (fileName, testName, test) => {
        return new Promise((resolve, reject) => {
          if (name === 'VMTests') {
            // suppress some output of VMTests
            // t.comment(`file: ${fileName} test: ${testName}`)
            test.fileName = fileName
            test.testName = testName
            runner(runnerArgs, test, t, resolve)
          } else {
            t.comment(`file: ${fileName} test: ${testName}`)
            runner(runnerArgs, test, t, resolve)
          }
        }).catch(err => console.log(err))
      }, testGetterArgs).then(() => {
        t.end()
      })
    })
  }
}

function runAll () {
  require('./tester.js')
  require('./cacheTest.js')
  require('./genesishashes.js')
  async.series([
    // runTests.bind(this, 'VMTests', {}), // VM tests disabled since we don't support Frontier gas costs
    runTests.bind(this, 'GeneralStateTests', {}),
    runTests.bind(this, 'BlockchainTests', {})
  ])
}
<|endoftext|>