<commit_before>/*
 * TestEvents
 *
 */
var TestRun = (function($) {

	TestRun.index = 0;

	TestRun.IconSkin = {
		TESTSUITE : "testSuite",
		TESTSUITE_RUN : "testSuiteRun",
		TESTSUITE_PASSED : "testSuitePassed",
		TESTSUITE_FAILED : "testSuiteFailed",
		TEST : "test",
		TEST_RUN : "testRun",
		TEST_IGNORED : "testIgnored",
		TEST_PASSED : "testPassed",
		TEST_FAILED : "testFailed",
		TEST_ERROR : "testError"
	}

	function TestRun(elementId, runId) {
		console.log("Test run : " + runId);
		TestRun.index++;
		this.tree = null;
		this.runId = runId;
		this.treeEvents = [];
		this.elementId = elementId;
		this.testCount = 0;
		this.testStarted = 0;
		this.testIgnored = 0;
		this.testEnded = 0;
		this.errors = 0;
		this.failures = 0;
		this.testMessageId = "testMessage-" + TestRun.index;
		this.progressId = "progress-" + TestRun.index;
		this.treeId = "tree-" + TestRun.index;
		this.runsId = "runs-" + TestRun.index;
		this.errorsId = "errors-" + TestRun.index;
		this.failuresId = "failures-" + TestRun.index;
		this.panelStackTraceId = "panel-stackTrace-" + TestRun.index;
		this.stackTraceId = "stackTrace-" + TestRun.index;
		$('#' + this.elementId).html(
				"
" + "<fieldset><legend>" + runId
						+ "</legend>" + "<fieldset>" + "

"
						+ "Runs : " + "Errors: "
						+ "Failures :

</fieldset>"
						+ "

"
						+ "<fieldset class='stacktrace' id='"
						+ this.panelStackTraceId + "'>

</fieldset>"
						+ "</fieldset>
");
		this.createScrollLockButton();
	}
	TestRun.prototype = {

		createScrollLockButton : function() {
			this.scrollLockId = "scrollLock-" + TestRun.index;
			$('#' + this.elementId + " > div.testpanel > fieldset > fieldset")
					.after(
							'<input type="checkbox" class="scrollLock" id="'
									+ this.scrollLockId + '" />Scroll Lock');
			$("#" + this.scrollLockId).button({
				text : true,
				icons : {
					primary : "lock"
				}
			});
		},
		handleTestEvents : function(events) {
			if (this.tree == null) {
				this.treeWillBeRefreshed = true;
			} else {
				this.treeWillBeRefreshed = false;
			}
			for ( var i = 0; i < events.length; i++) {
				this.handleTestEvent(events[i]);
			}
			if (this.tree != null && this.treeWillBeRefreshed == true) {
				this.tree.refresh();
			}
		},
		handleTestEvent : function(event) {
			switch (event.type) {
			case "TESTC":
				this.handleRunStartEvent(event);
				break;
			case "TSTTREE":
				this.treeEvents.push(event);
				break;
			case "FAILED":
				this.handleTestFailedEvent(event);
				break;
			case "ERROR":
				this.handleTestErrorEvent(event);
				break;
			case "TESTS":
				this.handleTestStartEvent(event);
				break;
			case "TESTE":
				this.handleTestEndEvent(event);
				break;
			case "RUNTIME":
				this.handleRunStopEvent(event);
				break;
			default:
				break;
			}
			this.updateStats();
		},
		updateStats : function() {
			var runs = this.testStarted + "/" + this.testCount;
			if (this.testIgnored > 0) {
				runs += " (" + this.testIgnored + " ignored)";
			}
			$("#" + this.runsId).text(runs);
			$("#" + this.errorsId).text(this.errors);
			$("#" + this.failuresId).text(this.failures);
		},
		setMessage : function(message) {
			$("#" + this.testMessageId).text(message);
		},
		handleRunStartEvent : function(event) {
			this.testCount = event.testCount;
			$("#" + this.progressId).progressbar({
				value : 0,
				max : this.testCount
			});
			$("#" + this.progressId + " > div").css({
				'background' : 'green'
			});
		},
		handleRunStopEvent : function(event) {
			this.setMessage("Finished after "
					+ (event.elapsedTime / 1000).toFixed(2) + " seconds");
			if (this.errors == 0 && this.failures == 0) {
				$('#' + this.elementId + "> .testpanel > fieldset legend")
						.addClass("successSuite");
			}
		},
		handleTestStartEvent : function(event) {
			this.testStarted++;
			if (event.ignored) {
				this.testIgnored++;
			}
			if (this.tree == null) {
				this.createTreeView();
			}
			var node = this.getNodeByTestId(event.testId);
			this.updateNode(node, node.name, TestRun.IconSkin.TEST_RUN);
			this.updateParentNode(node);
			this.expandParent(node);
			if (!$('#' + this.scrollLockId).is(':checked')) {
				this.tree.selectNode(node);
			}
		},
		updateNode : function(node, name, iconSkin) {
			node.name = name;
			node.iconSkin = iconSkin;
			if (this.treeWillBeRefreshed == false) {
				this.tree.updateNode(node);
			}
		},
		expandParent : function(node) {
			var parent = node.getParentNode();
			while (parent != null && parent.open == false) {
				if (this.treeWillBeRefreshed == true) {
					parent.open = true;
				} else {
					this.tree.expandNode(parent, true, false, false, false);
				}
				parent = parent.getParentNode();
			}
		},
		collapseParentIfPassed : function(node) {
			var parent = node.getParentNode();
			while (parent != null) {
				if (parent.iconSkin == TestRun.IconSkin.TESTSUITE_PASSED) {
					if (this.treeWillBeRefreshed == true) {
						parent.open = false;
					} else {
						this.tree
								.expandNode(parent, false, false, false, false);
					}
				} else {
					break;
				}
				parent = parent.getParentNode();
			}
		},
		handleTestFailedEvent : function(event) {
			this.failures++;
			var node = this.getNodeByTestId(event.testId);
			this.updateNode(node, node.name, "testFailed");
			node.trace = event.trace;
			$("#" + this.progressId + " > div").css({
				'background' : 'darkred'
			});
			$('#' + this.elementId + "> .testpanel > fieldset legend")
					.addClass("errorSuite");
		},
		handleTestErrorEvent : function(event) {
			this.errors++;
			var node = this.getNodeByTestId(event.testId);
			this.updateNode(node, node.name, TestRun.IconSkin.TEST_ERROR);
			node.trace = event.trace;
			$("#" + this.progressId + " > div").css({
				'background' : 'darkred'
			});
			$('#' + this.elementId + "> .testpanel > fieldset legend")
					.addClass("errorSuite");
		},
		handleTestEndEvent : function(event) {
			this.testEnded++;
			var node = this.getNodeByTestId(event.testId);
			node.elapsedTime = event.elapsedTime;
			var newIconSkin = node.iconSkin;
			if (node.iconSkin == "testRun") {
				if (event.ignored) {
					newIconSkin = "testIgnored";
				} else {
					newIconSkin = "testPassed";
				}
			}
			var elapsedTimeInSeconds = numeral(event.elapsedTime / 1000)
					.format('0,0.000');
			var newName = node.name + " ("
					+ elapsedTimeInSeconds + " s)</span";
			this.updateNode(node, newName, newIconSkin);
			$("#" + this.progressId).progressbar("value", this.testEnded);
			this.updateParentNode(node);
			this.collapseParentIfPassed(node);
		},
		updateParentNode : function(childNode) {
			var parentNode = childNode.getParentNode();
			if (parentNode == null) {
				return;
			}
			var parentStyle = TestRun.IconSkin.TESTSUITE;
			var elapsedTime = 0;
			for ( var i = 0; i < parentNode.children.length; i++) {
				var childNode = parentNode.children[i];
				if (childNode.iconSkin == TestRun.IconSkin.TEST_RUN
						|| childNode.iconSkin == TestRun.IconSkin.TESTSUITE_RUN
						|| childNode.iconSkin == TestRun.IconSkin.TEST
						|| childNode.iconSkin == TestRun.IconSkin.TESTSUITE) {
					parentStyle = TestRun.IconSkin.TESTSUITE_RUN;
					break;
				}
				if (parentStyle == TestRun.IconSkin.TESTSUITE) {
					if (childNode.iconSkin == TestRun.IconSkin.TEST_IGNORED
							|| childNode.iconSkin == TestRun.IconSkin.TEST_PASSED
							|| childNode.iconSkin == TestRun.IconSkin.TESTSUITE_PASSED) {
						parentStyle = TestRun.IconSkin.TESTSUITE_PASSED;
					}
				}
				if (childNode.iconSkin == TestRun.IconSkin.TEST_FAILED
						|| childNode.iconSkin == TestRun.IconSkin.TEST_ERROR
						|| childNode.iconSkin == TestRun.IconSkin.TESTSUITE_FAILED) {
					parentStyle = TestRun.IconSkin.TESTSUITE_FAILED;
				}
				elapsedTime += childNode.elapsedTime;
			}
			var newName = parentNode.name;
			if ((parentStyle == TestRun.IconSkin.TESTSUITE_PASSED || parentStyle == TestRun.IconSkin.TESTSUITE_FAILED)
					&& (parentNode.elapsedTime == null)) {
				parentNode.elapsedTime = elapsedTime;
				var elapsedTimeInSeconds = numeral(
						parentNode.elapsedTime / 1000).format('0,0.000');
				newName = parentNode.name + " ("
						+ elapsedTimeInSeconds + " s)</span";
			}
			this.updateNode(parentNode, newName, parentStyle);
			this.updateParentNode(parentNode);
		},
		createTreeNodes : function(treeEvents) {
			var eventIndex = 0;
			var testRun = this;
			function createTreeNode() {
				var event = treeEvents[eventIndex];
				if (event.suite == false) {
					var testName = testRun.getShortTestName(event);
					var newNode = {
						id : event.testId,
						name : testName,
						iconSkin : TestRun.IconSkin.TEST,
						suite : false
					};
					eventIndex++;
					return newNode;
				} else {
					var newNode = {
						id : event.testId,
						name : event.testName,
						suite : true,
						iconSkin : TestRun.IconSkin.TESTSUITE,
						children : []
					};
					eventIndex++;
					for ( var i = 0; i < event.testCount; i++) {
						newNode.children.push(createTreeNode());
					}
					return newNode;
				}
			}
			return [ createTreeNode() ];
		},
		createTreeView : function() {
			var treeNodes = this.createTreeNodes(this.treeEvents);
			$.fn.zTree.init($("#" + this.treeId), {
				view : {
					nameIsHTML : true
				},
				callback : {
					onClick : $.proxy(function(event, treeId, treeNode,
							clickFlag) {
						var trace = treeNode.trace;
						if (trace == null) {
							trace = "";
						}
						$('#' + this.stackTraceId).html(trace);
					}, this)
				}
			}, treeNodes);
			this.tree = $.fn.zTree.getZTreeObj(this.treeId);
		},
		getNodeByTestId : function(testId) {
			var node = this.tree.getNodeByParam("id", testId, null);
			return node;
		},
		getShortTestName : function(event) {
			var index = event.testName.indexOf('(');
			if (index == -1) {
				return;
			}
			return event.testName.slice(0, index);
		}
	};

	return TestRun;
}(jQuery));

var TestRuns = (function($) {

	function TestRuns(elementId) {
		this.elementId = elementId;
		this.eventsCount = 0;
		this.testRuns = [];
		this.index = 0;
	}

	TestRuns.prototype = {
		start : function(event) {
			var $this = this;
			(function() {
				$this.handleNextTestEvents();
				// call the function again in 2 seconds
				setTimeout(arguments.callee, 2000);
			})();
		},
		handleNextTestEvents : function() {
			var $this = this;
			remoteAction.getTestEvents(this.eventsCount, function(t) {
				var testEvents = t.responseObject();
				$this.handleTestEvents(testEvents);
				$this.eventsCount += testEvents.length;
			});
		},
		handleTestEvents : function(buildEvents) {
			var runIdToRunEvents = {};
			for ( var i = 0; i < buildEvents.length; i++) {
				var buildEvent = buildEvents[i];
				if (runIdToRunEvents[buildEvent.runId] == null) {
					runIdToRunEvents[buildEvent.runId] = [];
				}
				runIdToRunEvents[buildEvent.runId]
						.push(buildEvent.runTestEvent);
			}
			for ( var runId in runIdToRunEvents) {
				var testRun = this.testRuns[runId];

				if (testRun == null) {
					this.index++;
					$('#' + this.elementId).append(
							"

");
					testRun = new TestRun("runId-" + this.index, runId);
					this.testRuns[runId] = testRun;
				}
				testRun.handleTestEvents(runIdToRunEvents[runId]);
			}
		}
	};

	return TestRuns;
}(jQuery));<commit_msg>some refactoring<commit_after>/*
 * TestEvents
 *
 */
var TestRun = (function($) {

	TestRun.index = 0;

	// possible icon skins for a node
	TestRun.IconSkin = {
		TESTSUITE : "testSuite",
		TESTSUITE_RUN : "testSuiteRun",
		TESTSUITE_PASSED : "testSuitePassed",
		TESTSUITE_FAILED : "testSuiteFailed",
		TEST : "test",
		TEST_RUN : "testRun",
		TEST_IGNORED : "testIgnored",
		TEST_PASSED : "testPassed",
		TEST_FAILED : "testFailed",
		TEST_ERROR : "testError"
	}

	// possible status for a test/test suite
	TestRun.TestStatus = {
		UNKNOWN : "unknown",
		IGNORED : "ignored",
		RUNNING : "running",
		PASSED : "passed",
		FAILED : "failed",
		ERROR : "error"
	}

	function TestRun(elementId, runId) {
		console.log("Test run : " + runId);
		TestRun.index++;
		this.tree = null;
		this.runId = runId;
		this.treeEvents = [];
		this.elementId = elementId;
		this.testCount = 0;
		this.testStarted = 0;
		this.testIgnored = 0;
		this.testEnded = 0;
		this.errors = 0;
		this.failures = 0;
		this.testMessageId = "testMessage-" + TestRun.index;
		this.progressId = "progress-" + TestRun.index;
		this.treeId = "tree-" + TestRun.index;
		this.runsId = "runs-" + TestRun.index;
		this.errorsId = "errors-" + TestRun.index;
		this.failuresId = "failures-" + TestRun.index;
		this.panelStackTraceId = "panel-stackTrace-" + TestRun.index;
		this.stackTraceId = "stackTrace-" + TestRun.index;
		$('#' + this.elementId).html(
				"
" + "<fieldset><legend>" + runId
						+ "</legend>" + "<fieldset>" + "

"
						+ "Runs : " + "Errors: "
						+ "Failures :

</fieldset>"
						+ "

"
						+ "<fieldset class='stacktrace' id='"
						+ this.panelStackTraceId + "'>

</fieldset>"
						+ "</fieldset>
");
		this.createScrollLockButton();
	}
	TestRun.prototype = {

		createScrollLockButton : function() {
			this.scrollLockId = "scrollLock-" + TestRun.index;
			$('#' + this.elementId + " > div.testpanel > fieldset > fieldset")
					.after(
							'<input type="checkbox" class="scrollLock" id="'
									+ this.scrollLockId + '" />Scroll Lock');
			$("#" + this.scrollLockId).button({
				text : true,
				icons : {
					primary : "lock"
				}
			});
		},
		handleTestEvents : function(events) {
			if (this.tree == null) {
				this.treeWillBeRefreshed = true;
			} else {
				this.treeWillBeRefreshed = false;
			}
			for ( var i = 0; i < events.length; i++) {
				this.handleTestEvent(events[i]);
			}
			if (this.tree != null && this.treeWillBeRefreshed == true) {
				this.tree.refresh();
			}
		},
		handleTestEvent : function(event) {
			switch (event.type) {
			case "TESTC":
				this.handleRunStartEvent(event);
				break;
			case "TSTTREE":
				this.treeEvents.push(event);
				break;
			case "FAILED":
				this.handleTestFailedEvent(event);
				break;
			case "ERROR":
				this.handleTestErrorEvent(event);
				break;
			case "TESTS":
				this.handleTestStartEvent(event);
				break;
			case "TESTE":
				this.handleTestEndEvent(event);
				break;
			case "RUNTIME":
				this.handleRunStopEvent(event);
				break;
			default:
				break;
			}
			this.updateStats();
		},
		updateStats : function() {
			var runs = this.testStarted + "/" + this.testCount;
			if (this.testIgnored > 0) {
				runs += " (" + this.testIgnored + " ignored)";
			}
			$("#" + this.runsId).text(runs);
			$("#" + this.errorsId).text(this.errors);
			$("#" + this.failuresId).text(this.failures);
		},
		setMessage : function(message) {
			$("#" + this.testMessageId).text(message);
		},
		handleRunStartEvent : function(event) {
			this.testCount = event.testCount;
			$("#" + this.progressId).progressbar({
				value : 0,
				max : this.testCount
			});
			$("#" + this.progressId + " > div").css({
				'background' : 'green'
			});
		},
		handleRunStopEvent : function(event) {
			this.setMessage("Finished after "
					+ (event.elapsedTime / 1000).toFixed(2) + " seconds");
			if (this.errors == 0 && this.failures == 0) {
				$('#' + this.elementId + "> .testpanel > fieldset legend")
						.addClass("successSuite");
			}
		},
		handleTestStartEvent : function(event) {
			this.testStarted++;
			if (event.ignored) {
				this.testIgnored++;
			}
			if (this.tree == null) {
				this.createTreeView();
			}
			var node = this.getNodeByTestId(event.testId);
			node.testStatus = TestRun.TestStatus.RUNNING;
			this.updateNode(node);
			this.updateParentNode(node);
			this.expandParent(node);
			if (!$('#' + this.scrollLockId).is(':checked')) {
				this.tree.selectNode(node);
			}
		},
		updateNode : function(node) {
			if (node.elapsedTime != null) {
				var elapsedTimeInSeconds = numeral(node.elapsedTime / 1000)
						.format('0,0.000');
				node.name = node.testName + " ("
						+ elapsedTimeInSeconds + " s)</span";
			} else {
				node.name = node.testName;
			}
			if (node.suite) {
				switch (node.testStatus) {
				case TestRun.TestStatus.UNKNOWN:
					node.iconSkin = TestRun.IconSkin.TESTSUITE;
					break;
				case TestRun.TestStatus.RUNNING:
					node.iconSkin = TestRun.IconSkin.TESTSUITE_RUN;
					break;
				case TestRun.TestStatus.PASSED:
					node.iconSkin = TestRun.IconSkin.TESTSUITE_PASSED;
					break;
				case TestRun.TestStatus.FAILED:
					node.iconSkin = TestRun.IconSkin.TESTSUITE_FAILED;
					break;
				}
			} else {
				switch (node.testStatus) {
				case TestRun.TestStatus.UNKNOWN:
					node.iconSkin = TestRun.IconSkin.TEST;
					break;
				case TestRun.TestStatus.IGNORED:
					node.iconSkin = TestRun.IconSkin.TEST_IGNORED;
					break;
				case TestRun.TestStatus.RUNNING:
					node.iconSkin = TestRun.IconSkin.TEST_RUN;
					break;
				case TestRun.TestStatus.PASSED:
					node.iconSkin = TestRun.IconSkin.TEST_PASSED;
					break;
				case TestRun.TestStatus.FAILED:
					node.iconSkin = TestRun.IconSkin.TEST_FAILED;
					break;
				case TestRun.TestStatus.ERROR:
					node.iconSkin = TestRun.IconSkin.TEST_ERROR;
					break;
				}
			}
			if (this.treeWillBeRefreshed == false) {
				this.tree.updateNode(node);
			}
		},
		expandParent : function(node) {
			var parent = node.getParentNode();
			while (parent != null && parent.open == false) {
				if (this.treeWillBeRefreshed == true) {
					parent.open = true;
				} else {
					this.tree.expandNode(parent, true, false, false, false);
				}
				parent = parent.getParentNode();
			}
		},
		collapseParentIfPassed : function(node) {
			var parent = node.getParentNode();
			while (parent != null) {
				if (parent.testStatus == TestRun.TestStatus.PASSED) {
					if (this.treeWillBeRefreshed == true) {
						parent.open = false;
					} else {
						this.tree
								.expandNode(parent, false, false, false, false);
					}
				} else {
					break;
				}
				parent = parent.getParentNode();
			}
		},
		handleTestFailedEvent : function(event) {
			this.failures++;
			var node = this.getNodeByTestId(event.testId);
			node.testStatus = TestRun.TestStatus.FAILED;
			this.updateNode(node);
			node.trace = event.trace;
			$("#" + this.progressId + " > div").css({
				'background' : 'darkred'
			});
			$('#' + this.elementId + "> .testpanel > fieldset legend")
					.addClass("errorSuite");
		},
		handleTestErrorEvent : function(event) {
			this.errors++;
			var node = this.getNodeByTestId(event.testId);
			node.testStatus = TestRun.TestStatus.ERROR;
			this.updateNode(node);
			node.trace = event.trace;
			$("#" + this.progressId + " > div").css({
				'background' : 'darkred'
			});
			$('#' + this.elementId + "> .testpanel > fieldset legend")
					.addClass("errorSuite");
		},
		handleTestEndEvent : function(event) {
			this.testEnded++;
			var node = this.getNodeByTestId(event.testId);
			node.elapsedTime = event.elapsedTime;
			if (node.testStatus == TestRun.TestStatus.RUNNING) {
				if (event.ignored) {
					node.testStatus = TestRun.TestStatus.IGNORED;
				} else {
					node.testStatus = TestRun.TestStatus.PASSED;
				}
			}
			this.updateNode(node);
			$("#" + this.progressId).progressbar("value", this.testEnded);
			this.updateParentNode(node);
			this.collapseParentIfPassed(node);
		},
		updateParentNode : function(childNode) {
			var parentNode = childNode.getParentNode();
			if (parentNode == null) {
				return;
			}
			var parentTestStatus = TestRun.TestStatus.UNKNOWN;
			var elapsedTime = 0;
			for ( var i = 0; i < parentNode.children.length; i++) {
				var childNode = parentNode.children[i];
				if (childNode.testStatus == TestRun.TestStatus.RUNNING
						|| childNode.testStatus == TestRun.TestStatus.UNKNOWN) {
					parentTestStatus = TestRun.TestStatus.RUNNING;
					break;
				}
				if (parentTestStatus == TestRun.TestStatus.UNKNOWN) {
					if (childNode.testStatus == TestRun.TestStatus.IGNORED
							|| childNode.testStatus == TestRun.TestStatus.PASSED) {
						parentTestStatus = TestRun.TestStatus.PASSED;
					}
				}
				if (childNode.testStatus == TestRun.TestStatus.FAILED
						|| childNode.testStatus == TestRun.TestStatus.FAILED.ERROR) {
					parentTestStatus = TestRun.TestStatus.FAILED;
				}
				elapsedTime += childNode.elapsedTime;
			}
			parentNode.testStatus = parentTestStatus;
			if ((parentTestStatus == TestRun.TestStatus.PASSED || parentTestStatus == TestRun.TestStatus.FAILED)
					&& (parentNode.elapsedTime == null)) {
				parentNode.elapsedTime = elapsedTime;
			}
			this.updateNode(parentNode);
			this.updateParentNode(parentNode);
		},
		createTreeNodes : function(treeEvents) {
			var eventIndex = 0;
			var testRun = this;
			function createTreeNode() {
				var event = treeEvents[eventIndex];
				if (event.suite == false) {
					var testName = testRun.getShortTestName(event);
					var newNode = {
						name : testName,
						iconSkin : TestRun.IconSkin.TEST,
						// our properties :
						id : event.testId,
						suite : false,
						testName : testName,
						testStatus : TestRun.TestStatus.UNKNOWN
					};
					eventIndex++;
					return newNode;
				} else {
					var newNode = {
						name : event.testName,
						iconSkin : TestRun.IconSkin.TESTSUITE,
						children : [],
						// our properties :
						id : event.testId,
						suite : true,
						testName : event.testName,
						testStatus : TestRun.TestStatus.UNKNOWN
					};
					eventIndex++;
					for ( var i = 0; i < event.testCount; i++) {
						newNode.children.push(createTreeNode());
					}
					return newNode;
				}
			}
			return [ createTreeNode() ];
		},
		createTreeView : function() {
			var treeNodes = this.createTreeNodes(this.treeEvents);
			$.fn.zTree.init($("#" + this.treeId), {
				view : {
					nameIsHTML : true
				},
				callback : {
					onClick : $.proxy(function(event, treeId, treeNode,
							clickFlag) {
						var trace = treeNode.trace;
						if (trace == null) {
							trace = "";
						}
						$('#' + this.stackTraceId).html(trace);
					}, this)
				}
			}, treeNodes);
			this.tree = $.fn.zTree.getZTreeObj(this.treeId);
		},
		getNodeByTestId : function(testId) {
			var node = this.tree.getNodeByParam("id", testId, null);
			return node;
		},
		getShortTestName : function(event) {
			var index = event.testName.indexOf('(');
			if (index == -1) {
				return;
			}
			return event.testName.slice(0, index);
		}
	};

	return TestRun;
}(jQuery));

var TestRuns = (function($) {

	function TestRuns(elementId) {
		this.elementId = elementId;
		this.eventsCount = 0;
		this.testRuns = [];
		this.index = 0;
	}

	TestRuns.prototype = {
		start : function(event) {
			var $this = this;
			(function() {
				$this.handleNextTestEvents();
				// call the function again in 2 seconds
				setTimeout(arguments.callee, 2000);
			})();
		},
		handleNextTestEvents : function() {
			var $this = this;
			remoteAction.getTestEvents(this.eventsCount, function(t) {
				var testEvents = t.responseObject();
				$this.handleTestEvents(testEvents);
				$this.eventsCount += testEvents.length;
			});
		},
		handleTestEvents : function(buildEvents) {
			var runIdToRunEvents = {};
			for ( var i = 0; i < buildEvents.length; i++) {
				var buildEvent = buildEvents[i];
				if (runIdToRunEvents[buildEvent.runId] == null) {
					runIdToRunEvents[buildEvent.runId] = [];
				}
				runIdToRunEvents[buildEvent.runId]
						.push(buildEvent.runTestEvent);
			}
			for ( var runId in runIdToRunEvents) {
				var testRun = this.testRuns[runId];

				if (testRun == null) {
					this.index++;
					$('#' + this.elementId).append(
							"

");
					testRun = new TestRun("runId-" + this.index, runId);
					this.testRuns[runId] = testRun;
				}
				testRun.handleTestEvents(runIdToRunEvents[runId]);
			}
		}
	};

	return TestRuns;
}(jQuery));<|endoftext|>


<commit_before>var path = require('path');
var webpack = require('webpack');
var fs = require('fs');
var extend = require('util')._extend;
var camelcase = require('camelcase');
var autoprefixer = require('autoprefixer');
var Webpack2Polyfill = require('webpack2-polyfill-plugin');

const isDevelopment =
	!process.env.NODE_ENV || process.env.NODE_ENV == 'development';

var CompressionPlugin = require('compression-webpack-plugin');

function getFolders(dir) {
	return fs.readdirSync(dir).filter(function(file) {
		return fs.statSync(path.join(dir, file)).isDirectory();
	});
}

module.exports = options => {
	const webpackMultipleConfigs = [];

	options.entries.map(entry => {
		if (entry.forEachFolderIn) {
			var folders = getFolders(entry.forEachFolderIn);

			folders.map(folder => {
				var toPush = {};

				toPush.context = path.join(
					process.cwd(),
					entry.forEachFolderIn,
					folder
				);

				toPush.entry = entry.entry;

				toPush.output = Object.assign({}, entry.output, {
					path: path.join(
						process.cwd(),
						entry.forEachFolderIn,
						folder,
						entry.output.path
					),
					filename: '[name].js',
					jsonpFunction: camelcase(
						(entry.jsonpPrefix || 'webpack-jsonp-') + folder
					),
				});

				if (entry.licenseHeader) {
					// toPush['ctTemporaryHeader'] = entry.licenseHeader;
				}

				if (
					fs.existsSync(
						path.join(entry.forEachFolderIn, folder, entry.entry)
					)
				) {
					webpackMultipleConfigs.push(toPush);
				}
			});
		} else {
			var toPush = {};

			toPush['entry'] = entry.entry;
			toPush['output'] = entry.output;

			if (toPush['output']['path']) {
				if (!path.isAbsolute(toPush['output']['path'])) {
					toPush['output']['path'] = path.join(
						process.cwd(),
						toPush['output']['path']
					);
				}
			}

			toPush.context = process.cwd();

			if (entry.licenseHeader) {
				// toPush['ctTemporaryHeader'] = entry.licenseHeader;
			}

			webpackMultipleConfigs.push(toPush);
		}
	});

	var config = webpackMultipleConfigs.map(singleConfig => {
		// console.log('DEBUG', singleConfig.entry);

		let result = Object.assign(
			{},
			getCommonConfig(singleConfig),
			singleConfig
		);

		if (result.ctTemporaryHeader) {
			/*
			result.plugins = result.plugins.concat([
				new webpack.BannerPlugin(result.ctTemporaryHeader, {
					raw: true
				})
			]);
            */
		}

		return result;
	});

	return config;

	/**
	 * Crazy hack for https://github.com/webpack/css-loader/issues/337
	 */
	function getCommonConfig(singleConfig) {
		const commonConfig = {
			devtool: isDevelopment ? 'source-map' : false,

			module: Object.assign(
				{
					rules: [
						{
							test: /\.(js|jsx)$/,
							loader: require.resolve('babel-loader'),
							options: {
								presets: [
									[
										'env',
										{
											modules: false,
											targets: {
												browsers: 'defaults',
											},
										},
									],
								],
								plugins: [
									require.resolve(
										'babel-plugin-transform-object-rest-spread'
									),
									require.resolve(
										'babel-plugin-transform-flow-strip-types'
									),
									require.resolve(
										'babel-plugin-syntax-dynamic-import'
									),
									require.resolve(
										'babel-plugin-transform-vue-jsx'
									),
								].concat(options.babelAdditionalPlugins),
							},

							// TODO: configure load paths here. May slow down builds!!!
							exclude: /(node_modules|bower_components)/,
						},

						{
							test: /\.scss$/,
							loaders: [
								'style-loader',
								'css-loader?sourceMap',
								'postcss-loader',
								'sass-loader?sourceMap&sourceMapContents',
							],
						},

						{
							test: /\.css$/,
							loaders: [
								'style-loader',
								'css-loader?sourceMap',
								'postcss-loader',
							],
						},

						{
							test: /\.png$/,
							loader: 'file-loader',
						},
						{
							test: /\.gif/,
							loader: 'file-loader',
						},
						{
							test: /\.jpg$/,
							loader: 'file-loader',
						},
						{
							test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
							loader: 'file-loader',
						},
					].concat(options.webpackAdditionalLoaders),
				},
				options.webpackAdditionalModules
			),

			resolve: {
				extensions: ['.js', '.jsx', '.css'],

				modules: ['node_modules', 'bower_components'].concat(
					options.webpackIncludePaths
				),

				alias: options.webpackResolveAliases,
			},

			plugins: [
				new webpack.ProvidePlugin({
					$: 'jquery',
				}),

				new Webpack2Polyfill({
					Promise: true,
					'Function.prototype.bind': false,
					'Object.keys': false,
					'Object.defineProperty': false,
				}),

				new webpack.NoEmitOnErrorsPlugin(),

				/*
				new webpack.ResolverPlugin([
					new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
				], ["normal", "loader"]),
			*/

				new webpack.DefinePlugin({
					PRODUCTION: !isDevelopment,
				}),

				new webpack.EnvironmentPlugin(['NODE_ENV']),

				new webpack.LoaderOptionsPlugin({
					options: {
						context: singleConfig.context,
						output: singleConfig.output,
						postcss() {
							return [
								require('postcss-easing-gradients'),
								autoprefixer({ browsers: ['last 2 versions'] }),
							];
						},
					},
				}),
			]
				.concat(
					isDevelopment
						? []
						: [
								new webpack.optimize.UglifyJsPlugin({
									compress: {
										warnings: false,
									},
								}),
								new CompressionPlugin(),
							]
				)
				.concat(
					options.webpackOutputStats
						? [
								new StatsPlugin('stats.json', {
									chunkModules: true,
								}),
							]
						: []
				)
				.concat(options.webpackPlugins),

			externals: Object.assign(
				{
					jquery: 'window.jQuery',
					_: 'window._',
					underscore: 'window._',
				},
				options.webpackExternals
			),
		};

		return commonConfig;
	}
};
<commit_msg>get rid of provide plugin<commit_after>var path = require('path');
var webpack = require('webpack');
var fs = require('fs');
var extend = require('util')._extend;
var camelcase = require('camelcase');
var autoprefixer = require('autoprefixer');
var Webpack2Polyfill = require('webpack2-polyfill-plugin');

const isDevelopment =
	!process.env.NODE_ENV || process.env.NODE_ENV == 'development';

var CompressionPlugin = require('compression-webpack-plugin');

function getFolders(dir) {
	return fs.readdirSync(dir).filter(function(file) {
		return fs.statSync(path.join(dir, file)).isDirectory();
	});
}

module.exports = options => {
	const webpackMultipleConfigs = [];

	options.entries.map(entry => {
		if (entry.forEachFolderIn) {
			var folders = getFolders(entry.forEachFolderIn);

			folders.map(folder => {
				var toPush = {};

				toPush.context = path.join(
					process.cwd(),
					entry.forEachFolderIn,
					folder
				);

				toPush.entry = entry.entry;

				toPush.output = Object.assign({}, entry.output, {
					path: path.join(
						process.cwd(),
						entry.forEachFolderIn,
						folder,
						entry.output.path
					),
					filename: '[name].js',
					jsonpFunction: camelcase(
						(entry.jsonpPrefix || 'webpack-jsonp-') + folder
					),
				});

				if (entry.licenseHeader) {
					// toPush['ctTemporaryHeader'] = entry.licenseHeader;
				}

				if (
					fs.existsSync(
						path.join(entry.forEachFolderIn, folder, entry.entry)
					)
				) {
					webpackMultipleConfigs.push(toPush);
				}
			});
		} else {
			var toPush = {};

			toPush['entry'] = entry.entry;
			toPush['output'] = entry.output;

			if (toPush['output']['path']) {
				if (!path.isAbsolute(toPush['output']['path'])) {
					toPush['output']['path'] = path.join(
						process.cwd(),
						toPush['output']['path']
					);
				}
			}

			toPush.context = process.cwd();

			if (entry.licenseHeader) {
				// toPush['ctTemporaryHeader'] = entry.licenseHeader;
			}

			webpackMultipleConfigs.push(toPush);
		}
	});

	var config = webpackMultipleConfigs.map(singleConfig => {
		// console.log('DEBUG', singleConfig.entry);

		let result = Object.assign(
			{},
			getCommonConfig(singleConfig),
			singleConfig
		);

		if (result.ctTemporaryHeader) {
			/*
			result.plugins = result.plugins.concat([
				new webpack.BannerPlugin(result.ctTemporaryHeader, {
					raw: true
				})
			]);
            */
		}

		return result;
	});

	return config;

	/**
	 * Crazy hack for https://github.com/webpack/css-loader/issues/337
	 */
	function getCommonConfig(singleConfig) {
		const commonConfig = {
			devtool: isDevelopment ? 'source-map' : false,

			module: Object.assign(
				{
					rules: [
						{
							test: /\.(js|jsx)$/,
							loader: require.resolve('babel-loader'),
							options: {
								presets: [
									[
										'env',
										{
											modules: false,
											targets: {
												browsers: 'defaults',
											},
										},
									],
								],
								plugins: [
									require.resolve(
										'babel-plugin-transform-object-rest-spread'
									),
									require.resolve(
										'babel-plugin-transform-flow-strip-types'
									),
									require.resolve(
										'babel-plugin-syntax-dynamic-import'
									),
									require.resolve(
										'babel-plugin-transform-vue-jsx'
									),
								].concat(options.babelAdditionalPlugins),
							},

							// TODO: configure load paths here. May slow down builds!!!
							exclude: /(node_modules|bower_components)/,
						},

						{
							test: /\.scss$/,
							loaders: [
								'style-loader',
								'css-loader?sourceMap',
								'postcss-loader',
								'sass-loader?sourceMap&sourceMapContents',
							],
						},

						{
							test: /\.css$/,
							loaders: [
								'style-loader',
								'css-loader?sourceMap',
								'postcss-loader',
							],
						},

						{
							test: /\.png$/,
							loader: 'file-loader',
						},
						{
							test: /\.gif/,
							loader: 'file-loader',
						},
						{
							test: /\.jpg$/,
							loader: 'file-loader',
						},
						{
							test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
							loader: 'file-loader',
						},
					].concat(options.webpackAdditionalLoaders),
				},
				options.webpackAdditionalModules
			),

			resolve: {
				extensions: ['.js', '.jsx', '.css'],

				modules: ['node_modules', 'bower_components'].concat(
					options.webpackIncludePaths
				),

				alias: options.webpackResolveAliases,
			},

			plugins: [
				new Webpack2Polyfill({
					Promise: true,
					'Function.prototype.bind': false,
					'Object.keys': false,
					'Object.defineProperty': false,
				}),

				new webpack.NoEmitOnErrorsPlugin(),

				/*
				new webpack.ResolverPlugin([
					new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
				], ["normal", "loader"]),
			*/

				new webpack.DefinePlugin({
					PRODUCTION: !isDevelopment,
				}),

				new webpack.EnvironmentPlugin(['NODE_ENV']),

				new webpack.LoaderOptionsPlugin({
					options: {
						context: singleConfig.context,
						output: singleConfig.output,
						postcss() {
							return [
								require('postcss-easing-gradients'),
								autoprefixer({ browsers: ['last 2 versions'] }),
							];
						},
					},
				}),
			]
				.concat(
					isDevelopment
						? []
						: [
								new webpack.optimize.UglifyJsPlugin({
									compress: {
										warnings: false,
									},
								}),
								new CompressionPlugin(),
							]
				)
				.concat(
					options.webpackOutputStats
						? [
								new StatsPlugin('stats.json', {
									chunkModules: true,
								}),
							]
						: []
				)
				.concat(options.webpackPlugins),

			externals: Object.assign(
				{
					jquery: 'window.jQuery',
					_: 'window._',
					underscore: 'window._',
				},
				options.webpackExternals
			),
		};

		return commonConfig;
	}
};
<|endoftext|>


<commit_before>var testHelpers = require('./testHelpers.js');
var co = require('co');
var should = require('should');
var request = testHelpers.request;

describe('API for web pages', function(){
  describe('streams sounds', function(){
    it('return existing files', function(done){
      request
      .get('/api/sound/' + testHelpers.testSoundName)
      .expect(200, done);
    });

    it('fails for non existing files', function(done){
      request
      .get('/api/sound/_____')
      .expect(404, done);
    });
  });

  describe('counts the number of plays for a sound', function () {
    beforeEach(function (done) {
      testHelpers.removeAllDocs(done);
    });

    it('sets the number of plays to 1 for a sound that noone has played', function (done) {
      co(function *() {
        testHelpers.seedDb();

        request
          .post("/api/played/" + testHelpers.testSoundName)
          .expect(200)
          .expect({ noOfPlays : 1 })
          .end(function (){
            co(function *() {
              var sound = yield testHelpers.soundCollection.findOne({name :  testHelpers.testSoundName});
              sound.noOfPlays.should.equal(1);
            })(done);
          });
      })();
    });
    it('increments the number of plays with 1 for sounds that is played', function (done) {
    	co(function *() {
        var testDataAlreadyPlayed = 12;
	    	yield testHelpers.soundCollection.insert({ name: 'booooring', noOfPlays : testDataAlreadyPlayed })

        request
          .post("/api/played/" + testHelpers.testSoundName)
          .expect(200)
          .expect({ noOfPlays : testDataAlreadyPlayed+1 })
          .end(function (){
            co(function *() {
              var sound = yield testHelpers.soundCollection.findOne({name : testHelpers.testSoundName});
              sound.noOfPlays.should.equal(13);
            })(done);
          });
      })();
    });
  });
});<commit_msg>Clean up in testing better<commit_after>var testHelpers = require('./testHelpers.js');
var co = require('co');
var should = require('should');
var request = testHelpers.request;

describe('API for web pages', function(){
  describe('streams sounds', function(){
    it('return existing files', function(done){
      request
      .get('/api/sound/' + testHelpers.testSoundName)
      .expect(200, done);
    });

    it('fails for non existing files', function(done){
      request
      .get('/api/sound/_____')
      .expect(404, done);
    });
  });

  describe('counts the number of plays for a sound', function () {
    beforeEach(function (done) {
      testHelpers.removeAllDocs(done);
    });

    afterEach(function (done) {
      testHelpers.removeAllDocs(done);
    });

    it('sets the number of plays to 1 for a sound that noone has played', function (done) {
      co(function *() {
        testHelpers.seedDb();

        request
          .post("/api/played/" + testHelpers.testSoundName)
          .expect(200)
          .expect({ noOfPlays : 1 })
          .end(function (){
            co(function *() {
              var sound = yield testHelpers.soundCollection.findOne({name :  testHelpers.testSoundName});
              sound.noOfPlays.should.equal(1);
            })(done);
          });
      })();
    });
    it('increments the number of plays with 1 for sounds that is played', function (done) {
    	co(function *() {
        var testDataAlreadyPlayed = 12;
	    	yield testHelpers.soundCollection.insert({ name: 'booooring', noOfPlays : testDataAlreadyPlayed })

        request
          .post("/api/played/" + testHelpers.testSoundName)
          .expect(200)
          .expect({ noOfPlays : testDataAlreadyPlayed+1 })
          .end(function (){
            co(function *() {
              var sound = yield testHelpers.soundCollection.findOne({name : testHelpers.testSoundName});
              sound.noOfPlays.should.equal(13);
            })(done);
          });
      })();
    });
  });
});<|endoftext|>


<commit_before>define(['q'], function(Q) {

    'use strict';

	return ['$scope', '$location', 'Rest', 'AbsenceEdit', function($scope, $location, Rest, AbsenceEdit) {

        AbsenceEdit.initScope($scope);

        // resources
        var calendars = Rest.admin.calendars.getResource();
        var calendarEvents = Rest.admin.calendarevents.getResource();
        var accountRights = Rest.admin.accountrights.getResource();
        var users = Rest.admin.users.getResource();
        //var accountCollection = Rest.admin.collections.getResource();
        // TODO fix accountCollection, not the same as account/request

        $scope.request = Rest.admin.requests.getFromUrl().loadRouteId();

        var userId, userPromise;

        function loadRequestAndUserPromise()
        {
            var deferred = Q.defer();

            if ($scope.request.$promise) {
                $scope.request.$promise.then(function(request) {
                    // edit this request

                    $scope.editRequest = true;
                    AbsenceEdit.onceUserLoaded($scope, request.user.id, calendarEvents);

                    userId = request.user.id;
                    userPromise = users.get({ id: userId }).$promise;

                    deferred.resolve(userPromise);
                });

                return deferred.promise;
            }

            // create a new request
            $scope.newRequest = true;
            userId = $location.search().user;

            if (!userId) {
                throw new Error('the user parameter is mandatory to create a new request');
            }

            userPromise = users.get({ id: userId }).$promise;
            userPromise.then(function(user) {

                $scope.user = user;

                AbsenceEdit.onceUserLoaded($scope, user, calendarEvents);

                $scope.request.user = {
                    id: user._id,
                    name: user.lastname+' '+user.firstname
                };
            });

            deferred.resolve(userPromise);

            return deferred.promise;

        }

        /**
         * Period picker callbacks
         */
        $scope.loadWorkingTimes = AbsenceEdit.getLoadWorkingTimes(loadRequestAndUserPromise(), calendarEvents);
        $scope.loadEvents = AbsenceEdit.getLoadEvents(calendars, calendarEvents);
        $scope.loadScholarHolidays = AbsenceEdit.getLoadScholarHolidays(calendars, calendarEvents);

        /**
         * Go back to requests list, admin view
         */
        $scope.back = function() {
            $location.path('/admin/requests');
        };

        /**
         * Go from the period selection to the right assignments step
         */
        $scope.next = function() {

            /**
             * Load collection
             * The collection available on the selected period

            $scope.collection = accountCollection.get({
                user: $scope.user.id,
                dtstart: $scope.selection.begin,
                dtend: $scope.selection.end
            });
            */
            var serviceAction = AbsenceEdit.getNextButtonJob($scope, accountRights);

            serviceAction();
        };

        $scope.saveAbsence = function() {
            console.log('save request');
        };

	}];
});

<commit_msg>Collection<commit_after>define(['q'], function(Q) {

    'use strict';

	return ['$scope', '$location', 'Rest', 'AbsenceEdit', function($scope, $location, Rest, AbsenceEdit) {

        AbsenceEdit.initScope($scope);

        // resources
        var calendars = Rest.admin.calendars.getResource();
        var calendarEvents = Rest.admin.calendarevents.getResource();
        var accountRights = Rest.admin.accountrights.getResource();
        var users = Rest.admin.users.getResource();
        var collections = Rest.admin.collections.getResource();
        // TODO fix accountCollection, not the same as account/request

        $scope.request = Rest.admin.requests.getFromUrl().loadRouteId();

        var userId, userPromise;

        function loadRequestAndUserPromise()
        {
            var deferred = Q.defer();

            if ($scope.request.$promise) {
                $scope.request.$promise.then(function(request) {
                    // edit this request

                    $scope.editRequest = true;
                    AbsenceEdit.onceUserLoaded($scope, request.user.id, calendarEvents);

                    userId = request.user.id;
                    userPromise = users.get({ id: userId }).$promise;

                    deferred.resolve(userPromise);
                });

                return deferred.promise;
            }

            // create a new request
            $scope.newRequest = true;
            userId = $location.search().user;

            if (!userId) {
                throw new Error('the user parameter is mandatory to create a new request');
            }

            userPromise = users.get({ id: userId }).$promise;
            userPromise.then(function(user) {

                $scope.user = user;

                AbsenceEdit.onceUserLoaded($scope, user, calendarEvents);

                $scope.request.user = {
                    id: user._id,
                    name: user.lastname+' '+user.firstname
                };
            });

            deferred.resolve(userPromise);

            return deferred.promise;

        }

        /**
         * Period picker callbacks
         */
        $scope.loadWorkingTimes = AbsenceEdit.getLoadWorkingTimes(loadRequestAndUserPromise(), calendarEvents);
        $scope.loadEvents = AbsenceEdit.getLoadEvents(calendars, calendarEvents);
        $scope.loadScholarHolidays = AbsenceEdit.getLoadScholarHolidays(calendars, calendarEvents);

        /**
         * Go back to requests list, admin view
         */
        $scope.back = function() {
            $location.path('/admin/requests');
        };

        /**
         * Go from the period selection to the right assignments step
         */
        $scope.next = function() {

            /**
             * Load collection
             * The collection available on the selected period
             */

            collections.get({
                user: $scope.user._id,
                dtstart: $scope.selection.begin,
                dtend: $scope.selection.end
            }).$promise.then(function(collectionList) {
                if (0 === collectionList.length) {
                    throw new Error('No active collection for this user');
                }

                console.log(collectionList);

                if (1 !== collectionList.length) {
                    throw new Error('More than one collection found for the user');
                }

                $scope.collection = collectionList[0];
            });

            var serviceAction = AbsenceEdit.getNextButtonJob($scope, accountRights);

            serviceAction();
        };

        $scope.saveAbsence = function() {
            console.log('save request');
        };

	}];
});

<|endoftext|>


<commit_before>/* eslint-disable no-await-in-loop */
import {
  render,
  renderString,
  stop as stopTwigRenderer,
} from '@bolt/twig-renderer';
import { fixture as html } from '@open-wc/testing-helpers';
import { join } from 'path';

async function renderTwig(template, data) {
  return await render(template, data, true);
}

async function renderTwigString(template, data) {
  return await renderString(template, data, true);
}

const imageVrtConfig = {
  failureThreshold: '0.02',
  failureThresholdType: 'percent',
};

const timeout = 120000;

const viewportSizes = [
  {
    size: 'xlarge',
    width: 1920,
    height: 1080,
  },
  {
    size: 'large',
    width: 1024,
    height: 768,
  },
  {
    size: 'medium',
    width: 896,
    height: 414,
  },
  {
    size: 'small',
    width: 320,
    height: 568,
  },
];

describe('<bolt-navbar> Component', () => {
  let page;

  afterAll(async () => {
    await stopTwigRenderer();
  }, timeout);

  beforeEach(async () => {
    page = await global.__BROWSER__.newPage();
    await page.goto('http://127.0.0.1:4444/', {
      timeout: 0,
      waitLoad: true,
      waitNetworkIdle: true, // defaults to false
    });
  }, timeout);

  test(
    '<bolt-navbar> with 6 lengthy links',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          title: {
            tag: 'h2',
            text: 'Navbar with links',
            icon: {
              name: 'marketing-gray',
            },
          },
          links: [
            {
              text: 'Real-Time AI',
              url: '#!',
            },
            {
              text: 'End-to-end Automation',
              url: '#!',
            },
            {
              text: 'Journey-centric Delivery',
              url: '#!',
            },
            {
              text: 'Low Code',
              url: '#!',
            },
            {
              text: 'Multi-dimensional Power',
              url: '#!',
            },
            {
              text: 'Cloud Choice',
              url: '#!',
            },
          ],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);

      const screenshots = [];

      async function isVisible(selector) {
        return await page.evaluate(selector => {
          const e = document.querySelector(selector);
          if (!e) return false;
          const style = window.getComputedStyle(e);
          return style &&
            style.display !== 'none' &&
            style.visibility !== 'hidden' &&
            style.opacity !== '0'
            ? true
            : false;
        }, selector);
      }

      for (const item of viewportSizes) {
        const { height, width, size } = item;
        screenshots[size] = [];

        await page.setViewport({ height, width });
        screenshots[size].default = await page.screenshot();
        expect(screenshots[size].default).toMatchImageSnapshot(imageVrtConfig);

        if (await isVisible('.c-bolt-nav-priority__show-more')) {
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
          screenshots[size].navOpened = await page.screenshot();
          expect(screenshots[size].navOpened).toMatchImageSnapshot(
            imageVrtConfig,
          );
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
        }
      }
    },
    timeout,
  );

  test(
    '<bolt-navbar> with a linked title',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          theme: 'light',
          width: 'full',
          title: {
            tag: 'h1',
            text: 'Bolt Design System',
            url: 'https://www.boltdesignsystem.com',
            icon: {
              name: 'bolt-logo-colored',
            },
          },
          links: [
            {
              text: 'Real-Time AI',
              url: '#!',
            },
            {
              text: 'End-to-end Automation',
              url: '#!',
            },
            {
              text: 'Journey-centric Delivery',
              url: '#!',
            },
            {
              text: 'Low Code',
              url: '#!',
            },
            {
              text: 'Multi-dimensional Power',
              url: '#!',
            },
            {
              text: 'Cloud Choice',
              url: '#!',
            },
          ],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);

      await page.hover('.c-bolt-navbar__title--link');

      const image = await page.screenshot();
      expect(image).toMatchImageSnapshot(imageVrtConfig);

      await page.tap('.c-bolt-navbar__title--link');

      const pageTitle = await page.title();
      expect(pageTitle).toMatch('Bolt Design System');
    },
    timeout,
  );

  test(
    '<bolt-navbar> with 4 short links',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          theme: 'xdark',
          width: 'auto',
          title: {
            tag: 'h1',
            text:
              'Bolt Design System',
            url: '/',
            icon: {
              name: 'bolt-logo-colored',
            },
          },
          links: [
            {
              text: 'Components',
              url: '/pattern-lab/index.html',
            },
            {
              text: 'Docs',
              url: '/docs/getting-started/index.html',
            },
            {
              text: 'Releases',
              url: 'https://github.com/bolt-design-system/bolt/releases',
              attributes: {
                target: '_blank',
              },
            },
            {
              text: 'Github',
              url: 'https://github.com/bolt-design-system/bolt',
              attributes: {
                target: '_blank',
              },
              icon: {
                name: 'github',
                position: 'after',
              },
            },
          ],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);

      const screenshots = [];

      async function isVisible(selector) {
        return await page.evaluate(selector => {
          const e = document.querySelector(selector);
          if (!e) return false;
          const style = window.getComputedStyle(e);
          return style &&
            style.display !== 'none' &&
            style.visibility !== 'hidden' &&
            style.opacity !== '0'
            ? true
            : false;
        }, selector);
      }

      for (const item of viewportSizes) {
        const { height, width, size } = item;
        screenshots[size] = [];

        await page.setViewport({ height, width });
        screenshots[size].default = await page.screenshot();
        expect(screenshots[size].default).toMatchImageSnapshot(imageVrtConfig);

        if (await isVisible('.c-bolt-nav-priority__show-more')) {
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
          screenshots[size].navOpened = await page.screenshot();
          expect(screenshots[size].navOpened).toMatchImageSnapshot(
            imageVrtConfig,
          );
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
        }
      }
    },
    timeout,
  );

  test(
    '<bolt-navbar> centered with 4 short links',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          theme: 'xdark',
          width: 'auto',
          center: true,
          title: {
            tag: 'h1',
            text:
              'Bolt Design System',
            url: '/',
            icon: {
              name: 'bolt-logo-colored',
            },
          },
          links: [
            {
              text: 'Components',
              url: '/pattern-lab/index.html',
            },
            {
              text: 'Docs',
              url: '/docs/getting-started/index.html',
            },
            {
              text: 'Releases',
              url: 'https://github.com/bolt-design-system/bolt/releases',
              attributes: {
                target: '_blank',
              },
            },
            {
              text: 'Github',
              url: 'https://github.com/bolt-design-system/bolt',
              attributes: {
                target: '_blank',
              },
              icon: {
                name: 'github',
                position: 'after',
              },
            },
          ],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);

      const screenshots = [];

      async function isVisible(selector) {
        return await page.evaluate(selector => {
          const e = document.querySelector(selector);
          if (!e) return false;
          const style = window.getComputedStyle(e);
          return style &&
            style.display !== 'none' &&
            style.visibility !== 'hidden' &&
            style.opacity !== '0'
            ? true
            : false;
        }, selector);
      }

      for (const item of viewportSizes) {
        const { height, width, size } = item;
        screenshots[size] = [];

        await page.setViewport({ height, width });
        screenshots[size].default = await page.screenshot();
        expect(screenshots[size].default).toMatchImageSnapshot(imageVrtConfig);

        if (await isVisible('.c-bolt-nav-priority__show-more')) {
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
          screenshots[size].navOpened = await page.screenshot();
          expect(screenshots[size].navOpened).toMatchImageSnapshot(
            imageVrtConfig,
          );
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
        }
      }
    },
    timeout,
  );

  test(
    '<bolt-navbar> without links',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          title: {
            tag: 'h2',
            text: 'Navbar without links',
            icon: {
              name: 'marketing-gray',
            },
          },
          links: [],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);
      const largeViewport = await page.screenshot();

      expect(largeViewport).toMatchImageSnapshot(imageVrtConfig);

      await page.setViewport({ height: 568, width: 320 });
      const smallViewport = await page.screenshot();

      expect(smallViewport).toMatchImageSnapshot(imageVrtConfig);
    },
    timeout,
  );

  test(
    '<bolt-navbar> without a title',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          links: [
            {
              text: 'Components',
              url: '/pattern-lab/index.html',
            },
            {
              text: 'Docs',
              url: '/docs/getting-started/index.html',
            },
            {
              text: 'Releases',
              url: 'https://github.com/bolt-design-system/bolt/releases',
              attributes: {
                target: '_blank',
              },
            },
            {
              text: 'Github',
              url: 'https://github.com/bolt-design-system/bolt',
              attributes: {
                target: '_blank',
              },
              icon: {
                name: 'github',
                position: 'after',
              },
            },
          ],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);
      const largeViewport = await page.screenshot();

      expect(largeViewport).toMatchImageSnapshot(imageVrtConfig);

      await page.setViewport({ height: 568, width: 320 });
      const smallViewport = await page.screenshot();

      expect(smallViewport).toMatchImageSnapshot(imageVrtConfig);
    },
    timeout,
  );

  test(
    '<bolt-navbar> variable width',
    async () => {
      const { html, ok } = await renderTwigString(`
      {% grid "o-bolt-grid--center" %}
        {% cell "u-bolt-width-2/3 u-bolt-width-1/2@small" %}
          {% include "@bolt-components-navbar/navbar.twig" with {
            width: 'auto',
            center: true,
            links: [
              {
                text: 'Components',
                url: '/pattern-lab/index.html',
              },
              {
                text: 'Docs',
                url: '/docs/getting-started/index.html',
              },
              {
                text: 'Releases',
                url: 'https://github.com/bolt-design-system/bolt/releases',
                attributes: {
                  target: '_blank',
                },
              },
              {
                text: 'Github',
                url: 'https://github.com/bolt-design-system/bolt',
                attributes: {
                  target: '_blank',
                },
                icon: {
                  name: 'github',
                  position: 'after',
                },
              },
            ],
          } only %}
        {% endcell %}
      {% endgrid %}
    `);
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);

      const screenshots = [];

      for (const item of viewportSizes) {
        const { height, width, size } = item;
        screenshots[size] = [];

        await page.setViewport({ height, width });
        screenshots[size].default = await page.screenshot();
        expect(screenshots[size].default).toMatchImageSnapshot(imageVrtConfig);
      }
    },
    timeout,
  );
});
<commit_msg>fix: update navbar Jest test to wait until page navigation has finished. fixes inconsistent navbar test<commit_after>/* eslint-disable no-await-in-loop */
import {
  render,
  renderString,
  stop as stopTwigRenderer,
} from '@bolt/twig-renderer';
import { fixture as html } from '@open-wc/testing-helpers';
import { join } from 'path';

