<commit_before>"use strict";

const
    tickGenerator = require("../src/tick-generator"),

    TICK = (ticker) => ticker.tick(),
    PAUSE = (ticker) => ticker.pause(),
    RESUME = (ticker) => ticker.resume(),

    execute = (ticker, sequence, delay = 100) => {
        return new Promise((resolve) => {
            const next = () => {
                let command = sequence.shift();
                setTimeout(function () {
                    command.call(null, ticker);
                    if (sequence.length) {
                        next();
                    } else {
                        resolve();
                    }
                }, delay);
            };
            next();

        });
    }
;

describe("tick-generator", function () {

    it("exists", () => {
        assert(tickGenerator);
    });

    it("allocates a tick generator", () => {
        let ticker = tickGenerator.allocate();
        assert(ticker);
    });

    it("exposes tick, pause and resume methods", () => {
        let ticker = tickGenerator.allocate();
        ["tick", "pause", "resume"].forEach(methodName => {
            assert("function" === typeof ticker[methodName]);
        });
    });

    it("exposes on callback handler", () => {
        let ticker = tickGenerator.allocate();
        assert("function" === typeof ticker.on);
    });

    it("triggers a tick upon callback attachment", (done) => {
        let ticker = tickGenerator.allocate();
        ticker.on((tick) => {
            try {
                assert(tick.paused);
                done();
            } catch (e) {
                done(e);
            }
        });
    });

    it("starts paused", (done) => {
        let ticker = tickGenerator.allocate();
        ticker.on((tick) => {
            try {
                assert(tick.paused);
                assert(0 === tick.elapsed);
            } catch (e) {
                done(e);
            }
        });
        execute(ticker, [TICK, TICK]).then(done);
    });

    it("measures elapsed time", (done) => {
        let ticker = tickGenerator.allocate(),
            ticked = -1; // 0 is initial tick when attaching callback
        ticker.on((tick) => {
            try {
                ++ticked;
                if (1 === ticked) {
                    assert(0 === tick.elapsed);
                } else if (2 === ticked) {
                    assert(100 <= tick.elapsed);
                }
            } catch (e) {
                done(e);
            }
        });
        execute(ticker, [RESUME, TICK]).then(done);
    });

    it("stops measuring time on pause", (done) => {
        let ticker = tickGenerator.allocate(),
            ticked = -1,  // 0 is initial tick when attaching callback
            lastElapsed;
        ticker.on((tick) => {
            try {
                ++ticked;
                if (2 < ticked) {
                    lastElapsed = tick.elapsed;
                    assert(200 <= lastElapsed);
                    assert(300 >= lastElapsed);
                }
                if (0 === ticked) {
                    assert(tick.paused);
                } else if (1 === ticked || 2 === ticked) {
                    assert(!tick.paused);
                } else {
                    assert(lastElapsed === tick.elapsed);
                    assert(tick.paused);
                }
            } catch (e) {
                console.log(e);
                done(e);
            }
        });
        execute(ticker, [RESUME, TICK, PAUSE, TICK]).then(done);
    });

});
<commit_msg>Adds isPaused<commit_after>"use strict";

const
    tickGenerator = require("../src/tick-generator"),

    TICK = (ticker) => ticker.tick(),
    PAUSE = (ticker) => ticker.pause(),
    RESUME = (ticker) => ticker.resume(),

    execute = (ticker, sequence, delay = 100) => {
        return new Promise((resolve) => {
            const next = () => {
                let command = sequence.shift();
                setTimeout(function () {
                    command.call(null, ticker);
                    if (sequence.length) {
                        next();
                    } else {
                        resolve();
                    }
                }, delay);
            };
            next();

        });
    }
;

describe("tick-generator", function () {

    it("exists", () => {
        assert(tickGenerator);
    });

    it("allocates a tick generator", () => {
        let ticker = tickGenerator.allocate();
        assert(ticker);
    });

    ["tick", "pause", "resume", "on", "isPaused"].forEach(methodName => {
        it(`exposes ${methodName} method`, () => {
            let ticker = tickGenerator.allocate();
            assert("function" === typeof ticker[methodName]);
        });
    });

    it("exposes on callback handler", () => {
        let ticker = tickGenerator.allocate();
        assert("function" === typeof ticker.on);
    });

    it("triggers a tick upon callback attachment", (done) => {
        let ticker = tickGenerator.allocate();
        ticker.on((tick) => {
            try {
                assert(tick.paused);
                assert(ticker.isPaused());
                done();
            } catch (e) {
                done(e);
            }
        });
    });

    it("starts paused", (done) => {
        let ticker = tickGenerator.allocate();
        ticker.on((tick) => {
            try {
                assert(tick.paused);
                assert(ticker.isPaused());
                assert(0 === tick.elapsed);
            } catch (e) {
                done(e);
            }
        });
        execute(ticker, [TICK, TICK]).then(done);
    });

    it("measures elapsed time", (done) => {
        let ticker = tickGenerator.allocate(),
            ticked = -1; // 0 is initial tick when attaching callback
        ticker.on((tick) => {
            try {
                ++ticked;
                if (1 === ticked) {
                    assert(0 === tick.elapsed);
                } else if (2 === ticked) {
                    assert(!ticker.isPaused());
                    assert(100 <= tick.elapsed);
                }
            } catch (e) {
                done(e);
            }
        });
        execute(ticker, [RESUME, TICK]).then(done);
    });

    it("stops measuring time on pause", (done) => {
        let ticker = tickGenerator.allocate(),
            ticked = -1,  // 0 is initial tick when attaching callback
            lastElapsed;
        ticker.on((tick) => {
            try {
                ++ticked;
                if (2 < ticked) {
                    lastElapsed = tick.elapsed;
                    assert(200 <= lastElapsed);
                    assert(300 >= lastElapsed);
                }
                if (0 === ticked) {
                    assert(tick.paused);
                    assert(ticker.isPaused());
                } else if (1 === ticked || 2 === ticked) {
                    assert(!tick.paused);
                    assert(!ticker.isPaused());
                } else {
                    assert(lastElapsed === tick.elapsed);
                    assert(tick.paused);
                    assert(ticker.isPaused());
                }
            } catch (e) {
                console.log(e);
                done(e);
            }
        });
        execute(ticker, [RESUME, TICK, PAUSE, TICK]).then(done);
    });

});
<|endoftext|>


<commit_before>import Section from '../section'

const Plugin = ({ title, description, color, href }) => (

    {title}

{description}

)

const Buttons = () => (

      Browse Plugins

      Download App

)
export default () => (

The power of open-source

            The ease of use and speed you’ve been looking for – the
            functionality and extensibility you didn’t know you needed.{' '}

            <Plugin
              title="giphy"
              color="#ffd500"
              description="Share GIFs on Giphy"
              href="https://github.com/wulkano/kap-giphy"
            />
            <Plugin
              title="now"
              color="#FFF"
              description="Share on ▲ZEIT now"
              href="https://github.com/lucaperret/kap-now"
            />
            <Plugin
              title="draggable"
              color="#00ffbe"
              description="Share recordings with drag and drop"
              href="https://github.com/albinekb/kap-draggable"
            />

          <Buttons />

)
<commit_msg>🐛 Fix mobile safari bug<commit_after>import Section from '../section'

const Plugin = ({ title, description, color, href }) => (

    {title}

{description}

)

const Buttons = () => (

      Browse Plugins

      Download App

)
export default () => (

The power of open-source

            The ease of use and speed you’ve been looking for – the
            functionality and extensibility you didn’t know you needed.{' '}

            <Plugin
              title="giphy"
              color="#ffd500"
              description="Share GIFs on Giphy"
              href="https://github.com/wulkano/kap-giphy"
            />
            <Plugin
              title="now"
              color="#FFF"
              description="Share on ▲ZEIT now"
              href="https://github.com/lucaperret/kap-now"
            />
            <Plugin
              title="draggable"
              color="#00ffbe"
              description="Share recordings with drag and drop"
              href="https://github.com/albinekb/kap-draggable"
            />

          <Buttons />

        <Buttons />

)
<|endoftext|>


<commit_before>'use strict';