async function renderTwig(template, data) {
  return await render(template, data, true);
}

async function renderTwigString(template, data) {
  return await renderString(template, data, true);
}

const imageVrtConfig = {
  failureThreshold: '0.02',
  failureThresholdType: 'percent',
};

const timeout = 120000;

const viewportSizes = [
  {
    size: 'xlarge',
    width: 1920,
    height: 1080,
  },
  {
    size: 'large',
    width: 1024,
    height: 768,
  },
  {
    size: 'medium',
    width: 896,
    height: 414,
  },
  {
    size: 'small',
    width: 320,
    height: 568,
  },
];

describe('<bolt-navbar> Component', () => {
  let page;

  afterAll(async () => {
    await stopTwigRenderer();
  }, timeout);

  beforeEach(async () => {
    page = await global.__BROWSER__.newPage();
    await page.goto('http://127.0.0.1:4444/', {
      timeout: 0,
      waitLoad: true,
      waitNetworkIdle: true, // defaults to false
    });
  }, timeout);

  test(
    '<bolt-navbar> with 6 lengthy links',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          title: {
            tag: 'h2',
            text: 'Navbar with links',
            icon: {
              name: 'marketing-gray',
            },
          },
          links: [
            {
              text: 'Real-Time AI',
              url: '#!',
            },
            {
              text: 'End-to-end Automation',
              url: '#!',
            },
            {
              text: 'Journey-centric Delivery',
              url: '#!',
            },
            {
              text: 'Low Code',
              url: '#!',
            },
            {
              text: 'Multi-dimensional Power',
              url: '#!',
            },
            {
              text: 'Cloud Choice',
              url: '#!',
            },
          ],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);

      const screenshots = [];

      async function isVisible(selector) {
        return await page.evaluate(selector => {
          const e = document.querySelector(selector);
          if (!e) return false;
          const style = window.getComputedStyle(e);
          return style &&
            style.display !== 'none' &&
            style.visibility !== 'hidden' &&
            style.opacity !== '0'
            ? true
            : false;
        }, selector);
      }

      for (const item of viewportSizes) {
        const { height, width, size } = item;
        screenshots[size] = [];

        await page.setViewport({ height, width });
        screenshots[size].default = await page.screenshot();
        expect(screenshots[size].default).toMatchImageSnapshot(imageVrtConfig);

        if (await isVisible('.c-bolt-nav-priority__show-more')) {
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
          screenshots[size].navOpened = await page.screenshot();
          expect(screenshots[size].navOpened).toMatchImageSnapshot(
            imageVrtConfig,
          );
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
        }
      }
    },
    timeout,
  );

  test(
    '<bolt-navbar> with a linked title',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          theme: 'light',
          width: 'full',
          title: {
            tag: 'h1',
            text: 'Bolt Design System',
            url: 'https://www.boltdesignsystem.com',
            icon: {
              name: 'bolt-logo-colored',
            },
          },
          links: [
            {
              text: 'Real-Time AI',
              url: '#!',
            },
            {
              text: 'End-to-end Automation',
              url: '#!',
            },
            {
              text: 'Journey-centric Delivery',
              url: '#!',
            },
            {
              text: 'Low Code',
              url: '#!',
            },
            {
              text: 'Multi-dimensional Power',
              url: '#!',
            },
            {
              text: 'Cloud Choice',
              url: '#!',
            },
          ],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);

      const navigationPromise = page.waitForNavigation();
      await page.hover('.c-bolt-navbar__title--link');

      const image = await page.screenshot();
      expect(image).toMatchImageSnapshot(imageVrtConfig);

      await page.click('.c-bolt-navbar__title--link');
      await navigationPromise; // wait for page navigation to finish before verifying the navbar link rendered + brought us to the main docs site

      const pageTitle = await page.title();
      expect(pageTitle).toMatch('Bolt Design System');
    },
    timeout,
  );

  test(
    '<bolt-navbar> with 4 short links',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          theme: 'xdark',
          width: 'auto',
          title: {
            tag: 'h1',
            text:
              'Bolt Design System',
            url: '/',
            icon: {
              name: 'bolt-logo-colored',
            },
          },
          links: [
            {
              text: 'Components',
              url: '/pattern-lab/index.html',
            },
            {
              text: 'Docs',
              url: '/docs/getting-started/index.html',
            },
            {
              text: 'Releases',
              url: 'https://github.com/bolt-design-system/bolt/releases',
              attributes: {
                target: '_blank',
              },
            },
            {
              text: 'Github',
              url: 'https://github.com/bolt-design-system/bolt',
              attributes: {
                target: '_blank',
              },
              icon: {
                name: 'github',
                position: 'after',
              },
            },
          ],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);

      const screenshots = [];

      async function isVisible(selector) {
        return await page.evaluate(selector => {
          const e = document.querySelector(selector);
          if (!e) return false;
          const style = window.getComputedStyle(e);
          return style &&
            style.display !== 'none' &&
            style.visibility !== 'hidden' &&
            style.opacity !== '0'
            ? true
            : false;
        }, selector);
      }

      for (const item of viewportSizes) {
        const { height, width, size } = item;
        screenshots[size] = [];

        await page.setViewport({ height, width });
        screenshots[size].default = await page.screenshot();
        expect(screenshots[size].default).toMatchImageSnapshot(imageVrtConfig);

        if (await isVisible('.c-bolt-nav-priority__show-more')) {
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
          screenshots[size].navOpened = await page.screenshot();
          expect(screenshots[size].navOpened).toMatchImageSnapshot(
            imageVrtConfig,
          );
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
        }
      }
    },
    timeout,
  );

  test(
    '<bolt-navbar> centered with 4 short links',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          theme: 'xdark',
          width: 'auto',
          center: true,
          title: {
            tag: 'h1',
            text:
              'Bolt Design System',
            url: '/',
            icon: {
              name: 'bolt-logo-colored',
            },
          },
          links: [
            {
              text: 'Components',
              url: '/pattern-lab/index.html',
            },
            {
              text: 'Docs',
              url: '/docs/getting-started/index.html',
            },
            {
              text: 'Releases',
              url: 'https://github.com/bolt-design-system/bolt/releases',
              attributes: {
                target: '_blank',
              },
            },
            {
              text: 'Github',
              url: 'https://github.com/bolt-design-system/bolt',
              attributes: {
                target: '_blank',
              },
              icon: {
                name: 'github',
                position: 'after',
              },
            },
          ],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);

      const screenshots = [];

      async function isVisible(selector) {
        return await page.evaluate(selector => {
          const e = document.querySelector(selector);
          if (!e) return false;
          const style = window.getComputedStyle(e);
          return style &&
            style.display !== 'none' &&
            style.visibility !== 'hidden' &&
            style.opacity !== '0'
            ? true
            : false;
        }, selector);
      }

      for (const item of viewportSizes) {
        const { height, width, size } = item;
        screenshots[size] = [];

        await page.setViewport({ height, width });
        screenshots[size].default = await page.screenshot();
        expect(screenshots[size].default).toMatchImageSnapshot(imageVrtConfig);

        if (await isVisible('.c-bolt-nav-priority__show-more')) {
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
          screenshots[size].navOpened = await page.screenshot();
          expect(screenshots[size].navOpened).toMatchImageSnapshot(
            imageVrtConfig,
          );
          await page.tap('.c-bolt-nav-priority__button');
          await page.waitFor(500);
        }
      }
    },
    timeout,
  );

  test(
    '<bolt-navbar> without links',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          title: {
            tag: 'h2',
            text: 'Navbar without links',
            icon: {
              name: 'marketing-gray',
            },
          },
          links: [],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);
      const largeViewport = await page.screenshot();

      expect(largeViewport).toMatchImageSnapshot(imageVrtConfig);

      await page.setViewport({ height: 568, width: 320 });
      const smallViewport = await page.screenshot();

      expect(smallViewport).toMatchImageSnapshot(imageVrtConfig);
    },
    timeout,
  );

  test(
    '<bolt-navbar> without a title',
    async () => {
      const { html, ok } = await renderTwig(
        '@bolt-components-navbar/navbar.twig',
        {
          links: [
            {
              text: 'Components',
              url: '/pattern-lab/index.html',
            },
            {
              text: 'Docs',
              url: '/docs/getting-started/index.html',
            },
            {
              text: 'Releases',
              url: 'https://github.com/bolt-design-system/bolt/releases',
              attributes: {
                target: '_blank',
              },
            },
            {
              text: 'Github',
              url: 'https://github.com/bolt-design-system/bolt',
              attributes: {
                target: '_blank',
              },
              icon: {
                name: 'github',
                position: 'after',
              },
            },
          ],
        },
      );
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);
      const largeViewport = await page.screenshot();

      expect(largeViewport).toMatchImageSnapshot(imageVrtConfig);

      await page.setViewport({ height: 568, width: 320 });
      const smallViewport = await page.screenshot();

      expect(smallViewport).toMatchImageSnapshot(imageVrtConfig);
    },
    timeout,
  );

  test(
    '<bolt-navbar> variable width',
    async () => {
      const { html, ok } = await renderTwigString(`
      {% grid "o-bolt-grid--center" %}
        {% cell "u-bolt-width-2/3 u-bolt-width-1/2@small" %}
          {% include "@bolt-components-navbar/navbar.twig" with {
            width: 'auto',
            center: true,
            links: [
              {
                text: 'Components',
                url: '/pattern-lab/index.html',
              },
              {
                text: 'Docs',
                url: '/docs/getting-started/index.html',
              },
              {
                text: 'Releases',
                url: 'https://github.com/bolt-design-system/bolt/releases',
                attributes: {
                  target: '_blank',
                },
              },
              {
                text: 'Github',
                url: 'https://github.com/bolt-design-system/bolt',
                attributes: {
                  target: '_blank',
                },
                icon: {
                  name: 'github',
                  position: 'after',
                },
              },
            ],
          } only %}
        {% endcell %}
      {% endgrid %}
    `);
      expect(ok).toBe(true);
      expect(html).toMatchSnapshot();

      await page.evaluate(html => {
        const div = document.createElement('div');
        div.innerHTML = `${html}`;
        document.body.appendChild(div);
      }, html);

      const screenshots = [];

      for (const item of viewportSizes) {
        const { height, width, size } = item;
        screenshots[size] = [];

        await page.setViewport({ height, width });
        screenshots[size].default = await page.screenshot();
        expect(screenshots[size].default).toMatchImageSnapshot(imageVrtConfig);
      }
    },
    timeout,
  );
});
<|endoftext|>


<commit_before>'use strict';

var assert = require('assert');
var util = require('util');
var fs = require('fs');
var vm = require('vm');
var Compiler = require('..').Compiler;

// Fake Angular environment
function makeEnv(mod, catalog) {
    return {
        angular: {
            module: function (modDefined) {
                assert.equal(modDefined, mod);
                return {
                    run: function (block) {
                        assert.equal(block[0], 'gettextCatalog');
                        return block[1](catalog);
                    }
                };
            }
        }
    };
}

// Fake Angular environment with RequireJS module loader
function makeRequireJsEnv(mod, modPath, catalog) {
    return {
        define: function (modules, callback) {
            assert.equal(modules[0], 'angular');
            assert.equal(modules[1], modPath);

            var angular = {
                module: function (modDefined) {
                    assert.equal(modDefined, mod);
                    return {
                        run: function (block) {
                            assert.equal(block[0], 'gettextCatalog');
                            block[1](catalog);
                        }
                    };
                }
            };
            callback(angular);
        }
    };
}

function testCompile(filenames, options) {
    var compiler = new Compiler(options);
    var inputs = filenames.map(function (filename) {
        return fs.readFileSync(filename, 'utf8');
    });
    return compiler.convertPo(inputs);
}

describe('Compile', function () {
    it('Compiles a .po file into a .js catalog', function () {
        var files = ['test/fixtures/nl.po'];
        var output = testCompile(files);
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
                assert.equal(language, 'nl');
                assert.equal(strings['Hello!'], 'Hallo!');
                assert.equal(strings['This is a test'], 'Dit is een test');
                assert.deepEqual(strings.Bird, ['Vogel', 'Vogels']);
                assert.deepEqual(strings['Hello "world"'], 'Hallo "wereld"');
            }
        };

        var context = vm.createContext(makeEnv('gettext', catalog));
        vm.runInContext(output, context);
        assert(catalog.called);
    });

    it('Accepts a module parameter', function () {
        var files = ['test/fixtures/nl.po'];
        var output = testCompile(files, {
            module: 'myApp'
        });
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
            }
        };

        var context = vm.createContext(makeEnv('myApp', catalog));
        vm.runInContext(output, context);
        assert(catalog.called);
    });

    it('Accepts a defaultLanguage parameter', function () {
        var files = ['test/fixtures/nl.po'];
        var output = testCompile(files, {
            defaultLanguage: 'nl'
        });
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
            }
        };

        var context = vm.createContext(makeEnv('gettext', catalog));
        vm.runInContext(output, context);
        assert(catalog.called);
        assert.notEqual(output.indexOf('gettextCatalog.currentLanguage = \'nl\';'), -1);
        assert.equal(catalog.currentLanguage, 'nl');
    });

    it('Accepts a requirejs and modulePath parameter', function () {
        var files = ['test/fixtures/nl.po'];
        var output = testCompile(files, {
            module: 'myApp',
            requirejs: true,
            modulePath: './test/fixtures/module'
        });
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
            }
        };

        var context = vm.createContext(makeRequireJsEnv('myApp', './test/fixtures/module', catalog));
        vm.runInContext(output, context);
        assert(catalog.called);
    });

    it('Allows merging multiple languages', function () {
        var files = ['test/fixtures/nl.po', 'test/fixtures/fr.po'];
        var output = testCompile(files);
        var languages = 0;
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
                assert(language === 'nl' || language === 'fr');
                languages++;
            }
        };

        var context = vm.createContext(makeEnv('gettext', catalog));
        vm.runInContext(output, context);
        assert.equal(languages, 2);
        assert(catalog.called);
    });

    it('Can output to JSON', function () {
        var files = ['test/fixtures/nl.po', 'test/fixtures/fr.po'];
        var output = testCompile(files, {
            format: 'json'
        });
        var data = JSON.parse(output);

        assert.deepEqual(data.fr, {
            'Hello!': 'Bonjour!',
            'This is a test': 'Ceci est un test',
            'Bird': ['Oiseau', 'Oiseaux']
        });

        assert.deepEqual(data.nl, {
            'Hello!': 'Hallo!',
            'This is a test': 'Dit is een test',
            'Bird': ['Vogel', 'Vogels'],
            'Hello "world"': 'Hallo "wereld"'
        });
    });

    it('Ignores empty strings', function () {
        var files = ['test/fixtures/empty.po'];
        var output = testCompile(files, {
            format: 'json'
        });
        var data = JSON.parse(output);
        assert.deepEqual(data.nl, {
            'This is a test': 'Dit is een test'
        });
    });

    it('Ignores fuzzy strings', function () {
        var files = ['test/fixtures/fuzzy.po'];
        var output = testCompile(files, {
            format: 'json'
        });
        var data = JSON.parse(output);

        assert.deepEqual(data.nl, {
            'This is a test': 'Dit is een test'
        });
    });

    it('Can output multiple inputs to single JSON', function () {
        var files = ['test/fixtures/fr.po', 'test/fixtures/depth/fr.po'];
        var output = testCompile(files, {
            format: 'json'
        });
        var data = JSON.parse(output);

        assert.deepEqual(data.fr, {
            'Hello!': 'Bonjour!',
            'This is a test': 'Ceci est un test',
            'Bird': ['Oiseau', 'Oiseaux'],
            'Goodbye!': 'Au revoir!'
        });
    });

    it('Can handle contexts', function () {
        var files = ['test/fixtures/context.po'];
        var output = testCompile(files, {
            format: 'json'
        });
        var data = JSON.parse(output);

        assert.deepEqual(data.nl, {
            'Hello!': {
                '$$noContext': 'Hallo!',
                'male': 'Hallo (male)!'
            },
            'Goodbye': 'Vaarwel',
            'Ciao': { female: 'Ciao (female)' }
        });
    });

    it('Does not compile obsolete strings', function () {
        var files = ['test/fixtures/obsolete.po'];
        var output = testCompile(files);
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
                assert.equal(language, 'nl');
                assert.equal(strings['Hello!'], 'Hallo!');
                assert.equal(strings['Hello "world"'], undefined);
            }
        };

        var context = vm.createContext(makeEnv('gettext', catalog));
        vm.runInContext(output, context);
        assert(catalog.called);
    });
});
<commit_msg>adapt test<commit_after>'use strict';