// Projects controller
angular.module('projects').controller('ProjectsController', ['$scope', '$stateParams', '$location', 'Authentication', 'Projects', '$http', '$mdToast', '$mdDialog', '$timeout',
	function($scope, $stateParams, $location, Authentication, Projects, $http, $mdToast, $mdDialog, $timeout) {
		$scope.people = [];
		$http.get('/users/getUsers').success(function(users) {
			for (var i in users) {
				$scope.people.push(users[i].displayName);
			}
		});

		$scope.authentication = Authentication;
		$scope.rootIsEmpty = function() {
			//debugger;
			if (typeof $scope.project.children !== undefined) {
				if ($scope.project.children.length < 1) {
					return true;
				}
			} else {
				return false;
			}
		};
		$scope.addRootNode = function() {
			// initialise estimations array
			var estimationsArr = [];
			for (var i in $scope.project.users) {
				estimationsArr.push(null);
			}
			$scope.project.children.push({id: 'node', title:'Root Node', nodes: [], collapsed : false, estimations : estimationsArr});
		};
		$scope.goTo = function(route) {
			$location.path(route);
		};
		$scope.createProject = function() {
			//		var project = {'name': $scope.projectName, 'description': $scope.description, 'owner' : Authentication.user, 'users' : $scope.selected};
			var project = new Projects ({
			name: $scope.projectName,
			description: $scope.description,
			users : $scope.selected
		});
			project.$save(function(response) {
				$location.path('projects/' + project._id + '/edit');
				$mdToast.show(
				$mdToast.simple()
				.content('Project created')
				.position($scope.getToastPosition())
				.hideDelay(3000)
				);
			}, function(errorResponse) {
			$scope.error = errorResponse.data.message;
		});
			/*
				$http({method:'POST', url:'/projects', data: project}).success(function(res) {
					if (res === false) {
						if (project.owner === '') {
							$mdToast.show(
							$mdToast.simple()
							.content('Need to be logged in to create a project')
							.position($scope.getToastPosition())
							.hideDelay(3000)
							);
						} else {
							$mdToast.show(
							$mdToast.simple()
							.content('There already exists a project with that name')
							.position($scope.getToastPosition())
							.hideDelay(3000)
							);
						}
					} else {
						var invites = {'projectName': $scope.projectName, 'users': $scope.selected};
						//$http({method:'POST', url:'/email', data: invites});

						$mdToast.show(
						$mdToast.simple()
						.content('Project created')
						.position($scope.getToastPosition())
						.hideDelay(3000)
						);

						$scope.goTo('/project/' + project._id);
					}
				});
*/
		};

		$scope.deleteProject = function(project) {
			var confirm = $mdDialog.confirm()
			.parent(angular.element(document.body))
			.title('Are you sure you wish to delete project ' + project.name + '?')
			.content('This will delete the project and prevent it from showing up in the list of projects.')
			.ariaLabel('Delete the project')
			.ok('Yes')
			.cancel('No');
			$mdDialog.show(confirm).then(function() {
				$timeout(function() {
					//$http({method:'DELETE', url:'/projects/' + project._id, data: project}).success(function() {
					//	$scope.updateProjects();
					//});
					$scope.remove(project);
				});
					//debugger;
			}, function() {
			});
		};

		$scope.toastPosition = {
			bottom: true,
			top: false,
			left: false,
			right: true
		};

		$scope.getToastPosition = function() {
			return Object.keys($scope.toastPosition)
			.filter(function(pos) { return $scope.toastPosition[pos]; })
			.join(' ');
		};

		// Remove existing Project
		$scope.remove = function(project) {
			if (project) {
				project.$remove();

				for (var i in $scope.projects) {
					if ($scope.projects [i] === project) {
						$scope.projects.splice(i, 1);
					}
				}
			} else {
				$scope.project.$remove(function() {
					$location.path('projects');
				});
			}
		};

		// Update existing Project
		$scope.update = function() {
			var project = $scope.project;

			project.$update(function() {
				$location.path('projects/' + project._id);
			}, function(errorResponse) {
				$scope.error = errorResponse.data.message;
			});
		};

		// Find a list of Projects
		$scope.find = function() {
			$scope.projects = Projects.query();
		};

		// Find existing Project
		$scope.findOne = function() {
			$scope.project = Projects.get({
				projectId: $stateParams.projectId
			});
		};

		$scope.updateProjects = function() {
			$scope.projects = Projects.query();
		};

		$scope.querySearch = function(query) {
			//console.log(query);
			var results = query ? $scope.projects.filter(createFilterFor(query)) : $scope.projects, deferred;
			return results;
		};

		$scope.searchTextChange = function(text) {
			console.log('Text changed to ' + text);
		};

		$scope.selectedItemChange = function(item) {
			console.log(item);
			$scope.goTo('/projects/' + item._id + '/edit');
		};

		var createFilterFor = function(query) {
			var lowercaseQuery = angular.lowercase(query);
			return function filterFn(item) {
				//console.log(item);
				var name = angular.lowercase(item.name);
				return (name.indexOf(lowercaseQuery) === 0);
			};
		};

		$scope.newSubItem = function(scope) {
			// console.log(scope.project.users);
			var nodeData = scope.$modelValue;
			// console.log(nodeData);
			var estimationsArr = [];
			for (var i in scope.project.users) {
				// console.log(i);
				estimationsArr.push(null);
			}
			nodeData.nodes.push({
				id: nodeData.id * 10 + nodeData.nodes.length,
				title: nodeData.title + '.' + (nodeData.nodes.length + 1),
				nodes: [],
				collapsed : false,
				estimations : estimationsArr
			});
		};

		$scope.collapseAll = function() {
			$scope.$broadcast('collapseAll');
		};

		$scope.expandAll = function() {
			$scope.$broadcast('expandAll');
		};

		$scope.undoToolTip = function(node, removeNode, newSubItem) {
			//debugger;
			var tree = $.extend(true, [], $scope.project.children);
			removeNode(node);
			var toast = $mdToast.simple()
				.content('Node deleted')
				.action('UNDO')
				.highlightAction(false)
				.position($scope.getToastPosition());
			$mdToast.show(toast).then(function() {
				$scope.project.children = $.extend(true, [], tree);
			});
		};

		$scope.saveProject = function() {
			$scope.project.$update(function(response) {
				$mdToast.show(
					$mdToast.simple()
					.content('Project saved')
					.position($scope.getToastPosition())
					.hideDelay(3000)
				);
			}, function(errorResponse) {
				$scope.error = errorResponse.data.message;
			});
		};

		function DialogController($scope, $mdDialog) {
			$scope.hide = function() {
				$mdDialog.hide();
			};
			$scope.cancel = function() {
				$mdDialog.cancel();
			};
		}

		$scope.showDescriptionDialog = function(ev, node) {
			$scope.currentNode = node;

			$scope.setCurrentNode(node, function() {
				var newScope = $scope.$new();

				$mdDialog.show({
					controller: DialogController,
					templateUrl: 'modules/projects/views/description.dialog.client.view.html',
					parent: angular.element(document.body),
					targetEvent: ev,
					scope: newScope
				});
			});
		};

		$scope.setCurrentNode = function(node, callback) {
			$scope.currentNode = node;

			if (callback !== undefined) {
				callback();
			}
		};

		$scope.selected = [];
		$scope.toggle = function(item, list) {
			var idx = list.indexOf(item);
			if (idx > -1) {
				list.splice(idx, 1);
			} else {
				list.push(item);
			}
		};

		$scope.exists = function(item, list) {
			return list.indexOf(item) > -1;
		};

		$scope.$on('$locationChangeStart', function(event, newUrl, oldUrl) {
			// Appending dialog to document.body to cover sidenav in docs app
			if (!$scope.confirm) {
				event.preventDefault();
				//console.log(newUrl);
				var confirm = $mdDialog.confirm()
				.parent(angular.element(document.body))
				.title('Are you sure you want to leave this page?')
				.content('All unsaved changes will be lost.')
				.ariaLabel('Yes')
				.ok('Yes')
				.cancel('No')
				.targetEvent(event);
				$mdDialog.show(confirm).then(function() {
				newUrl = newUrl.split('#!');
				$scope.goTo(newUrl[1]);
				$scope.confirm = true;
				//$scope.saveProject();
			}, function() {

			});
			}

		});
	}
]);
<commit_msg>Re-adding bubble-up function<commit_after>'use strict';