var assert = require('assert');
var util = require('util');
var fs = require('fs');
var vm = require('vm');
var Compiler = require('..').Compiler;

// Fake Angular environment
function makeEnv(mod, catalog) {
    return {
        angular: {
            module: function (modDefined) {
                assert.equal(modDefined, mod);
                return {
                    run: function (block) {
                        assert.equal(block[0], 'gettextCatalog');
                        return block[1](catalog);
                    }
                };
            }
        }
    };
}

// Fake Angular environment with RequireJS module loader
function makeRequireJsEnv(mod, name, deps, catalog) {
    return {
        define: function (expliciteName, modules, callback) {
            assert.equal(modules[0], deps[0]);
            assert.equal(modules[1], deps[1]);

            var angular = {
                module: function (modDefined) {
                    assert.equal(modDefined, mod);
                    return {
                        run: function (block) {
                            assert.equal(block[0], 'gettextCatalog');
                            block[1](catalog);
                        }
                    };
                }
            };
            callback(angular);
        }
    };
}

function testCompile(filenames, options) {
    var compiler = new Compiler(options);
    var inputs = filenames.map(function (filename) {
        return fs.readFileSync(filename, 'utf8');
    });
    return compiler.convertPo(inputs);
}

describe('Compile', function () {
    it('Compiles a .po file into a .js catalog', function () {
        var files = ['test/fixtures/nl.po'];
        var output = testCompile(files);
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
                assert.equal(language, 'nl');
                assert.equal(strings['Hello!'], 'Hallo!');
                assert.equal(strings['This is a test'], 'Dit is een test');
                assert.deepEqual(strings.Bird, ['Vogel', 'Vogels']);
                assert.deepEqual(strings['Hello "world"'], 'Hallo "wereld"');
            }
        };

        var context = vm.createContext(makeEnv('gettext', catalog));
        vm.runInContext(output, context);
        assert(catalog.called);
    });

    it('Accepts a module parameter', function () {
        var files = ['test/fixtures/nl.po'];
        var output = testCompile(files, {
            module: 'myApp'
        });
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
            }
        };

        var context = vm.createContext(makeEnv('myApp', catalog));
        vm.runInContext(output, context);
        assert(catalog.called);
    });

    it('Accepts a defaultLanguage parameter', function () {
        var files = ['test/fixtures/nl.po'];
        var output = testCompile(files, {
            defaultLanguage: 'nl'
        });
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
            }
        };

        var context = vm.createContext(makeEnv('gettext', catalog));
        vm.runInContext(output, context);
        assert(catalog.called);
        assert.notEqual(output.indexOf('gettextCatalog.currentLanguage = \'nl\';'), -1);
        assert.equal(catalog.currentLanguage, 'nl');
    });

    it('Accepts a requirejs and modulePath parameter', function () {
        var files = ['test/fixtures/nl.po'];
        var output = testCompile(files, {
            module: 'myApp',
            requirejs: true,
            modulePath: ['angular', './test/fixtures/module']
        });
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
            }
        };

        var context = vm.createContext(makeRequireJsEnv('myApp', 'testName', ['angular', './test/fixtures/module'], catalog));
        vm.runInContext(output, context);
        assert(catalog.called);
    });

    it('Allows merging multiple languages', function () {
        var files = ['test/fixtures/nl.po', 'test/fixtures/fr.po'];
        var output = testCompile(files);
        var languages = 0;
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
                assert(language === 'nl' || language === 'fr');
                languages++;
            }
        };

        var context = vm.createContext(makeEnv('gettext', catalog));
        vm.runInContext(output, context);
        assert.equal(languages, 2);
        assert(catalog.called);
    });

    it('Can output to JSON', function () {
        var files = ['test/fixtures/nl.po', 'test/fixtures/fr.po'];
        var output = testCompile(files, {
            format: 'json'
        });
        var data = JSON.parse(output);

        assert.deepEqual(data.fr, {
            'Hello!': 'Bonjour!',
            'This is a test': 'Ceci est un test',
            'Bird': ['Oiseau', 'Oiseaux']
        });

        assert.deepEqual(data.nl, {
            'Hello!': 'Hallo!',
            'This is a test': 'Dit is een test',
            'Bird': ['Vogel', 'Vogels'],
            'Hello "world"': 'Hallo "wereld"'
        });
    });

    it('Ignores empty strings', function () {
        var files = ['test/fixtures/empty.po'];
        var output = testCompile(files, {
            format: 'json'
        });
        var data = JSON.parse(output);
        assert.deepEqual(data.nl, {
            'This is a test': 'Dit is een test'
        });
    });

    it('Ignores fuzzy strings', function () {
        var files = ['test/fixtures/fuzzy.po'];
        var output = testCompile(files, {
            format: 'json'
        });
        var data = JSON.parse(output);

        assert.deepEqual(data.nl, {
            'This is a test': 'Dit is een test'
        });
    });

    it('Can output multiple inputs to single JSON', function () {
        var files = ['test/fixtures/fr.po', 'test/fixtures/depth/fr.po'];
        var output = testCompile(files, {
            format: 'json'
        });
        var data = JSON.parse(output);

        assert.deepEqual(data.fr, {
            'Hello!': 'Bonjour!',
            'This is a test': 'Ceci est un test',
            'Bird': ['Oiseau', 'Oiseaux'],
            'Goodbye!': 'Au revoir!'
        });
    });

    it('Can handle contexts', function () {
        var files = ['test/fixtures/context.po'];
        var output = testCompile(files, {
            format: 'json'
        });
        var data = JSON.parse(output);

        assert.deepEqual(data.nl, {
            'Hello!': {
                '$$noContext': 'Hallo!',
                'male': 'Hallo (male)!'
            },
            'Goodbye': 'Vaarwel',
            'Ciao': { female: 'Ciao (female)' }
        });
    });

    it('Does not compile obsolete strings', function () {
        var files = ['test/fixtures/obsolete.po'];
        var output = testCompile(files);
        var catalog = {
            called: false,
            setStrings: function (language, strings) {
                this.called = true;
                assert.equal(language, 'nl');
                assert.equal(strings['Hello!'], 'Hallo!');
                assert.equal(strings['Hello "world"'], undefined);
            }
        };

        var context = vm.createContext(makeEnv('gettext', catalog));
        vm.runInContext(output, context);
        assert(catalog.called);
    });
});
<|endoftext|>


<commit_before>var Utils = module.exports = {
  r20: /%20/g,
  noop: function() {},

  isObjEmpty: function(obj) {
    for(var key in obj) {
      if(obj.hasOwnProperty(key)) return false;
    }

    return true;
  },

  extend: function(out) {
    out = out || {};

    for (var i = 1; i < arguments.length; i++) {
      if (!arguments[i])
        continue;

      for (var key in arguments[i]) {
        if (arguments[i].hasOwnProperty(key) && arguments[i][key] !== undefined)
          out[key] = arguments[i][key];
      }
    }

    return out;
  },

  params: function(entry) {
    if (typeof entry !== 'object') {
      return entry;
    }

    var validKeys = function(entry) {
      return Object.keys(entry).
        filter(function(key) {
          return entry[key] !== undefined &&
                 entry[key] !== null
        });
    }

    var buildRecursive = function(key, value, suffix) {
      suffix = suffix || '';
      var isArray = Array.isArray(value);
      var isObject = typeof value === 'object';

      if (!isArray && !isObject) {
        return encodeURIComponent(key + suffix) + '=' + encodeURIComponent(value);
      }

      if (isArray) {
        return value.map(function(v) { return buildRecursive(key, v, suffix + '[]') }).
        join('&');
      }

      return validKeys(value).
        map(function(k) { return buildRecursive(key, value[k], suffix + '[' + k + ']') }).
        join('&');
    }

    return validKeys(entry).
      map(function(key) { return buildRecursive(key, entry[key]) }).
      join('&').
      replace(Utils.r20, '+');
  },

  Exception: function(message) {
    this.message = message;
    this.toString = function() { return '[Mappersmith] ' + this.message; }
  }
}
<commit_msg>better convention<commit_after>var Utils = {
  r20: /%20/g,
  noop: function() {},

  isObjEmpty: function(obj) {
    for(var key in obj) {
      if(obj.hasOwnProperty(key)) return false;
    }

    return true;
  },

  extend: function(out) {
    out = out || {};

    for (var i = 1; i < arguments.length; i++) {
      if (!arguments[i])
        continue;

      for (var key in arguments[i]) {
        if (arguments[i].hasOwnProperty(key) && arguments[i][key] !== undefined)
          out[key] = arguments[i][key];
      }
    }

    return out;
  },

  params: function(entry) {
    if (typeof entry !== 'object') {
      return entry;
    }

    var validKeys = function(entry) {
      return Object.keys(entry).
        filter(function(key) {
          return entry[key] !== undefined &&
                 entry[key] !== null
        });
    }

    var buildRecursive = function(key, value, suffix) {
      suffix = suffix || '';
      var isArray = Array.isArray(value);
      var isObject = typeof value === 'object';

      if (!isArray && !isObject) {
        return encodeURIComponent(key + suffix) + '=' + encodeURIComponent(value);
      }

      if (isArray) {
        return value.map(function(v) { return buildRecursive(key, v, suffix + '[]') }).
        join('&');
      }

      return validKeys(value).
        map(function(k) { return buildRecursive(key, value[k], suffix + '[' + k + ']') }).
        join('&');
    }

    return validKeys(entry).
      map(function(key) { return buildRecursive(key, entry[key]) }).
      join('&').
      replace(Utils.r20, '+');
  },

  Exception: function(message) {
    this.message = message;
    this.toString = function() { return '[Mappersmith] ' + this.message; }
  }
}

module.exports = Utils;
<|endoftext|>


<commit_before>/**
 * Created by zhouyong on 15-1-8.
 */
function Cart(barCodes){
    this.barCodes = barCodes;
}
<commit_msg>add method parse_bar_code_to_commodities in Cart<commit_after>/**
 * Created by zhouyong on 15-1-8.
 */
function Cart(barCodes){
    this.barCodes = barCodes;
}

Cart.prototype = {
    parse_bar_codes_to_commodities : function(){
        var barCodes = this.barCodes;
        return _.map(barCodes,function(barCode){
            for(var i in barCode){
                var commodity = _.where(get_commodities(),{barCode:i});
                commodity.num = barCode[i];
                return commodity;
            }
        });
    }
};
<|endoftext|>