// Projects controller
angular.module('projects').controller('ProjectsController', ['$scope', '$stateParams', '$location', 'Authentication', 'Projects', '$http', '$mdToast', '$mdDialog', '$timeout', '$rootScope',
	function($scope, $stateParams, $location, Authentication, Projects, $http, $mdToast, $mdDialog, $timeout, $rootScope) {
		$scope.people = [];
		$http.get('/users/getUsers').success(function(users) {
			for (var i in users) {
				$scope.people.push(users[i].displayName);
			}
		});

		$scope.authentication = Authentication;
		$scope.rootIsEmpty = function() {
			//debugger;
			if (typeof $scope.project.children !== undefined) {
				if ($scope.project.children.length < 1) {
					return true;
				}
			} else {
				return false;
			}
		};
		$scope.addRootNode = function() {
			// initialise estimations array
			var estimationsArr = [];
			for (var i in $scope.project.users) {
				estimationsArr.push(null);
			}
			$scope.project.children.push({id: 'node', title:'Root Node', nodes: [], collapsed : false, estimations : estimationsArr});
		};
		$scope.goTo = function(route) {
			$location.path(route);
		};
		$scope.createProject = function() {
			//		var project = {'name': $scope.projectName, 'description': $scope.description, 'owner' : Authentication.user, 'users' : $scope.selected};
			var project = new Projects ({
			name: $scope.projectName,
			description: $scope.description,
			users : $scope.selected
		});
			project.$save(function(response) {
				$location.path('projects/' + project._id + '/edit');
				$mdToast.show(
				$mdToast.simple()
				.content('Project created')
				.position($scope.getToastPosition())
				.hideDelay(3000)
				);
			}, function(errorResponse) {
			$scope.error = errorResponse.data.message;
		});
			/*
				$http({method:'POST', url:'/projects', data: project}).success(function(res) {
					if (res === false) {
						if (project.owner === '') {
							$mdToast.show(
							$mdToast.simple()
							.content('Need to be logged in to create a project')
							.position($scope.getToastPosition())
							.hideDelay(3000)
							);
						} else {
							$mdToast.show(
							$mdToast.simple()
							.content('There already exists a project with that name')
							.position($scope.getToastPosition())
							.hideDelay(3000)
							);
						}
					} else {
						var invites = {'projectName': $scope.projectName, 'users': $scope.selected};
						//$http({method:'POST', url:'/email', data: invites});

						$mdToast.show(
						$mdToast.simple()
						.content('Project created')
						.position($scope.getToastPosition())
						.hideDelay(3000)
						);

						$scope.goTo('/project/' + project._id);
					}
				});
*/
		};

		$scope.deleteProject = function(project) {
			var confirm = $mdDialog.confirm()
			.parent(angular.element(document.body))
			.title('Are you sure you wish to delete project ' + project.name + '?')
			.content('This will delete the project and prevent it from showing up in the list of projects.')
			.ariaLabel('Delete the project')
			.ok('Yes')
			.cancel('No');
			$mdDialog.show(confirm).then(function() {
				$timeout(function() {
					//$http({method:'DELETE', url:'/projects/' + project._id, data: project}).success(function() {
					//	$scope.updateProjects();
					//});
					$scope.remove(project);
				});
					//debugger;
			}, function() {
			});
		};

		$scope.toastPosition = {
			bottom: true,
			top: false,
			left: false,
			right: true
		};

		$scope.getToastPosition = function() {
			return Object.keys($scope.toastPosition)
			.filter(function(pos) { return $scope.toastPosition[pos]; })
			.join(' ');
		};

		// Remove existing Project
		$scope.remove = function(project) {
			if (project) {
				project.$remove();

				for (var i in $scope.projects) {
					if ($scope.projects [i] === project) {
						$scope.projects.splice(i, 1);
					}
				}
			} else {
				$scope.project.$remove(function() {
					$location.path('projects');
				});
			}
		};

		// Update existing Project
		$scope.update = function() {
			var project = $scope.project;

			project.$update(function() {
				$location.path('projects/' + project._id);
			}, function(errorResponse) {
				$scope.error = errorResponse.data.message;
			});
		};

		// Find a list of Projects
		$scope.find = function() {
			$scope.projects = Projects.query();
		};

		// Find existing Project
		$scope.findOne = function() {
			$scope.project = Projects.get({
				projectId: $stateParams.projectId
			});
		};

		$scope.updateProjects = function() {
			$scope.projects = Projects.query();
		};

		$scope.querySearch = function(query) {
			//console.log(query);
			var results = query ? $scope.projects.filter(createFilterFor(query)) : $scope.projects, deferred;
			return results;
		};

		$scope.searchTextChange = function(text) {
			console.log('Text changed to ' + text);
		};

		$scope.selectedItemChange = function(item) {
			console.log(item);
			$scope.goTo('/projects/' + item._id + '/edit');
		};

		var createFilterFor = function(query) {
			var lowercaseQuery = angular.lowercase(query);
			return function filterFn(item) {
				//console.log(item);
				var name = angular.lowercase(item.name);
				return (name.indexOf(lowercaseQuery) === 0);
			};
		};

		$scope.newSubItem = function(scope) {
			// console.log(scope.project.users);
			var nodeData = scope.$modelValue;
			// console.log(nodeData);
			var estimationsArr = [];
			for (var i in scope.project.users) {
				// console.log(i);
				estimationsArr.push(null);
			}
			nodeData.nodes.push({
				id: nodeData.id * 10 + nodeData.nodes.length,
				title: nodeData.title + '.' + (nodeData.nodes.length + 1),
				nodes: [],
				collapsed : false,
				estimations : estimationsArr
			});
		};

		$scope.collapseAll = function() {
			$scope.$broadcast('collapseAll');
		};

		$scope.expandAll = function() {
			$scope.$broadcast('expandAll');
		};

		$scope.undoToolTip = function(node, removeNode, newSubItem) {
			//debugger;
			var tree = $.extend(true, [], $scope.project.children);
			removeNode(node);
			var toast = $mdToast.simple()
				.content('Node deleted')
				.action('UNDO')
				.highlightAction(false)
				.position($scope.getToastPosition());
			$mdToast.show(toast).then(function() {
				$scope.project.children = $.extend(true, [], tree);
			});
		};

		$scope.saveProject = function() {
			$scope.project.$update(function(response) {
				$mdToast.show(
					$mdToast.simple()
					.content('Project saved')
					.position($scope.getToastPosition())
					.hideDelay(3000)
				);
			}, function(errorResponse) {
				$scope.error = errorResponse.data.message;
			});
		};

		function DialogController($scope, $mdDialog) {
			$scope.hide = function() {
				$mdDialog.hide();
			};
			$scope.cancel = function() {
				$mdDialog.cancel();
			};
		}

		$scope.showDescriptionDialog = function(ev, node) {
			$scope.currentNode = node;

			$scope.setCurrentNode(node, function() {
				var newScope = $scope.$new();

				$mdDialog.show({
					controller: DialogController,
					templateUrl: 'modules/projects/views/description.dialog.client.view.html',
					parent: angular.element(document.body),
					targetEvent: ev,
					scope: newScope
				});
			});
		};

		$scope.updateLocalTree = function(scope) {
			var user = Authentication.user.firstName + ' ' + Authentication.user.lastName;
			console.log('Curent user name: ' + user);

			console.log($scope.project.children[0].estimations);

			var count = 0;
			var found = false;

			console.log(scope.project.users);
			// console.log(scope.project);

			for (var u in scope.project.users) {
				if (scope.project.users[u] === user) {
					found = true;
					count = u;
					break;
				}
			}

			// console.log('User number: ' + count);

			var currnode = $scope.project.children[0];

			var result;
			$scope.getEstimation(currnode, count, function(res) {
				result = res;
				// console.log(result);
			});
		};

		$scope.getEstimation = function(node, userNum, callback) {
			if (node.nodes.length <= 0) {
				callback(node.estimations[userNum]);
			}
			else {
				node.estimations[userNum] = null;
				for (var i in node.nodes) {
					$scope.getEstimation(node.nodes[i], userNum, function(result) {
						if (node.estimations[userNum] === null) {
							node.estimations[userNum] = parseInt(result);
						}
						else {
							node.estimations[userNum] += parseInt(result);
						}
						callback(parseInt(result));
					});
				}
			}
		};

		$scope.currentNode = undefined;

		$scope.setCurrentNode = function(node, callback) {
			$scope.currentNode = node;

			if (callback !== undefined) {
				callback();
			}
		};

		$scope.selected = [];
		$scope.toggle = function(item, list) {
			var idx = list.indexOf(item);
			if (idx > -1) {
				list.splice(idx, 1);
			} else {
				list.push(item);
			}
		};

		$scope.exists = function(item, list) {
			return list.indexOf(item) > -1;
		};

		$scope.$on('$locationChangeStart', function(event, newUrl, oldUrl) {
			// Appending dialog to document.body to cover sidenav in docs app
			if (!$scope.confirm) {
				event.preventDefault();
				//console.log(newUrl);
				var confirm = $mdDialog.confirm()
				.parent(angular.element(document.body))
				.title('Are you sure you want to leave this page?')
				.content('All unsaved changes will be lost.')
				.ariaLabel('Yes')
				.ok('Yes')
				.cancel('No')
				.targetEvent(event);
				$mdDialog.show(confirm).then(function() {
				newUrl = newUrl.split('#!');
				$scope.goTo(newUrl[1]);
				$scope.confirm = true;
				//$scope.saveProject();
			}, function() {

			});
			}

		});
	}
]);
<|endoftext|>


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

var assert = require('assert'),
    vows = require('vows'),
    databank = require('databank'),
    Step = require('step'),
    URLMaker = require('../lib/urlmaker').URLMaker,
    modelBatch = require('./lib/model').modelBatch,
    Databank = databank.Databank,
    DatabankObject = databank.DatabankObject,
    NoSuchThingError = databank.NoSuchThingError;

var suite = vows.describe('tombstone interface');

var testSchema = {
    pkey: 'typeuuid',
    fields: ['objectType',
             'id',
             'uuid',
             'created',
             'updated',
             'deleted'],
    indices: ['id']
};

var testData = {
    'create': {
        objectType: 'person',
        id: 'http://example.net/api/person/QpL57jiXQt2WzMW4GKfp9A',
        uuid: 'QpL57jiXQt2WzMW4GKfp9A',
        created: '2012-06-07T12:00:00',
        updated: '2012-06-07T12:05:00'
    }
};

var mb = modelBatch('tombstone', 'Tombstone', testSchema, testData);

mb['When we require the tombstone module']
['and we get its Tombstone class export']
['and we create a tombstone instance']
['auto-generated fields are there'] = function(err, created) {
    assert.isString(created.typeuuid);
    assert.isString(created.deleted);
};

suite.addBatch(mb);

suite.addBatch({
    'When we get the Tombstone class again': {
        topic: function() {
            var cb = this.callback;
            // Need this to make IDs

            URLMaker.hostname = "example.net";

            // Dummy databank

            var params = {schema: schema};

            var db = Databank.get('memory', params);

            db.connect({}, function(err) {
                var mod;

                DatabankObject.bank = db;

                mod = require('../lib/model/tombstone').Tombstone;

                cb(null, mod);
            });
        },
        'it works': function(err, Tombstone) {
            assert.isObject(Tombstone);
        },
        'it has the mark() method': function(err, Tombstone) {
            assert.include(Tombstone, 'mark');
            assert.isFunction(Tombstone.mark);
        },
        'it has the lookup() method': function(err, Tombstone) {
            assert.include(Tombstone, 'lookup');
            assert.isFunction(Tombstone.lookup);
        },
        'and we call mark() on an ActivityObject': {
            topic: function(Tombstone) {
                var cb = this.callback,
                    Person = require('../lib/model/person').Person;

                Step(
                    function() {
                        Person.create({displayName: "Abraham Lincoln"}, this);
                    },
                    function(err, person) {
                        if (err) throw err;
                        Tombstone.mark(person, this);
                    },
                    function(err) {
                        cb(err);
                    }
                );
            },
            'it works': function(err) {
                assert.ifError(err);
            }
        },
        'and we call mark() on another kind of object': {
            topic: function(Tombstone) {
                var cb = this.callback,
                    Cls = function() {},
                    inst = new Cls();

                Tombstone.mark(inst, function(err) {
                    if (err) {
                        cb(null);
                    } else {
                        cb(new Error('Unexpected success'));
                    }
                });
            },
            'it works': function(err) {
                assert.ifError(err);
            }
        },
        'and we call mark() on null': {
            topic: function(Tombstone) {
                var cb = this.callback;

                Tombstone.mark(null, function(err) {
                    if (err) {
                        cb(null);
                    } else {
                        cb(new Error('Unexpected success'));
                    }
                });
            },
            'it works': function(err) {
                assert.ifError(err);
            }
        },
        'and we call lookup() on a valid type/uuid pair': {
            topic: function(Tombstone) {
                var cb = this.callback,
                    Person = require('../lib/model/person').Person,
                    person;

                Step(
                    function() {
                        Person.create({displayName: "John MacDonald"}, this);
                    },
                    function(err, results) {
                        if (err) throw err;
                        person = results;
                        Tombstone.mark(person, this);
                    },
                    function(err) {
                        if (err) throw err;
                        Tombstone.lookup(Person.type, person.uuid, this);
                    },
                    function(err, ts) {
                        if (err) {
                            cb(err, null, null);
                        } else {
                            cb(null, ts, person);
                        }
                    }
                );
            },
            'it works': function(err, ts, person) {
                assert.ifError(err);
            },
            'tombstone is correct': function(err, ts, person) {
                assert.isObject(ts);
                assert.equal(ts.objectType, person.objectType);
                assert.equal(ts.id, person.id);
                assert.equal(ts.uuid, person.uuid);
                assert.equal(ts.published, person.published);
                assert.equal(ts.updated, person.updated);
                assert.isString(ts.deleted);
                assert.match(ts.deleted, /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
            }
        },
        'and we call lookup() on a valid type but invalid uuid': {
            topic: function(Tombstone) {
                var cb = this.callback;
                Tombstone.lookup('person', 'NOTAUUID', function(err, ts) {
                    if (err && err instanceof NoSuchThingError) {
                        cb(null);
                    } else if (err) {
                        cb(err);
                    } else {
                        cb(new Error("Unexpected success"));
                    }
                });
            },
            'it fails correctly': function(err) {
                assert.ifError(err);
            }
        },
        'and we call lookup() on a valid uuid but mismatched type': {
            topic: function(Tombstone) {
                var cb = this.callback,
                    Person = require('../lib/model/person').Person,
                    person;

                Step(
                    function() {
                        Person.create({displayName: "Benjamin Disraeli"}, this);
                    },
                    function(err, results) {
                        if (err) throw err;
                        person = results;
                        Tombstone.mark(person, this);
                    },
                    function(err) {
                        if (err) throw err;
                        Tombstone.lookup('audio', person.uuid, this);
                    },
                    function(err, ts) {
                        if (err && err instanceof NoSuchThingError) {
                            cb(null);
                        } else if (err) {
                            cb(err);
                        } else {
                            cb(new Error("Unexpected success"));
                        }
                    }
                );
            },
            'it fails correctly': function(err) {
                assert.ifError(err);
            }
        }
    }
});

suite['export'](module);
<commit_msg>Tombstone in schema<commit_after>// tombstone-test.js
//
// Test the tombstone module
//
// Copyright 2012, StatusNet Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var assert = require('assert'),
    vows = require('vows'),
    databank = require('databank'),
    Step = require('step'),
    URLMaker = require('../lib/urlmaker').URLMaker,
    modelBatch = require('./lib/model').modelBatch,
    schema = require('../lib/schema').schema,
    Databank = databank.Databank,
    DatabankObject = databank.DatabankObject,
    NoSuchThingError = databank.NoSuchThingError;

var suite = vows.describe('tombstone interface');

var testSchema = {
    pkey: 'typeuuid',
    fields: ['objectType',
             'id',
             'uuid',
             'created',
             'updated',
             'deleted'],
    indices: ['id']
};

var testData = {
    'create': {
        objectType: 'person',
        id: 'http://example.net/api/person/QpL57jiXQt2WzMW4GKfp9A',
        uuid: 'QpL57jiXQt2WzMW4GKfp9A',
        created: '2012-06-07T12:00:00',
        updated: '2012-06-07T12:05:00'
    }
};

var mb = modelBatch('tombstone', 'Tombstone', testSchema, testData);

mb['When we require the tombstone module']
['and we get its Tombstone class export']
['and we create a tombstone instance']
['auto-generated fields are there'] = function(err, created) {
    assert.isString(created.typeuuid);
    assert.isString(created.deleted);
};

suite.addBatch(mb);

suite.addBatch({
    'When we get the Tombstone class again': {
        topic: function() {
            var cb = this.callback;
            // Need this to make IDs

            URLMaker.hostname = "example.net";

            // Dummy databank

            var params = {schema: schema};

            var db = Databank.get('memory', params);

            db.connect({}, function(err) {
                var mod;

                DatabankObject.bank = db;

                mod = require('../lib/model/tombstone').Tombstone;

                cb(null, mod);
            });
        },
        'it works': function(err, Tombstone) {
            assert.isObject(Tombstone);
        },
        'it has the mark() method': function(err, Tombstone) {
            assert.include(Tombstone, 'mark');
            assert.isFunction(Tombstone.mark);
        },
        'it has the lookup() method': function(err, Tombstone) {
            assert.include(Tombstone, 'lookup');
            assert.isFunction(Tombstone.lookup);
        },
        'and we call mark() on an ActivityObject': {
            topic: function(Tombstone) {
                var cb = this.callback,
                    Person = require('../lib/model/person').Person;

                Step(
                    function() {
                        Person.create({displayName: "Abraham Lincoln"}, this);
                    },
                    function(err, person) {
                        if (err) throw err;
                        Tombstone.mark(person, this);
                    },
                    function(err) {
                        cb(err);
                    }
                );
            },
            'it works': function(err) {
                assert.ifError(err);
            }
        },
        'and we call mark() on another kind of object': {
            topic: function(Tombstone) {
                var cb = this.callback,
                    Cls = function() {},
                    inst = new Cls();

                Tombstone.mark(inst, function(err) {
                    if (err) {
                        cb(null);
                    } else {
                        cb(new Error('Unexpected success'));
                    }
                });
            },
            'it works': function(err) {
                assert.ifError(err);
            }
        },
        'and we call mark() on null': {
            topic: function(Tombstone) {
                var cb = this.callback;

                Tombstone.mark(null, function(err) {
                    if (err) {
                        cb(null);
                    } else {
                        cb(new Error('Unexpected success'));
                    }
                });
            },
            'it works': function(err) {
                assert.ifError(err);
            }
        },
        'and we call lookup() on a valid type/uuid pair': {
            topic: function(Tombstone) {
                var cb = this.callback,
                    Person = require('../lib/model/person').Person,
                    person;

                Step(
                    function() {
                        Person.create({displayName: "John MacDonald"}, this);
                    },
                    function(err, results) {
                        if (err) throw err;
                        person = results;
                        Tombstone.mark(person, this);
                    },
                    function(err) {
                        if (err) throw err;
                        Tombstone.lookup(Person.type, person.uuid, this);
                    },
                    function(err, ts) {
                        if (err) {
                            cb(err, null, null);
                        } else {
                            cb(null, ts, person);
                        }
                    }
                );
            },
            'it works': function(err, ts, person) {
                assert.ifError(err);
            },
            'tombstone is correct': function(err, ts, person) {
                assert.isObject(ts);
                assert.equal(ts.objectType, person.objectType);
                assert.equal(ts.id, person.id);
                assert.equal(ts.uuid, person.uuid);
                assert.equal(ts.published, person.published);
                assert.equal(ts.updated, person.updated);
                assert.isString(ts.deleted);
                assert.match(ts.deleted, /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
            }
        },
        'and we call lookup() on a valid type but invalid uuid': {
            topic: function(Tombstone) {
                var cb = this.callback;
                Tombstone.lookup('person', 'NOTAUUID', function(err, ts) {
                    if (err && err instanceof NoSuchThingError) {
                        cb(null);
                    } else if (err) {
                        cb(err);
                    } else {
                        cb(new Error("Unexpected success"));
                    }
                });
            },
            'it fails correctly': function(err) {
                assert.ifError(err);
            }
        },
        'and we call lookup() on a valid uuid but mismatched type': {
            topic: function(Tombstone) {
                var cb = this.callback,
                    Person = require('../lib/model/person').Person,
                    person;

                Step(
                    function() {
                        Person.create({displayName: "Benjamin Disraeli"}, this);
                    },
                    function(err, results) {
                        if (err) throw err;
                        person = results;
                        Tombstone.mark(person, this);
                    },
                    function(err) {
                        if (err) throw err;
                        Tombstone.lookup('audio', person.uuid, this);
                    },
                    function(err, ts) {
                        if (err && err instanceof NoSuchThingError) {
                            cb(null);
                        } else if (err) {
                            cb(err);
                        } else {
                            cb(new Error("Unexpected success"));
                        }
                    }
                );
            },
            'it fails correctly': function(err) {
                assert.ifError(err);
            }
        }
    }
});

suite['export'](module);
<|endoftext|>


<commit_before>import {app, BrowserWindow, ipcMain} from 'electron';
import {contains} from 'ramda';

import {Logger} from './logger';
import {SequelizeManager, OPTIONS} from './sequelizeManager';
import {ipcMessageReceive,
        CHANNEL} from './messageHandler';
import {setupHTTP, setupHTTPS, findSelfSignedCert} from './setupServers';
import {setupMenus} from './menus';

if (process.env.NODE_ENV === 'development') {
    require('electron-debug')();
}

const isUnix = () => {
    return (process.platform === 'darwin' || process.platform === 'linux');
};

const isTestRun = () => {
    return (contains('--test-type=webdriver', process.argv.slice(2)));
};

// TODO: issue #65 shell scripts for HTTPS setup may not work on windows atm
const canSetupHTTPS = isUnix() && !isTestRun();

app.on('ready', () => {

    let mainWindow = new BrowserWindow({
        show: false,
        width: 1024,
        height: OPTIONS.large ? 1024 : 728
    });

    const logger = new Logger(OPTIONS, mainWindow, CHANNEL);
    const sequelizeManager = new SequelizeManager(logger);
    /*
        'responseTools' is generic for the things required to handle
        responses from either the app through IPC CHANNEL or from a API
        request
    */
    const responseTools = {sequelizeManager, mainWindow, OPTIONS};

    sequelizeManager.log('Starting Application...', 0);

    mainWindow.loadURL(`file://${__dirname}/../app/app.html`);

    // startup main window
    mainWindow.webContents.on('did-finish-load', () => {

        // show window if it's not running in headless mode and not a test
        if (!OPTIONS.headless && !isTestRun()) {
            sequelizeManager.log('Opening main window.', 2);
            mainWindow.show();
            mainWindow.focus();
        }

        ipcMain.removeAllListeners(CHANNEL);
        // what to do when a message through IPC is received
        ipcMain.on(CHANNEL, ipcMessageReceive(responseTools));
        // what to do when a message through API is received
        setupHTTP(responseTools);

        mainWindow.webContents.send(CHANNEL, {canSetupHTTPS});

        if (canSetupHTTPS) {
            const hasSelfSignedCert = findSelfSignedCert();
            mainWindow.webContents.send(CHANNEL, {hasSelfSignedCert});
            // if user has certificates, setup the HTTPS server right away
            if (hasSelfSignedCert) {
                setupHTTPS(responseTools);
            }
        }

    });

    if (process.env.NODE_ENV === 'development') {
        mainWindow.openDevTools();
    }

    mainWindow.on('closed', () => {
        mainWindow = null;
    });

    setupMenus(app, mainWindow);

});

// close the app when windows is closed
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit();
});
<commit_msg>:wrench: include elasticManager in the responseTools<commit_after>import {app, BrowserWindow, ipcMain} from 'electron';
import {contains} from 'ramda';

import {Logger} from './logger';
import {SequelizeManager, OPTIONS} from './sequelizeManager';
import {ElasticManager} from './elasticManager';
import {ipcMessageReceive,
        CHANNEL} from './messageHandler';
import {setupHTTP, setupHTTPS, findSelfSignedCert} from './setupServers';
import {setupMenus} from './menus';

if (process.env.NODE_ENV === 'development') {
    require('electron-debug')();
}

const isUnix = () => {
    return (process.platform === 'darwin' || process.platform === 'linux');
};

const isTestRun = () => {
    return (contains('--test-type=webdriver', process.argv.slice(2)));
};

// TODO: issue #65 shell scripts for HTTPS setup may not work on windows atm
const canSetupHTTPS = isUnix() && !isTestRun();

app.on('ready', () => {

    let mainWindow = new BrowserWindow({
        show: false,
        width: 1024,
        height: OPTIONS.large ? 1024 : 728
    });

    const logger = new Logger(OPTIONS, mainWindow, CHANNEL);
    const sequelizeManager = new SequelizeManager(logger);
    const elasticManager = new ElasticManager(logger);
    /*
        'responseTools' is generic for the things required to handle
        responses from either the app through IPC CHANNEL or from a API
        request
    */
    const responseTools = {
        sequelizeManager, elasticManager, mainWindow, OPTIONS
    };

    sequelizeManager.log('Starting Application...', 0);

    mainWindow.loadURL(`file://${__dirname}/../app/app.html`);

    // startup main window
    mainWindow.webContents.on('did-finish-load', () => {

        // show window if it's not running in headless mode and not a test
        if (!OPTIONS.headless && !isTestRun()) {
            sequelizeManager.log('Opening main window.', 2);
            mainWindow.show();
            mainWindow.focus();
        }

        ipcMain.removeAllListeners(CHANNEL);
        // what to do when a message through IPC is received
        ipcMain.on(CHANNEL, ipcMessageReceive(responseTools));
        // what to do when a message through API is received
        setupHTTP(responseTools);

        mainWindow.webContents.send(CHANNEL, {canSetupHTTPS});

        if (canSetupHTTPS) {
            const hasSelfSignedCert = findSelfSignedCert();
            mainWindow.webContents.send(CHANNEL, {hasSelfSignedCert});
            // if user has certificates, setup the HTTPS server right away
            if (hasSelfSignedCert) {
                setupHTTPS(responseTools);
            }
        }

    });

    if (process.env.NODE_ENV === 'development') {
        mainWindow.openDevTools();
    }

    mainWindow.on('closed', () => {
        mainWindow = null;
    });

    setupMenus(app, mainWindow);

});

// close the app when windows is closed
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit();
});
<|endoftext|>


<commit_before>/**
 * Created by kintesh on 28/01/15.
 */
var assert = require("assert"),
    translator = require("../lib/translator"),
    fs = require("fs"),
    testSource
    ;

describe("Translator", function() {

    it("Rigorous tests", function() {
        assert.equal(true, true);
        assert.notEqual(true, false);
        assert.notDeepEqual(translator, {});
        assert.notDeepEqual(fs, {});
    });

    it("Test removeComments(source)", function() {
        var input = "Tyche is the /*nick*/name given to a /**hypothetical**/ gas giant located in the " +
                "Solar System's Oort cloud//.",
            output = "Tyche is the name given to a  gas giant located in the Solar System's Oort cloud";
        assert.equal(translator.removeComments(input), output);
    });

    it("read test for source file", function() {
        testSource = fs.readFileSync(__dirname+"/testSource", "utf8");
        assert.notDeepEqual(testSource, undefined);
    });

    it("test for readProperties", function() {
        var input = testSource,
            output = {
                title: 'Sample Slides',
                sub_title: 'The following are sample slides showing different features.',
                author: 'Kintesh Patel',
                date: '28/01/2015'
            };
        assert.deepEqual(translator.readProperties(input), output);
    });

    it("test for extractFrames", function() {
        var input = testSource,
            frameLength = 7,
            frame0 = "# Headers\n---------\n\n# H1 header\n## H2 header\n### H3 header\n#### H4 header\n" +
                "##### H5 header\n###### H6 header\n\n";
        var frames = translator.extractFrames(input);

        assert.equal(frameLength, frames.length);
        assert.deepEqual(frame0, frames[0]);
    });

    it("test for extractMaths", function() {
        var inputFrame = "Inline math equations go in like so: $ \\omega = d\\phi / dt $. Display math should " +
                "get its own line and be put in in double-dollarsigns:\n\n$$ I = \\int \\rho R^{2} dV $$\n\nAnd " +
                "note that you can backslash-escape any punctuation characters.",
            outputFrame = "Inline math equations go in like so: %{MATH0}. Display math should get its own " +
                "line and be put in in double-dollarsigns:\n\n%{MATH1}\n\nAnd note that you can backslash-escape " +
                "any punctuation characters.",
            mathsOutput = [
                { type: 0, value: " \\omega = d\\phi / dt " },
                { type: 1, value: " I = \\int \\rho R^{2} dV " }
            ];
        var output = translator.extractMaths(inputFrame);
        assert.deepEqual(outputFrame, output.frame);
        assert.deepEqual(mathsOutput, output.maths);
    });

    it("test for restoreMaths", function() {
        var inputFrame = "Inline math equations go in like so: %{MATH0}. Display math should get its own " +
                "line and be put in in double-dollarsigns:\n\n%{MATH1}\n\nAnd note that you can backslash-escape " +
                "any punctuation characters.",
            outputFrame = "Inline math equations go in like so:
 \\omega = d\\phi / dt " +
                "
. Display math should get its own line and be put in in double-dollarsigns:\n\n" +
                "
 I = \\int \\rho R^{2} dV
\n\nAnd note that you can " +
                "backslash-escape any punctuation characters.",
            maths = [
                { type: 0, value: " \\omega = d\\phi / dt " },
                { type: 1, value: " I = \\int \\rho R^{2} dV " }
            ],
            replaceInline = "
%{MATH}
",
            replaceBlock = "
%{MATH}
";
        assert.deepEqual(translator.restoreMaths(inputFrame, maths, replaceInline, replaceBlock), outputFrame);
    });

    it("test for replaceControlTags", function() {
        var inputFrame = "Itemized lists look like:\n[visibility:reveal, animation:fade]\n  * this one\n  " +
            "* that one\n  * the other one\n",
            outputFrame = "Itemized lists look like:\n
" +
                "{visibility:\"reveal\",animation:\"fade\"}
\n  * this one\n  * that one\n  * the other one\n";
        assert.deepEqual(translator.replaceControlTags(inputFrame), outputFrame);
    });

    it("test for makeTitleSlide", function(){
        var input = {
                title: 'Sample Slides',
                sub_title: 'The following are sample slides showing different features.',
                author: 'Kintesh Patel',
                date: '28/01/2015'
            },
            output = "
\n
Sample Slides
" +
                "
The following are sample slides showing different features.
" +
                "
Kintesh Patel

28/01/2015
\n
\n";
        assert.deepEqual(translator.makeTitleSlide(input), output)
    });

    it("test for renderMarkdown", function() {
        var input = "I am using __markdown__.",
            output = "
I am using markdown.
\n";
        assert.deepEqual(translator.renderMarkdown(input), output);
    });

    it.skip("test for translate", function() {
        console.log(translator.translate(testSource));
    });

});<commit_msg>updated.<commit_after>/**
 * Created by kintesh on 28/01/15.
 */
var assert = require("assert"),
    translator = require("../lib/translator"),
    fs = require("fs"),
    testSource
    ;

describe("Translator test", function() {

    it("Rigorous tests", function() {
        assert.equal(true, true);
        assert.notEqual(true, false);
        assert.notDeepEqual(translator, {});
        assert.notDeepEqual(fs, {});
    });

    it("Test removeComments(source)", function() {
        var input = "Tyche is the /*nick*/name given to a /**hypothetical**/ gas giant located in the " +
                "Solar System's Oort cloud//.",
            output = "Tyche is the name given to a  gas giant located in the Solar System's Oort cloud";
        assert.equal(translator.removeComments(input), output);
    });

    it("read test for source file", function() {
        testSource = fs.readFileSync(__dirname+"/testSource", "utf8");
        assert.notDeepEqual(testSource, undefined);
    });

    it("test for readProperties", function() {
        var input = testSource,
            output = {
                title: 'Sample Slides',
                sub_title: 'The following are sample slides showing different features.',
                author: 'Kintesh Patel',
                date: '28/01/2015'
            };
        assert.deepEqual(translator.readProperties(input), output);
    });

    it("test for extractFrames", function() {
        var input = testSource,
            frameLength = 7,
            frame0 = "# Headers\n---------\n\n# H1 header\n## H2 header\n### H3 header\n#### H4 header\n" +
                "##### H5 header\n###### H6 header\n\n";
        var frames = translator.extractFrames(input);

        assert.equal(frameLength, frames.length);
        assert.deepEqual(frame0, frames[0]);
    });

    it("test for extractMaths", function() {
        var inputFrame = "Inline math equations go in like so: $ \\omega = d\\phi / dt $. Display math should " +
                "get its own line and be put in in double-dollarsigns:\n\n$$ I = \\int \\rho R^{2} dV $$\n\nAnd " +
                "note that you can backslash-escape any punctuation characters.",
            outputFrame = "Inline math equations go in like so: %{MATH0}. Display math should get its own " +
                "line and be put in in double-dollarsigns:\n\n%{MATH1}\n\nAnd note that you can backslash-escape " +
                "any punctuation characters.",
            mathsOutput = [
                { type: 0, value: " \\omega = d\\phi / dt " },
                { type: 1, value: " I = \\int \\rho R^{2} dV " }
            ];
        var output = translator.extractMaths(inputFrame);
        assert.deepEqual(outputFrame, output.frame);
        assert.deepEqual(mathsOutput, output.maths);
    });

    it("test for restoreMaths", function() {
        var inputFrame = "Inline math equations go in like so: %{MATH0}. Display math should get its own " +
                "line and be put in in double-dollarsigns:\n\n%{MATH1}\n\nAnd note that you can backslash-escape " +
                "any punctuation characters.",
            outputFrame = "Inline math equations go in like so:
 \\omega = d\\phi / dt " +
                "
. Display math should get its own line and be put in in double-dollarsigns:\n\n" +
                "
 I = \\int \\rho R^{2} dV
\n\nAnd note that you can " +
                "backslash-escape any punctuation characters.",
            maths = [
                { type: 0, value: " \\omega = d\\phi / dt " },
                { type: 1, value: " I = \\int \\rho R^{2} dV " }
            ],
            replaceInline = "
%{MATH}
",
            replaceBlock = "
%{MATH}
";
        assert.deepEqual(translator.restoreMaths(inputFrame, maths, replaceInline, replaceBlock), outputFrame);
    });

    it("test for replaceControlTags", function() {
        var inputFrame = "Itemized lists look like:\n[visibility:reveal, animation:fade]\n  * this one\n  " +
            "* that one\n  * the other one\n",
            outputFrame = "Itemized lists look like:\n
" +
                "{visibility:\"reveal\",animation:\"fade\"}
\n  * this one\n  * that one\n  * the other one\n";
        assert.deepEqual(translator.replaceControlTags(inputFrame), outputFrame);
    });

    it("test for makeTitleSlide", function(){
        var input = {
                title: 'Sample Slides',
                sub_title: 'The following are sample slides showing different features.',
                author: 'Kintesh Patel',
                date: '28/01/2015'
            },
            output = "
\n
Sample Slides
" +
                "
The following are sample slides showing different features.
" +
                "
Kintesh Patel

28/01/2015
\n
\n";
        assert.deepEqual(translator.makeTitleSlide(input), output)
    });

    it("test for renderMarkdown", function() {
        var input = "I am using **markdown**.",
            output = "
I am using markdown.
\n";
        assert.deepEqual(translator.renderMarkdown(input), output);
    });

    it.skip("test for translate", function() {
        console.log(translator.translate(testSource));
    });

});<|endoftext|>


<commit_before>var _ = require('lodash');
var assert = require('chai').assert;
var sinon = require('sinon');
var React = require('react/addons');
var Typeahead = require('../src/typeahead');
var TypeaheadOption = require('../src/typeahead/option');
var TypeaheadSelector = require('../src/typeahead/selector');
var Keyevent = require('../src/keyevent');
var TestUtils = React.addons.TestUtils;

function simulateTextInput(component, value) {
  var node = component.refs.entry.getDOMNode();
  node.value = value;
  TestUtils.Simulate.change(node);
  return TestUtils.scryRenderedComponentsWithType(component, TypeaheadOption);
}

var BEATLES = ['John', 'Paul', 'George', 'Ringo'];

var BEATLES_COMPLEX = [
  {
    firstName: 'John',
    lastName: 'Lennon',
    nameWithTitle: 'John Winston Ono Lennon MBE'
  }, {
    firstName: 'Paul',
    lastName: 'McCartney',
    nameWithTitle: 'Sir James Paul McCartney MBE'
  }, {
    firstName: 'George',
    lastName: 'Harrison',
    nameWithTitle: 'George Harrison MBE'
  }, {
    firstName: 'Ringo',
    lastName: 'Starr',
    nameWithTitle: 'Richard Starkey Jr. MBE'
  }
];

describe('Typeahead Component', function() {

  describe('sanity', function() {
    beforeEach(function() {
      this.component = TestUtils.renderIntoDocument(<Typeahead options={
        BEATLES
      } />);
    });

    it('should fuzzy search and render matching results', function() {
      // input value: num of expected results
      var testplan = {
        'o': 3,
        'pa': 1,
        'Grg': 1,
        'Ringo': 1,
        'xxx': 0
      };

      _.each(testplan, function(expected, value) {
        var results = simulateTextInput(this.component, value);
        assert.equal(results.length, expected, 'Text input: ' + value);
      }, this);
    });

    it('does not change the url hash when clicking on options', function() {
      var results = simulateTextInput(this.component, 'o');
      var firstResult = results[0];
      var anchor = TestUtils.findRenderedDOMComponentWithTag(firstResult, 'a');
      var href = anchor.getDOMNode().getAttribute('href');
      assert.notEqual(href, '#');
    });

    describe('keyboard controls', function() {
      it('down arrow + return selects an option', function() {
        var results = simulateTextInput(this.component, 'o');
        var secondItem = results[1].getDOMNode().innerText;
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_RETURN });
        assert.equal(node.value, secondItem); // Poor Ringo
      });

      it('up arrow + return navigates and selects an option', function() {
        var results = simulateTextInput(this.component, 'o');
        var firstItem = results[0].getDOMNode().innerText;
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_UP });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_RETURN });
        assert.equal(node.value, firstItem);
      });

      it('escape clears selection', function() {
        var results = simulateTextInput(this.component, 'o');
        var firstItem = results[0].getDOMNode();
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        assert.ok(firstItem.classList.contains('hover'));
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_ESCAPE });
        assert.notOk(firstItem.classList.contains('hover'));
      });

      it('tab to choose first item', function() {
        var results = simulateTextInput(this.component, 'o');
        var itemText = results[0].getDOMNode().innerText;
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_TAB });
        assert.equal(node.value, itemText);
      });

      it('tab to selected current item', function() {
        var results = simulateTextInput(this.component, 'o');
        var itemText = results[1].getDOMNode().innerText;
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_TAB });
        assert.equal(node.value, itemText);
      });

      it('tab on no selection should not be undefined', function() {
        var results = simulateTextInput(this.component, 'oz');
        assert(results.length == 0);
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_TAB });
        assert.equal("oz", node.value);
      });
    });

  });

  describe('props', function() {
    context('maxVisible', function() {
      it('limits the result set based on the maxVisible option', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          maxVisible={ 1 }
          ></Typeahead>);
        var results = simulateTextInput(component, 'o');
        assert.equal(results.length, 1);
      });
    });

    context('displayOption', function() {
      it('renders simple options verbatim when not specified', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
        />);
        var results = simulateTextInput(component, 'john');
        assert.equal(results[0].getDOMNode().textContent, 'John');
      });

      it('renders custom options when specified as a string', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES_COMPLEX }
          filterOption='firstName'
          displayOption='nameWithTitle'
        />);
        var results = simulateTextInput(component, 'john');
        assert.equal(results[0].getDOMNode().textContent, 'John Winston Ono Lennon MBE');
      });

      it('renders custom options when specified as a function', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES_COMPLEX }
          filterOption='firstName'
          displayOption={ function(o, i) { return i + ' ' + o.firstName + ' ' + o.lastName; } }
        />);
        var results = simulateTextInput(component, 'john');
        assert.equal(results[0].getDOMNode().textContent, '0 John Lennon');
      });
    });

    context('allowCustomValues', function() {

      beforeEach(function() {
        this.sinon = sinon.sandbox.create()
        this.selectSpy = this.sinon.spy();
        this.component = TestUtils.renderIntoDocument(<Typeahead
          options={BEATLES}
          allowCustomValues={3}
          onOptionSelected={this.selectSpy}
          ></Typeahead>);
      });

      afterEach(function() {
        this.sinon.restore();
      })

      it('should not display custom value if input length is less than entered', function() {
        var input = this.component.refs.entry.getDOMNode();
        input.value = "zz";
        TestUtils.Simulate.change(input);
        var results = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        assert.equal(0, results.length);
        assert.equal(false, this.selectSpy.called);
      });

      it('should display custom value if input exceeds props.allowCustomValues', function() {
        var input = this.component.refs.entry.getDOMNode();
        input.value = "ZZZ";
        TestUtils.Simulate.change(input);
        var results = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        assert.equal(1, results.length);
        assert.equal(false, this.selectSpy.called);
      });

      it('should call onOptionSelected when selecting from options', function() {
        var results = simulateTextInput(this.component, 'o');
        var firstItem = results[0].getDOMNode().innerText;
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_UP });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_RETURN });

        assert.equal(true, this.selectSpy.called);
        assert(this.selectSpy.calledWith(firstItem));
      })

      it('should call onOptionSelected when custom value is selected', function() {
        var input = this.component.refs.entry.getDOMNode();
        input.value = "ZZZ";
        TestUtils.Simulate.change(input);
        TestUtils.Simulate.keyDown(input, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(input, { keyCode: Keyevent.DOM_VK_RETURN });

        assert.equal(true, this.selectSpy.called);
        assert(this.selectSpy.calledWith(input.value));
      })

    });

    context('customClasses', function() {

      before(function() {
        var customClasses = {
          input: 'topcoat-text-input',
          results: 'topcoat-list__container',
          listItem: 'topcoat-list__item',
          listAnchor: 'topcoat-list__link',
          hover: 'topcoat-list__item-active'
        };

        this.component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          customClasses={ customClasses }
        ></Typeahead>);

        simulateTextInput(this.component, 'o');
      });

      it('adds a custom class to the typeahead input', function() {
        var input = this.component.refs.entry.getDOMNode();
        assert.isTrue(input.classList.contains('topcoat-text-input'));
      });

      it('adds a custom class to the results component', function() {
        var results = TestUtils.findRenderedComponentWithType(this.component, TypeaheadSelector).getDOMNode();
        assert.isTrue(results.classList.contains('topcoat-list__container'));
      });

      it('adds a custom class to the list items', function() {
        var typeaheadOptions = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        var listItem = typeaheadOptions[1].getDOMNode();
        assert.isTrue(listItem.classList.contains('topcoat-list__item'));
      });

      it('adds a custom class to the option anchor tags', function() {
        var typeaheadOptions = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        var listAnchor = typeaheadOptions[1].refs.anchor.getDOMNode();
        assert.isTrue(listAnchor.classList.contains('topcoat-list__link'));
      });

      it('adds a custom class to the list items when active', function() {
        var typeaheadOptions = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        var node = this.component.refs.entry.getDOMNode();

        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });

        var listItem = typeaheadOptions[0];
        var domListItem = listItem.getDOMNode();

        assert.isTrue(domListItem.classList.contains('topcoat-list__item-active'));
      });
    });

    context('defaultValue', function() {
      it('should perform an initial search if a default value is provided', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          defaultValue={ 'o' }
        />);

        var results = TestUtils.scryRenderedComponentsWithType(component, TypeaheadOption);
        assert.equal(results.length, 3);
      });
    });

    context('onKeyDown', function() {
      it('should bind to key events on the input', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          onKeyDown={ function(e) {
              assert.equal(e.keyCode, 87);
            }
          }
        />);

        var input = component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(input, { keyCode: 87 });
      });
    });

    context('onKeyUp', function() {
      it('should bind to key events on the input', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          onKeyUp={ function(e) {
              assert.equal(e.keyCode, 87);
            }
          }
        />);

        var input = component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyUp(input, { keyCode: 87 });
      });
    });

    context('inputProps', function() {
      it('should forward props to the input element', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          inputProps={{ autoCorrect: 'off' }}
        />);

        var input = component.refs.entry;
        assert.equal(input.props.autoCorrect, 'off');
      });
    });

    context('filterOption', function() {
      var FN_TEST_PLANS = [
        {
          name: 'accepts everything',
          fn: function() { return true; },
          input: 'xxx',
          output: 4
        }, {
          name: 'rejects everything',
          fn: function() { return false; },
          input: 'o',
          output: 0
        }
      ];

      _.each(FN_TEST_PLANS, function(testplan) {
        it('should filter with a custom function that ' + testplan.name, function() {
          var component = TestUtils.renderIntoDocument(<Typeahead
            options={ BEATLES }
            filterOption={ testplan.fn }
          />);

          var results = simulateTextInput(component, testplan.input);
          assert.equal(results.length, testplan.output);
        });
      });

      var STRING_TEST_PLANS = {
        'o': 3,
        'pa': 1,
        'Grg': 1,
        'Ringo': 1,
        'xxx': 0
      };

      it('should filter using fuzzy matching on the provided field name', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES_COMPLEX }
          filterOption='firstName'
          displayOption='firstName'
        />);

        _.each(STRING_TEST_PLANS, function(expected, value) {
          var results = simulateTextInput(component, value);
          assert.equal(results.length, expected, 'Text input: ' + value);
        }, this);
      });
    });

    context('formInputOption', function() {
      var FORM_INPUT_TEST_PLANS = [
        {
          name: 'uses simple options verbatim when not specified',
          props: {
            options: BEATLES
          },
          output: 'John'
        }, {
          name: 'defaults to the display string when not specified',
          props: {
            options: BEATLES_COMPLEX,
            filterOption: 'firstName',
            displayOption: 'nameWithTitle'
          },
          output: 'John Winston Ono Lennon MBE'
        }, {
          name: 'uses custom options when specified as a string',
          props: {
            options: BEATLES_COMPLEX,
            filterOption: 'firstName',
            displayOption: 'nameWithTitle',
            formInputOption: 'lastName'
          },
          output: 'Lennon'
        }, {
          name: 'uses custom optinos when specified as a function',
          props: {
            options: BEATLES_COMPLEX,
            filterOption: 'firstName',
            displayOption: 'nameWithTitle',
            formInputOption: function(o, i) { return o.firstName + ' ' + o.lastName; }
          },
          output: 'John Lennon'
        }
      ];

      _.each(FORM_INPUT_TEST_PLANS, function(testplan) {
        it(testplan.name, function() {
          var component = TestUtils.renderIntoDocument(<Typeahead
            {...testplan.props}
            name='beatles'
          />);
          var results = simulateTextInput(component, 'john');

          var node = component.refs.entry.getDOMNode();
          TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
          TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_RETURN });

          assert.equal(component.state.selection, testplan.output);
        });
      });
    });
  });
});
<commit_msg>added two tests for hover behavior<commit_after>var _ = require('lodash');
var assert = require('chai').assert;
var sinon = require('sinon');
var React = require('react/addons');
var Typeahead = require('../src/typeahead');
var TypeaheadOption = require('../src/typeahead/option');
var TypeaheadSelector = require('../src/typeahead/selector');
var Keyevent = require('../src/keyevent');
var TestUtils = React.addons.TestUtils;

function simulateTextInput(component, value) {
  var node = component.refs.entry.getDOMNode();
  node.value = value;
  TestUtils.Simulate.change(node);
  return TestUtils.scryRenderedComponentsWithType(component, TypeaheadOption);
}

var BEATLES = ['John', 'Paul', 'George', 'Ringo'];

var BEATLES_COMPLEX = [
  {
    firstName: 'John',
    lastName: 'Lennon',
    nameWithTitle: 'John Winston Ono Lennon MBE'
  }, {
    firstName: 'Paul',
    lastName: 'McCartney',
    nameWithTitle: 'Sir James Paul McCartney MBE'
  }, {
    firstName: 'George',
    lastName: 'Harrison',
    nameWithTitle: 'George Harrison MBE'
  }, {
    firstName: 'Ringo',
    lastName: 'Starr',
    nameWithTitle: 'Richard Starkey Jr. MBE'
  }
];

describe('Typeahead Component', function() {

  describe('sanity', function() {
    beforeEach(function() {
      this.component = TestUtils.renderIntoDocument(<Typeahead options={
        BEATLES
      } />);
    });

    it('should fuzzy search and render matching results', function() {
      // input value: num of expected results
      var testplan = {
        'o': 3,
        'pa': 1,
        'Grg': 1,
        'Ringo': 1,
        'xxx': 0
      };

      _.each(testplan, function(expected, value) {
        var results = simulateTextInput(this.component, value);
        assert.equal(results.length, expected, 'Text input: ' + value);
      }, this);
    });

    it('does not change the url hash when clicking on options', function() {
      var results = simulateTextInput(this.component, 'o');
      var firstResult = results[0];
      var anchor = TestUtils.findRenderedDOMComponentWithTag(firstResult, 'a');
      var href = anchor.getDOMNode().getAttribute('href');
      assert.notEqual(href, '#');
    });

    describe('keyboard controls', function() {
      it('down arrow + return selects an option', function() {
        var results = simulateTextInput(this.component, 'o');
        var secondItem = results[1].getDOMNode().innerText;
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_RETURN });
        assert.equal(node.value, secondItem); // Poor Ringo
      });

      it('up arrow + return navigates and selects an option', function() {
        var results = simulateTextInput(this.component, 'o');
        var firstItem = results[0].getDOMNode().innerText;
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_UP });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_RETURN });
        assert.equal(node.value, firstItem);
      });

      it('escape clears selection', function() {
        var results = simulateTextInput(this.component, 'o');
        var firstItem = results[0].getDOMNode();
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        assert.ok(firstItem.classList.contains('hover'));
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_ESCAPE });
        assert.notOk(firstItem.classList.contains('hover'));
      });

      it('tab to choose first item', function() {
        var results = simulateTextInput(this.component, 'o');
        var itemText = results[0].getDOMNode().innerText;
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_TAB });
        assert.equal(node.value, itemText);
      });

      it('tab to selected current item', function() {
        var results = simulateTextInput(this.component, 'o');
        var itemText = results[1].getDOMNode().innerText;
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_TAB });
        assert.equal(node.value, itemText);
      });

      it('tab on no selection should not be undefined', function() {
        var results = simulateTextInput(this.component, 'oz');
        assert(results.length == 0);
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_TAB });
        assert.equal("oz", node.value);
      });

      it('should set hover', function() {
        var results = simulateTextInput(this.component, 'o');
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        assert.equal(true, results[1].props.hover);
      });
    });

  });

  describe('props', function() {
    context('maxVisible', function() {
      it('limits the result set based on the maxVisible option', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          maxVisible={ 1 }
          ></Typeahead>);
        var results = simulateTextInput(component, 'o');
        assert.equal(results.length, 1);
      });
    });

    context('displayOption', function() {
      it('renders simple options verbatim when not specified', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
        />);
        var results = simulateTextInput(component, 'john');
        assert.equal(results[0].getDOMNode().textContent, 'John');
      });

      it('renders custom options when specified as a string', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES_COMPLEX }
          filterOption='firstName'
          displayOption='nameWithTitle'
        />);
        var results = simulateTextInput(component, 'john');
        assert.equal(results[0].getDOMNode().textContent, 'John Winston Ono Lennon MBE');
      });

      it('renders custom options when specified as a function', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES_COMPLEX }
          filterOption='firstName'
          displayOption={ function(o, i) { return i + ' ' + o.firstName + ' ' + o.lastName; } }
        />);
        var results = simulateTextInput(component, 'john');
        assert.equal(results[0].getDOMNode().textContent, '0 John Lennon');
      });
    });

    context('allowCustomValues', function() {

      beforeEach(function() {
        this.sinon = sinon.sandbox.create()
        this.selectSpy = this.sinon.spy();
        this.component = TestUtils.renderIntoDocument(<Typeahead
          options={BEATLES}
          allowCustomValues={3}
          onOptionSelected={this.selectSpy}
          ></Typeahead>);
      });

      afterEach(function() {
        this.sinon.restore();
      })

      it('should not display custom value if input length is less than entered', function() {
        var input = this.component.refs.entry.getDOMNode();
        input.value = "zz";
        TestUtils.Simulate.change(input);
        var results = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        assert.equal(0, results.length);
        assert.equal(false, this.selectSpy.called);
      });

      it('should display custom value if input exceeds props.allowCustomValues', function() {
        var input = this.component.refs.entry.getDOMNode();
        input.value = "ZZZ";
        TestUtils.Simulate.change(input);
        var results = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        assert.equal(1, results.length);
        assert.equal(false, this.selectSpy.called);
      });

      it('should call onOptionSelected when selecting from options', function() {
        var results = simulateTextInput(this.component, 'o');
        var firstItem = results[0].getDOMNode().innerText;
        var node = this.component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_UP });
        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_RETURN });

        assert.equal(true, this.selectSpy.called);
        assert(this.selectSpy.calledWith(firstItem));
      })

      it('should call onOptionSelected when custom value is selected', function() {
        var input = this.component.refs.entry.getDOMNode();
        input.value = "ZZZ";
        TestUtils.Simulate.change(input);
        TestUtils.Simulate.keyDown(input, { keyCode: Keyevent.DOM_VK_DOWN });
        TestUtils.Simulate.keyDown(input, { keyCode: Keyevent.DOM_VK_RETURN });
        assert.equal(true, this.selectSpy.called);
        assert(this.selectSpy.calledWith(input.value));
      })

      it('should add hover prop to customValue', function() {
        var input = this.component.refs.entry.getDOMNode();
        input.value = "ZZZ";
        TestUtils.Simulate.change(input);
        var results = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        TestUtils.Simulate.keyDown(input, { keyCode: Keyevent.DOM_VK_DOWN });
        assert.equal(true, results[0].props.hover)
      })

    });

    context('customClasses', function() {

      before(function() {
        var customClasses = {
          input: 'topcoat-text-input',
          results: 'topcoat-list__container',
          listItem: 'topcoat-list__item',
          listAnchor: 'topcoat-list__link',
          hover: 'topcoat-list__item-active'
        };

        this.component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          customClasses={ customClasses }
        ></Typeahead>);

        simulateTextInput(this.component, 'o');
      });

      it('adds a custom class to the typeahead input', function() {
        var input = this.component.refs.entry.getDOMNode();
        assert.isTrue(input.classList.contains('topcoat-text-input'));
      });

      it('adds a custom class to the results component', function() {
        var results = TestUtils.findRenderedComponentWithType(this.component, TypeaheadSelector).getDOMNode();
        assert.isTrue(results.classList.contains('topcoat-list__container'));
      });

      it('adds a custom class to the list items', function() {
        var typeaheadOptions = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        var listItem = typeaheadOptions[1].getDOMNode();
        assert.isTrue(listItem.classList.contains('topcoat-list__item'));
      });

      it('adds a custom class to the option anchor tags', function() {
        var typeaheadOptions = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        var listAnchor = typeaheadOptions[1].refs.anchor.getDOMNode();
        assert.isTrue(listAnchor.classList.contains('topcoat-list__link'));
      });

      it('adds a custom class to the list items when active', function() {
        var typeaheadOptions = TestUtils.scryRenderedComponentsWithType(this.component, TypeaheadOption);
        var node = this.component.refs.entry.getDOMNode();

        TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });

        var listItem = typeaheadOptions[0];
        var domListItem = listItem.getDOMNode();

        assert.isTrue(domListItem.classList.contains('topcoat-list__item-active'));
      });
    });

    context('defaultValue', function() {
      it('should perform an initial search if a default value is provided', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          defaultValue={ 'o' }
        />);

        var results = TestUtils.scryRenderedComponentsWithType(component, TypeaheadOption);
        assert.equal(results.length, 3);
      });
    });

    context('onKeyDown', function() {
      it('should bind to key events on the input', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          onKeyDown={ function(e) {
              assert.equal(e.keyCode, 87);
            }
          }
        />);

        var input = component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyDown(input, { keyCode: 87 });
      });
    });

    context('onKeyUp', function() {
      it('should bind to key events on the input', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          onKeyUp={ function(e) {
              assert.equal(e.keyCode, 87);
            }
          }
        />);

        var input = component.refs.entry.getDOMNode();
        TestUtils.Simulate.keyUp(input, { keyCode: 87 });
      });
    });

    context('inputProps', function() {
      it('should forward props to the input element', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES }
          inputProps={{ autoCorrect: 'off' }}
        />);

        var input = component.refs.entry;
        assert.equal(input.props.autoCorrect, 'off');
      });
    });

    context('filterOption', function() {
      var FN_TEST_PLANS = [
        {
          name: 'accepts everything',
          fn: function() { return true; },
          input: 'xxx',
          output: 4
        }, {
          name: 'rejects everything',
          fn: function() { return false; },
          input: 'o',
          output: 0
        }
      ];

      _.each(FN_TEST_PLANS, function(testplan) {
        it('should filter with a custom function that ' + testplan.name, function() {
          var component = TestUtils.renderIntoDocument(<Typeahead
            options={ BEATLES }
            filterOption={ testplan.fn }
          />);

          var results = simulateTextInput(component, testplan.input);
          assert.equal(results.length, testplan.output);
        });
      });

      var STRING_TEST_PLANS = {
        'o': 3,
        'pa': 1,
        'Grg': 1,
        'Ringo': 1,
        'xxx': 0
      };

      it('should filter using fuzzy matching on the provided field name', function() {
        var component = TestUtils.renderIntoDocument(<Typeahead
          options={ BEATLES_COMPLEX }
          filterOption='firstName'
          displayOption='firstName'
        />);

        _.each(STRING_TEST_PLANS, function(expected, value) {
          var results = simulateTextInput(component, value);
          assert.equal(results.length, expected, 'Text input: ' + value);
        }, this);
      });
    });

    context('formInputOption', function() {
      var FORM_INPUT_TEST_PLANS = [
        {
          name: 'uses simple options verbatim when not specified',
          props: {
            options: BEATLES
          },
          output: 'John'
        }, {
          name: 'defaults to the display string when not specified',
          props: {
            options: BEATLES_COMPLEX,
            filterOption: 'firstName',
            displayOption: 'nameWithTitle'
          },
          output: 'John Winston Ono Lennon MBE'
        }, {
          name: 'uses custom options when specified as a string',
          props: {
            options: BEATLES_COMPLEX,
            filterOption: 'firstName',
            displayOption: 'nameWithTitle',
            formInputOption: 'lastName'
          },
          output: 'Lennon'
        }, {
          name: 'uses custom optinos when specified as a function',
          props: {
            options: BEATLES_COMPLEX,
            filterOption: 'firstName',
            displayOption: 'nameWithTitle',
            formInputOption: function(o, i) { return o.firstName + ' ' + o.lastName; }
          },
          output: 'John Lennon'
        }
      ];

      _.each(FORM_INPUT_TEST_PLANS, function(testplan) {
        it(testplan.name, function() {
          var component = TestUtils.renderIntoDocument(<Typeahead
            {...testplan.props}
            name='beatles'
          />);
          var results = simulateTextInput(component, 'john');

          var node = component.refs.entry.getDOMNode();
          TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_DOWN });
          TestUtils.Simulate.keyDown(node, { keyCode: Keyevent.DOM_VK_RETURN });

          assert.equal(component.state.selection, testplan.output);
        });
      });
    });
  });
});
<|endoftext|>