<commit_before>var DayPlanner = function() {
	var menu;

	var minOpenedItemHeight = 100; // px
	var maxOpenedItemHeight = 300; // px

	var minItemInterval = 1; // min
	var maxItemInterval = 120; // min

	var startTime = "00:00";

	/********
	 * MAIN *
	 ********/

	// set height according to duration (1 minute = 1px)
	var resetItemsHeight = function() {
		var items = getItems();
		for (var i = 0; i < items.length; i++) {
			setItemHeight(items[i], getItemDuration(items[i]));
		}
	};

	var recalculateTimes = function() {
		var items = getItems();

		var previousTime = startTime;
		for (var i = 0; i < items.length; i++) {
			items[i].querySelector(".time").innerHTML = Time.minutesToTime(Time.timeToMinutes(previousTime) + getItemDuration(items[i]));
			previousTime = Time.minutesToTime(getItemDuration(items[i]) + Time.timeToMinutes(previousTime));
		}
	};

	var openItem = function(item) {
		resetItemsHeight();
		showMenu(item);
		resizeOpenedItem(getItemDuration(item));
	};

	var resizeOpenedItem = function(minutes) {
		minutes = minutes * 1;
		minutes = Lib.linearConversion(minutes, minItemInterval, maxItemInterval, minOpenedItemHeight, maxOpenedItemHeight);
		setItemHeight(getOpenedItem(), Math.round(minutes));
	};

	var hideAndMove = function(element) {
		document.getElementById("hide").appendChild(element);
	};

	var hide = function(element) {
		element.className += " hidden";
	};

	var show = function(element) {
		element.classList.remove('hidden');
	};

		/*****************
		 * GET FUNCTIONS *
		 *****************/

		var getOpenedItem = function() {
			return getMenu().parentNode;
		};

		var getItemsContainer = function() {
			return document.getElementById("items-container");
		};
		var getItems = function() {
			return getItemsContainer().querySelectorAll(".item");
		};
		var getStartTimeDiv = function() {
			return document.getElementById("start-time");
		};

		var getItemName = function(item) {
			return item.querySelector(".item-name").innerHTML.trim();
		};

		var getItemDuration = function(item) {
			return getItemDurationDiv(item).innerHTML.trim() * 1;
		};
		var getItemDurationDiv = function(item) {
			return item.querySelector(".duration");
		};
		var getItemColor = function(item) {
			return item.style.backgroundColor;
		};

		var getDefaultItemClone = function() {
			var defaultItem = document.getElementById("default-item").children[0];
			defaultItem = defaultItem.cloneNode(true);
			return defaultItem;
		};

		/*****************
		 * SET FUNCTIONS *
		 *****************/

		var setItemDuration = function(item, duration) {
			getItemDurationDiv(item).innerHTML = duration;
		};
		var setItemName = function(item, name) {
			item.querySelector(".item-name").innerHTML = name;
		};
		var setItemColor = function(item, color) {
			item.style.backgroundColor = color;
		};

		var setItemHeight = function(item, height) {
			item.style.height = height + "px";
			// getItemDuration(item).
		};

		/************************
		 * ITEM DELETE / CREATE *
		 ************************/

		var deleteItem = function(item) {
			// item.outerHTML = "";
			item.parentNode.removeChild(item);
		};

		var deleteAllItems = function() {
			hideMenu();

			// moves start-time div so its not deleted
			hideAndMove(getStartTimeDiv());

			// removes all items
			var itemsContainer = getItemsContainer();
			while (itemsContainer.firstChild) {
				itemsContainer.removeChild(itemsContainer.firstChild);
			}
		};

		var createItem = function(where, behind, firstItem, item) {
			var defaultItem;
			if (!item) {
				defaultItem = getDefaultItemClone();
			} else {
				defaultItem = item;
			}

			var newItem;
			if (behind) {
				// adds item behind "where"
				newItem = where.parentNode.insertBefore(defaultItem, where.nextSibling);
			} else {
				// adds item inside "where"
				newItem = where.appendChild(defaultItem);
			}

			if (firstItem) {
				// if its first item in the list, we need to add start-time div
				newItem.appendChild(getStartTimeDiv());
			}

			// add onclick event on newly created item
			newItem.querySelector(".content").onclick = function() {
				openItem(this.parentNode);
			};

			return newItem;
		};

	/********
	 * MENU *
	 ********/

	var getMenu = function() {
		return document.getElementById("menu");
	};

	var showMenu = function(item) {
		item.appendChild(getMenu());

		var itemsContainer = getItemsContainer();
		if (item === itemsContainer.firstChild) {
			hide(document.getElementById("delete-item"));
		} else {
			show(document.getElementById("delete-item"));
		}

		refreshMenu();
	};

	var hideMenu = function() {
		hideAndMove(getMenu());
	};

	var refreshMenu = function() {
		var openedItem = getOpenedItem();

		// refresh change item name input
		document.getElementById("name-input").value = getItemName(openedItem);
		// refresh duration input
		document.getElementById("duration-input").value = getItemDuration(openedItem);
	};

	/***************
	 * SAVE / LOAD *
	 ***************/

	var saveAppState = function() {
		var data = {};
		var items = getItems();

		for (var i = 0; i < items.length; i++) {
			data[i] = {
				"name": getItemName(items[i]),
				"duration": getItemDuration(items[i]),
				"color": getItemColor(items[i])
			};
		}

		Storage.save(data, "data");
	};

	var loadAppState = function() {
		deleteAllItems();

		var items = Storage.load("data");

		if (items) {
			for (var i = 0; i < Object.keys(items).length; i++) {
				var defaultItem = getDefaultItemClone();

				setItemDuration(defaultItem, items[i].duration);
				setItemName(defaultItem, items[i].name);
				setItemColor(defaultItem, items[i].color);

				createItem(getItemsContainer(), false, i === 0 ? true : false, defaultItem);

			}
		} else {
			resetAppState();
		}

		resetItemsHeight();
		recalculateTimes();
	};

	var resetAppState = function() {
		var itemsContainer = getItemsContainer();

		deleteAllItems();

		createItem(itemsContainer, false, true);
		for (var i = 1; i < 5; i++) {
			createItem(itemsContainer, false, false);
		}

		resetItemsHeight();
		recalculateTimes();
	};

	/********
	 * INIT *
	 ********/

	var init = function() {
		// initialize first time in items start/end times
		getStartTimeDiv().innerHTML = startTime;

		loadAppState();

		// initialize menu
		menuInit();

		// reset button
		document.getElementById("reset").onclick = resetAppState;

		// save button
		document.getElementById("save").onclick = saveAppState;

		// load button
		document.getElementById("load").onclick = loadAppState;

	};

	var menuInit = function() {
		menu = document.getElementById('menu');

		// add button init
		var addButton = document.getElementById("add-item");
		addButton.onclick = function() {
			// add default item behind selected item
			newItem = createItem(getOpenedItem(), true, false);

			// opens menu on newly created item
			openItem(newItem);

			// recalculate times
			recalculateTimes();

			saveAppState();
		};

		// delete button init
		var deleteButton = document.getElementById("delete-item");
		deleteButton.onclick = function() {
			var openedItem = getOpenedItem();

			hideMenu();

			// delete current item
			deleteItem(openedItem);

			// recalculate times
			recalculateTimes();

			saveAppState();
		};

		// duration buttons
		var addDuration = function(amount) {
			var durationInput = document.getElementById("duration-input");

			amount = amount * 1 + durationInput.value * 1;
			if (amount < minItemInterval) {
				amount = minItemInterval;
			} else if (amount > maxItemInterval) {
				amount = maxItemInterval;
			}

			setItemDuration(getOpenedItem(), amount);
			durationInput.value = amount;

			resizeOpenedItem(amount);
			recalculateTimes();

			saveAppState();
		};

		var changeDuration = function(amount) {
			if (Lib.isNumber(amount) && amount >= minItemInterval && amount <= maxItemInterval) {

				setItemDuration(getOpenedItem(), Math.round(amount));

				resizeOpenedItem(amount);
				recalculateTimes();

				saveAppState();
			}
		};

		var durationInput = document.getElementById("duration-input");
		durationInput.oninput = function() {
			// It's not quite magic to make onchange fire on all those actions.  <input onchange="doSomething();" onkeypress="this.onchange();" onpaste="this.onchange();" oninput="this.onchange();"> will do well enough for most
			changeDuration(this.value);
		};

		var plusButton = document.getElementById("duration-plus");
		plusButton.onclick = function() {
			addDuration(10);
		};

		var minusButton = document.getElementById("duration-minus");
		minusButton.onclick = function() {
			addDuration(-10);
		};

		// changes name of item
		var nameInput = document.getElementById("name-input");
		nameInput.oninput = function() {
			setItemName(getOpenedItem(), this.value);

			saveAppState();
		};

		//hide menu button
		var hideMenuButton = document.getElementById("hide-menu");
		hideMenuButton.onclick = function() {
			resetItemsHeight();
			hideMenu();
		};

		// color settings
		var colors = document.getElementById("colors").getElementsByTagName("div");
		for (var i = 0; i < colors.length; i++) {
			colors[i].onclick = function() {
				setItemColor(getOpenedItem(), getItemColor(this));

				saveAppState();
			};
		}
	};

	return {
		init: init
	};
}();
<commit_msg>refactoring item name<commit_after>var DayPlanner = function() {
	var menu;

	var minOpenedItemHeight = 100; // px
	var maxOpenedItemHeight = 300; // px

	var minItemInterval = 1; // min
	var maxItemInterval = 120; // min

	var startTime = "00:00";

	/********
	 * MAIN *
	 ********/

	// set height according to duration (1 minute = 1px)
	var resetItemsHeight = function() {
		var items = getItems();
		for (var i = 0; i < items.length; i++) {
			setItemHeight(items[i], getItemDuration(items[i]));
		}
	};

	var recalculateTimes = function() {
		var items = getItems();

		var previousTime = startTime;
		for (var i = 0; i < items.length; i++) {
			items[i].querySelector(".time").innerHTML = Time.minutesToTime(Time.timeToMinutes(previousTime) + getItemDuration(items[i]));
			previousTime = Time.minutesToTime(getItemDuration(items[i]) + Time.timeToMinutes(previousTime));
		}
	};

	var openItem = function(item) {
		resetItemsHeight();
		showMenu(item);
		resizeOpenedItem(getItemDuration(item));
	};

	var resizeOpenedItem = function(minutes) {
		minutes = minutes * 1;
		minutes = Lib.linearConversion(minutes, minItemInterval, maxItemInterval, minOpenedItemHeight, maxOpenedItemHeight);
		setItemHeight(getOpenedItem(), Math.round(minutes));
	};

	var hideAndMove = function(element) {
		document.getElementById("hide").appendChild(element);
	};

	var hide = function(element) {
		element.className += " hidden";
	};

	var show = function(element) {
		element.classList.remove('hidden');
	};

		/*****************
		 * GET FUNCTIONS *
		 *****************/

		var getOpenedItem = function() {
			return getMenu().parentNode;
		};

		var getItemsContainer = function() {
			return document.getElementById("items-container");
		};
		var getItems = function() {
			return getItemsContainer().querySelectorAll(".item");
		};
		var getStartTimeDiv = function() {
			return document.getElementById("start-time");
		};

		var getItemName = function(item) {
			return getItemNameDiv(item).innerHTML.trim();
		};
		var getItemNameDiv = function(item) {
			return item.querySelector(".item-name");
		};
		var getItemDuration = function(item) {
			return getItemDurationDiv(item).innerHTML.trim() * 1;
		};
		var getItemDurationDiv = function(item) {
			return item.querySelector(".duration");
		};
		var getItemColor = function(item) {
			return item.style.backgroundColor;
		};

		var getDefaultItemClone = function() {
			var defaultItem = document.getElementById("default-item").children[0];
			defaultItem = defaultItem.cloneNode(true);
			return defaultItem;
		};

		/*****************
		 * SET FUNCTIONS *
		 *****************/

		var setItemDuration = function(item, duration) {
			getItemDurationDiv(item).innerHTML = duration;
		};
		var setItemName = function(item, name) {
			getItemNameDiv(item).innerHTML = name;
		};
		var setItemColor = function(item, color) {
			item.style.backgroundColor = color;
		};
		var setItemHeight = function(item, height) {
			item.style.height = height + "px";
			// getItemDuration(item).
		};

		/************************
		 * ITEM DELETE / CREATE *
		 ************************/

		var deleteItem = function(item) {
			// item.outerHTML = "";
			item.parentNode.removeChild(item);
		};

		var deleteAllItems = function() {
			hideMenu();

			// moves start-time div so its not deleted
			hideAndMove(getStartTimeDiv());

			// removes all items
			var itemsContainer = getItemsContainer();
			while (itemsContainer.firstChild) {
				itemsContainer.removeChild(itemsContainer.firstChild);
			}
		};

		var createItem = function(where, behind, firstItem, item) {
			var defaultItem;
			if (!item) {
				defaultItem = getDefaultItemClone();
			} else {
				defaultItem = item;
			}

			var newItem;
			if (behind) {
				// adds item behind "where"
				newItem = where.parentNode.insertBefore(defaultItem, where.nextSibling);
			} else {
				// adds item inside "where"
				newItem = where.appendChild(defaultItem);
			}

			if (firstItem) {
				// if its first item in the list, we need to add start-time div
				newItem.appendChild(getStartTimeDiv());
			}

			// add onclick event on newly created item
			newItem.querySelector(".content").onclick = function() {
				openItem(this.parentNode);
			};

			return newItem;
		};

	/********
	 * MENU *
	 ********/

	var getMenu = function() {
		return document.getElementById("menu");
	};

	var showMenu = function(item) {
		item.appendChild(getMenu());

		var itemsContainer = getItemsContainer();
		if (item === itemsContainer.firstChild) {
			hide(document.getElementById("delete-item"));
		} else {
			show(document.getElementById("delete-item"));
		}

		refreshMenu();
	};

	var hideMenu = function() {
		hideAndMove(getMenu());
	};

	var refreshMenu = function() {
		var openedItem = getOpenedItem();

		// refresh change item name input
		document.getElementById("name-input").value = getItemName(openedItem);
		// refresh duration input
		document.getElementById("duration-input").value = getItemDuration(openedItem);
	};

	/***************
	 * SAVE / LOAD *
	 ***************/

	var saveAppState = function() {
		var data = {};
		var items = getItems();

		for (var i = 0; i < items.length; i++) {
			data[i] = {
				"name": getItemName(items[i]),
				"duration": getItemDuration(items[i]),
				"color": getItemColor(items[i])
			};
		}

		Storage.save(data, "data");
	};

	var loadAppState = function() {
		deleteAllItems();

		var items = Storage.load("data");

		if (items) {
			for (var i = 0; i < Object.keys(items).length; i++) {
				var defaultItem = getDefaultItemClone();

				setItemDuration(defaultItem, items[i].duration);
				setItemName(defaultItem, items[i].name);
				setItemColor(defaultItem, items[i].color);

				createItem(getItemsContainer(), false, i === 0 ? true : false, defaultItem);

			}
		} else {
			resetAppState();
		}

		resetItemsHeight();
		recalculateTimes();
	};

	var resetAppState = function() {
		var itemsContainer = getItemsContainer();

		deleteAllItems();

		createItem(itemsContainer, false, true);
		for (var i = 1; i < 5; i++) {
			createItem(itemsContainer, false, false);
		}

		resetItemsHeight();
		recalculateTimes();
	};

	/********
	 * INIT *
	 ********/

	var init = function() {
		// initialize first time in items start/end times
		getStartTimeDiv().innerHTML = startTime;

		loadAppState();

		// initialize menu
		menuInit();

		// reset button
		document.getElementById("reset").onclick = resetAppState;

		// save button
		document.getElementById("save").onclick = saveAppState;

		// load button
		document.getElementById("load").onclick = loadAppState;

	};

	var menuInit = function() {
		menu = document.getElementById('menu');

		// add button init
		var addButton = document.getElementById("add-item");
		addButton.onclick = function() {
			// add default item behind selected item
			newItem = createItem(getOpenedItem(), true, false);

			// opens menu on newly created item
			openItem(newItem);

			// recalculate times
			recalculateTimes();

			saveAppState();
		};

		// delete button init
		var deleteButton = document.getElementById("delete-item");
		deleteButton.onclick = function() {
			var openedItem = getOpenedItem();

			hideMenu();

			// delete current item
			deleteItem(openedItem);

			// recalculate times
			recalculateTimes();

			saveAppState();
		};

		// duration buttons
		var addDuration = function(amount) {
			var durationInput = document.getElementById("duration-input");

			amount = amount * 1 + durationInput.value * 1;
			if (amount < minItemInterval) {
				amount = minItemInterval;
			} else if (amount > maxItemInterval) {
				amount = maxItemInterval;
			}

			setItemDuration(getOpenedItem(), amount);
			durationInput.value = amount;

			resizeOpenedItem(amount);
			recalculateTimes();

			saveAppState();
		};

		var changeDuration = function(amount) {
			if (Lib.isNumber(amount) && amount >= minItemInterval && amount <= maxItemInterval) {

				setItemDuration(getOpenedItem(), Math.round(amount));

				resizeOpenedItem(amount);
				recalculateTimes();

				saveAppState();
			}
		};

		var durationInput = document.getElementById("duration-input");
		durationInput.oninput = function() {
			// It's not quite magic to make onchange fire on all those actions.  <input onchange="doSomething();" onkeypress="this.onchange();" onpaste="this.onchange();" oninput="this.onchange();"> will do well enough for most
			changeDuration(this.value);
		};

		var plusButton = document.getElementById("duration-plus");
		plusButton.onclick = function() {
			addDuration(10);
		};

		var minusButton = document.getElementById("duration-minus");
		minusButton.onclick = function() {
			addDuration(-10);
		};

		// changes name of item
		var nameInput = document.getElementById("name-input");
		nameInput.oninput = function() {
			setItemName(getOpenedItem(), this.value);

			saveAppState();
		};

		//hide menu button
		var hideMenuButton = document.getElementById("hide-menu");
		hideMenuButton.onclick = function() {
			resetItemsHeight();
			hideMenu();
		};

		// color settings
		var colors = document.getElementById("colors").getElementsByTagName("div");
		for (var i = 0; i < colors.length; i++) {
			colors[i].onclick = function() {
				setItemColor(getOpenedItem(), getItemColor(this));

				saveAppState();
			};
		}
	};

	return {
		init: init
	};
}();
<|endoftext|>


<commit_before>/**
 * Created by daniel.irwin on 8/7/16.
 */
module.exports = function(cameras){
    var request = require('request');

    //var badCamera = fs.createReadStream( __dirname + '/nocamera.jpg');

    function getCamera(cameraFinder, cb){

        var theCamera = cameras.filter((camera) => {
            //console.log('cameraFinder', cameraFinder, 'camera', camera);
            var port = camera.port;
            if(typeof cameraFinder.name === 'string'){
                return cameraFinder.name === camera.name;
            }
            if(cameraFinder.port && isNaN(cameraFinder.port)){
                port = parseInt(cameraFinder.port);
            }
            return camera.ip === cameraFinder.ip && camera.port === port;
        });

        if(theCamera && theCamera.length > 0){
            //console.log('found camera', theCamera[0]);
            return cb(undefined, theCamera[0]);
        }
        //console.log('no camera found');
        cb('no camera found');
    }

    function saveProxyStream(camera, stream){
        if(!camera.proxyStream){
            camera.proxyStream = stream;
            stream.on('close', function(){
               camera.proxyStream = null;
            });
            stream.on('end', function(){
                camera.proxyStream = null;
            })
            .on('error', function(err) {
                console.log('proxy error', err);
            });
        }
        return stream;
    }

    function ptzRequestOpts(camera) {
        return {
            auth: {
                user: camera.username,
                pass: camera.password
            },
            gzip : true
        };
    }

    function proxyVideo(camera){
        var url = 'http://' + camera.ip + ':' + camera.port + camera.video;
        if(camera.proxyStream){
            return camera.proxyStream;
        }
        return saveProxyStream(camera, request.get(url, ptzRequestOpts(camera)));
    }

    function proxySnapshot(camera){
        var url = 'http://' + camera.ip + ':' + camera.port + camera.snapshot;
        return request.get(url, ptzRequestOpts(camera));
    }

    function proxyAudio(camera){
        //http://192.168.1.108:5182/audio.cgi
        var url = 'http://' + camera.ip + ':' + camera.port + camera.audio;
        return request.get(url, ptzRequestOpts(camera));
    }

    function ptz(camera, action){

        var url = camera.ptz[action];
        var requestUrl = 'http://' + camera.ip + ':' + camera.port + url;
        return request.get(requestUrl, ptzRequestOpts(camera));
    }

    return {
        getCamera : getCamera,
        proxyVideo : proxyVideo,
        proxyAudio: proxyAudio,
        proxySnapshot : proxySnapshot,
        ptz : ptz
    };
};<commit_msg>finish should kill stream as well<commit_after>/**
 * Created by daniel.irwin on 8/7/16.
 */
module.exports = function(cameras){
    var request = require('request');

    //var badCamera = fs.createReadStream( __dirname + '/nocamera.jpg');

    function getCamera(cameraFinder, cb){

        var theCamera = cameras.filter((camera) => {
            //console.log('cameraFinder', cameraFinder, 'camera', camera);
            var port = camera.port;
            if(typeof cameraFinder.name === 'string'){
                return cameraFinder.name === camera.name;
            }
            if(cameraFinder.port && isNaN(cameraFinder.port)){
                port = parseInt(cameraFinder.port);
            }
            return camera.ip === cameraFinder.ip && camera.port === port;
        });

        if(theCamera && theCamera.length > 0){
            //console.log('found camera', theCamera[0]);
            return cb(undefined, theCamera[0]);
        }
        //console.log('no camera found');
        cb('no camera found');
    }

    function saveProxyStream(camera, stream){
        if(!camera.proxyStream){
            camera.proxyStream = stream;
            stream.on('close', function(){
               camera.proxyStream = null;
            });
            stream.on('end', function(){
                camera.proxyStream = null;
            });
            stream.on('finish', function(){
                camera.proxyStream = null
            });
            stream.on('error', function(err) {
                console.log('proxy error', err);
            });
        }
        return stream;
    }

    function ptzRequestOpts(camera) {
        return {
            auth: {
                user: camera.username,
                pass: camera.password
            },
            gzip : true
        };
    }

    function proxyVideo(camera){
        var url = 'http://' + camera.ip + ':' + camera.port + camera.video;
        if(camera.proxyStream){
            return camera.proxyStream;
        }
        return saveProxyStream(camera, request.get(url, ptzRequestOpts(camera)));
    }

    function proxySnapshot(camera){
        var url = 'http://' + camera.ip + ':' + camera.port + camera.snapshot;
        return request.get(url, ptzRequestOpts(camera));
    }

    function proxyAudio(camera){
        //http://192.168.1.108:5182/audio.cgi
        var url = 'http://' + camera.ip + ':' + camera.port + camera.audio;
        return request.get(url, ptzRequestOpts(camera));
    }

    function ptz(camera, action){

        var url = camera.ptz[action];
        var requestUrl = 'http://' + camera.ip + ':' + camera.port + url;
        return request.get(requestUrl, ptzRequestOpts(camera));
    }

    return {
        getCamera : getCamera,
        proxyVideo : proxyVideo,
        proxyAudio: proxyAudio,
        proxySnapshot : proxySnapshot,
        ptz : ptz
    };
};<|endoftext|>


<commit_before>/*
 * mechanic.js UIAutomation Library
 * http://cozykozy.com/pages/mechanicjs
 *
 * Copyright (c) 2012 Jason Kozemczak
 * mechanic.js may be freely distributed under the MIT license.
 *
 * Includes parts of Zepto.js
 * Copyright 2010-2012, Thomas Fuchs
 * Zepto.js may be freely distributed under the MIT license.
 */

var mechanic = (function() {
    // Save a reference to the local target for convenience
    var target = UIATarget.localTarget();

    // Set the default timeout value to 0 to avoid making walking the object tree incredibly slow.
    // Developers can adjust this value by calling $.timeout(duration)
    target.setTimeout(0);

    // This property is meant to suppress excessive logging which prevents instruments from promptly dumping out screenshots.
    this.isVerbose = false

    var app = target.frontMostApp(),
        window = app.mainWindow(),
        emptyArray = [],
        slice = emptyArray.slice

    // Setup a map of UIAElement types to their "shortcut" selectors.
    var typeShortcuts = {
        'UIAActionSheet' : ['actionsheet'],
        'UIAActivityIndicator' : ['activityIndicator'],
        'UIAAlert' : ['alert'],
        'UIAButton' : ['button'],
        'UIACollectionCell' : ['collectionCell'],
        'UIACollectionView' : ['collection'],
        'UIAEditingMenu': ['editingMenu'],
        'UIAElement' : ['\\*'], // TODO: sort of a hack
        'UIAImage' : ['image'],
        'UIAKey' : ['key'],
        'UIAKeyboard' : ['keyboard'],
        'UIALink' : ['link'],
        'UIAMapView': ['mapView'],
        'UIAPageIndicator' : ['pageIndicator'],
        'UIAPicker' : ['picker'],
        'UIAPickerWheel' : ['pickerwheel'],
        'UIAPopover' : ['popover'],
        'UIAProgressIndicator' : ['progress'],
        'UIAScrollView' : ['scrollview'],
        'UIASearchBar' : ['searchbar'],
        'UIASecureTextField' : ['secure'],
        'UIASegmentedControl' : ['segmented'],
        'UIASlider' : ['slider'],
        'UIAStaticText' : ['text'],
        'UIAStatusBar' : ['statusbar'],
        'UIASwitch' : ['switch'],
        'UIATabBar' : ['tabbar'],
        'UIATableView' : ['tableview'],
        'UIATableCell' : ['cell', 'tableCell'],
        'UIATableGroup' : ['group'],
        'UIATextField' : ['textfield'],
        'UIATextView' : ['textview'],
        'UIAToolbar' : ['toolbar'],
        'UIAWebView' : ['webview'],
        'UIAWindow' : ['window'],
        'UIANavigationBar': ['navigationBar']
    };

    // Build a RegExp for picking out type selectors.
    var typeSelectorREString = (function() {
        var key;
        var typeSelectorREString = "\\";
        for (key in typeShortcuts) {
            typeSelectorREString += key + "|";
            typeShortcuts[key].forEach(function(shortcut) { typeSelectorREString += shortcut + "|"; });
        }
        return typeSelectorREString.substr(1, typeSelectorREString.length - 2);
    })();

    var patternName = "[^,\\[\\]]+"

    var selectorPatterns = {
      simple:          (new RegExp("^#("+patternName+")$"))
     ,byType:          (new RegExp("^("+typeSelectorREString+")$"))
     ,byAttr:          (new RegExp("^\\[(\\w+)=("+patternName+")\\]$"))
     ,byTypeAndAttr:   (new RegExp("^("+typeSelectorREString+")\\[(\\w+)=("+patternName+")\\]$"))
     ,children:        (new RegExp("^(.*) > (.*)$"))
     ,descendents:     (new RegExp("^(.+) +(.+)$"))
    }

    var searches = {
      simple:          function(name)         { return this.getElementsByName(name)          }
     ,byType:          function(type)         { return this.getElementsByType(type)          }
     ,byAttr:          function(attr,value)   { return this.getElementsByAttr(attr,value)    }
     ,byTypeAndAttr:   function(type,a,v)     { return $(type, this).filter('['+a+'='+v+']') }
     ,children:        function(parent,child) { return $(parent, this).children().filter(child) }
     ,descendents:     function(parent,child) { return $(child, $(parent, this))             }
    }

    var filters = {
       simple:        function(name)      { return this.name() == name                       }
      ,byType:        function(type)      { return this.isType(type)                         }
      ,byAttr:        function(attr,value){ return this[attr] && this[attr]() == value       }
      ,byTypeAndAttr: function(type,a,v ) { return this.isType(type) && this[a]() == v  }
    }

    function Z(dom, selector){
        dom = dom || emptyArray;
        dom.__proto__ = Z.prototype;
        dom.selector = selector || '';
        if (dom === emptyArray) {
            UIALogger.logWarning("element " + selector + " have not been found");
        }
        return dom;
    }

    function $(selector, context) {
        if (!selector) return Z();
        if (context !== undefined) return $(context).find(selector);
        else if (selector instanceof Z) return selector;
        else {
            var dom;
            if (isA(selector)) dom = compact(selector);
            else if (selector instanceof UIAElement) dom = [selector];
            else dom = $$(app, selector);
            return Z(dom, selector);
        }
    }

    $.qsa = $$ = function(element, selector) {
        var ret = [],
            groups = selector.split(/ *, */),
            matches
        $.each(groups, function() {
          for (type in searches) {
            if (matches = this.match(selectorPatterns[type])) {
              matches.shift()
              ret = ret.concat($(searches[type].apply(element, matches)))
              break
            }
          }
        })
        return $(ret)
    };

    // Add functions to UIAElement to make object graph searching easier.
    UIAElement.prototype.getElementsByName = function(name) {
        return this.getElementsByAttr('name', name)
    };

    UIAElement.prototype.getElementsByAttr = function(attr, value) {
        return $.map(this.elements(), function(el) {
            var matches = el.getElementsByAttr(attr, value),
                val = el[attr]
            if (typeof val == 'function') val = val.apply(el)
            if (typeof val != 'undefined' && val == value)
              matches.push(el)
            return matches
        })
    }
    UIAElement.prototype.getElementsByType = function(type) {
        return $.map(this.elements(), function(el) {
            var matches = el.getElementsByType(type);
            if (el.isType(type)) matches.unshift(el);
            return matches;
        });
    };
    UIAElement.prototype.isType = function(type) {
        var thisType = this.toString().split(" ")[1];
        thisType = thisType.substr(0, thisType.length - 1);
        if (type === thisType) return true;
        else if (typeShortcuts[thisType] !== undefined && typeShortcuts[thisType].indexOf(type) >= 0) return true;
        else if (type === '*' || type === 'UIAElement') return true;
        else return false;
    };

    function isF(value) { return ({}).toString.call(value) == "[object Function]"; }
    function isO(value) { return value instanceof Object; }
    function isA(value) { return value instanceof Array; }
    function likeArray(obj) { return typeof obj.length == 'number'; }

    function compact(array) { return array.filter(function(item){ return item !== undefined && item !== null; }); }
    function flatten(array) { return array.length > 0 ? [].concat.apply([], array) : array; }

    function uniq(array) { return array.filter(function(item,index,array){ return array.indexOf(item) == index; }); }

    function filtered(elements, selector) {
        return selector === undefined ? $(elements) : $(elements).filter(selector);
    }

    $.extend = function(target){
        var key;
        slice.call(arguments, 1).forEach(function(source) {
            for (key in source) target[key] = source[key];
        });
        return target;
    };

    $.inArray = function(elem, array, i) {
        return emptyArray.indexOf.call(array, elem, i);
    };

    $.map = function(elements, callback) {
        var value, values = [], i, key;
        if (likeArray(elements)) {
            for (i = 0; i < elements.length; i++) {
                value = callback(elements[i], i);
                if (value != null) values.push(value);
            }
        } else {
            for (key in elements) {
                value = callback(elements[key], key);
                if (value != null) values.push(value);
            }
        }
        return flatten(values);
    };

    $.each = function(elements, callback) {
        var i, key;
        if (likeArray(elements)) {
            for(i = 0; i < elements.length; i++) {
                if(callback.call(elements[i], i, elements[i]) === false) return elements;
            }
        } else {
            for(key in elements) {
                if(callback.call(elements[key], key, elements[key]) === false) return elements;
            }
        }
        return elements;
    };

    $.fn = {
        forEach: emptyArray.forEach,
        reduce: emptyArray.reduce,
        push: emptyArray.push,
        indexOf: emptyArray.indexOf,
        concat: emptyArray.concat,
        map: function(fn){
            return $.map(this, function(el, i){ return fn.call(el, i, el); });
        },
        slice: function(){
            return $(slice.apply(this, arguments));
        },
        get: function(idx){ return idx === undefined ? slice.call(this) : this[idx]; },
        size: function(){ return this.length; },
        each: function(callback) {
            this.forEach(function(el, idx){ callback.call(el, idx, el); });
            return this;
        },
        filter: function(selector) {
          var matches
          for (type in filters) {
            if (matches = selector.match(selectorPatterns[type])) {
              matches.shift() // remove the original string, we only want the capture groups
              return $.map(this, function(e) {
                return filters[type].apply(e, matches) ? e : null
              })
            }
          }
        },
        end: function(){
            return this.prevObject || $();
        },
        andSelf:function(){
            return this.add(this.prevObject || $());
        },
        add:function(selector,context){
            return $(uniq(this.concat($(selector,context))));
        },
        is: function(selector){
            return this.length > 0 && $(this[0]).filter(selector).length > 0;
        },
        not: function(selector){
            var nodes=[];
            if (isF(selector) && selector.call !== undefined)
                this.each(function(idx){
                    if (!selector.call(this,idx)) nodes.push(this);
                });
            else {
                var excludes = typeof selector == 'string' ? this.filter(selector) :
                        (likeArray(selector) && isF(selector.item)) ? slice.call(selector) : $(selector);
                this.forEach(function(el){
                    if (excludes.indexOf(el) < 0) nodes.push(el);
                });
            }
            return $(nodes);
        },
        eq: function(idx){
            return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1);
        },
        first: function(){ var el = this[0]; return el && !isO(el) ? el : $(el); },
        last: function(){ var el = this[this.length - 1]; return el && !isO(el) ? el : $(el); },
        find: function(selector) {
            var result;
            if (this.length == 1) result = $$(this[0], selector);
            else result = this.map(function(){ return $$(this, selector); });
            return $(result);
        },
        predicate: function(predicate) {
            return this.map(function(el, idx) {
                if (typeof predicate == 'string') return el.withPredicate(predicate);
                else return null;
            });
        },
        valueForKey: function(key, value) {
            var result = this.map(function(idx, el) {
                if (key in el && el[key]() == value) {
                    return el;
                }
                return null;
            });
            return $(result);
        },
        valueInKey: function(key, val) {
            var result = this.map(function(idx, el) {
                if (key in el) {
                    var elKey = el[key]();
                    if (elKey === null) {
                        return null;
                    }
                    // make this a case insensitive search
                    elKey = elKey.toString().toLowerCase();
                    val = val.toString().toLowerCase();

                    if (elKey.indexOf(val) !== -1) {
                        return el;
                    }
                }
                return null;
            });
            return $(result);
        },
        closest: function(selector, context) {
            var el = this[0], candidates = $$(context || app, selector);
            if (!candidates.length) el = null;
            while (el && candidates.indexOf(el) < 0)
                el = el !== context && el !== app && el.parent();
            return $(el);
        },
        ancestry: function(selector) {
            var ancestors = [], elements = this;
            while (elements.length > 0)
                elements = $.map(elements, function(node){
                    if ((node = node.parent()) && !node.isType('UIAApplication') && ancestors.indexOf(node) < 0) {
                        ancestors.push(node);
                        return node;
                    }
                });
            return filtered(ancestors, selector);
        },
        parent: function(selector) {
            return filtered(uniq(this.map(function() { return this.parent(); })), selector);
        },
        children: function(selector) {
            return filtered(this.map(function(){ return slice.call(this.elements()); }), selector);
        },
        siblings: function(selector) {
            return filtered(this.map(function(i, el) {
                return slice.call(el.parent().elements()).filter(function(child){ return child!==el; });
            }), selector);
        },
        next: function(selector) {
            return filtered(this.map(function() {
                var els = this.parent().elements().toArray();
                return els[els.indexOf(this) + 1];
            }), selector);
        },
        prev: function(selector) {
            return filtered(this.map(function() {
                var els = this.parent().elements().toArray();
                return els[els.indexOf(this) - 1];
            }), selector);
        },
        index: function(element) {
            return element ? this.indexOf($(element)[0]) : this.parent().elements().toArray().indexOf(this[0]);
        },
        pluck: function(property) {
            return this.map(function() {
                if (typeof this[property] == 'function') return this[property]();
                else return this[property];
            });
        }
    };

    'filter,add,not,eq,first,last,find,closest,parents,parent,children,siblings'.split(',').forEach(function(property) {
        var fn = $.fn[property];
        $.fn[property] = function() {
            var ret = fn.apply(this, arguments);
            ret.prevObject = this;
            return ret;
        };
    });

    Z.prototype = $.fn;
    return $;
})();

var $ = $ || mechanic;  // expose $ shortcut
<commit_msg>fix crash with Xcode 5 and extra automatic properties<commit_after>/*
 * mechanic.js UIAutomation Library
 * http://cozykozy.com/pages/mechanicjs
 *
 * Copyright (c) 2012 Jason Kozemczak
 * mechanic.js may be freely distributed under the MIT license.
 *
 * Includes parts of Zepto.js
 * Copyright 2010-2012, Thomas Fuchs
 * Zepto.js may be freely distributed under the MIT license.
 */

var mechanic = (function() {
    // Save a reference to the local target for convenience
    var target = UIATarget.localTarget();

    // Set the default timeout value to 0 to avoid making walking the object tree incredibly slow.
    // Developers can adjust this value by calling $.timeout(duration)
    target.setTimeout(0);

    // This property is meant to suppress excessive logging which prevents instruments from promptly dumping out screenshots.
    this.isVerbose = false

    var app = target.frontMostApp(),
        window = app.mainWindow(),
        emptyArray = [],
        slice = emptyArray.slice

    // Setup a map of UIAElement types to their "shortcut" selectors.
    var typeShortcuts = {
        'UIAActionSheet' : ['actionsheet'],
        'UIAActivityIndicator' : ['activityIndicator'],
        'UIAAlert' : ['alert'],
        'UIAButton' : ['button'],
        'UIACollectionCell' : ['collectionCell'],
        'UIACollectionView' : ['collection'],
        'UIAEditingMenu': ['editingMenu'],
        'UIAElement' : ['\\*'], // TODO: sort of a hack
        'UIAImage' : ['image'],
        'UIAKey' : ['key'],
        'UIAKeyboard' : ['keyboard'],
        'UIALink' : ['link'],
        'UIAMapView': ['mapView'],
        'UIAPageIndicator' : ['pageIndicator'],
        'UIAPicker' : ['picker'],
        'UIAPickerWheel' : ['pickerwheel'],
        'UIAPopover' : ['popover'],
        'UIAProgressIndicator' : ['progress'],
        'UIAScrollView' : ['scrollview'],
        'UIASearchBar' : ['searchbar'],
        'UIASecureTextField' : ['secure'],
        'UIASegmentedControl' : ['segmented'],
        'UIASlider' : ['slider'],
        'UIAStaticText' : ['text'],
        'UIAStatusBar' : ['statusbar'],
        'UIASwitch' : ['switch'],
        'UIATabBar' : ['tabbar'],
        'UIATableView' : ['tableview'],
        'UIATableCell' : ['cell', 'tableCell'],
        'UIATableGroup' : ['group'],
        'UIATextField' : ['textfield'],
        'UIATextView' : ['textview'],
        'UIAToolbar' : ['toolbar'],
        'UIAWebView' : ['webview'],
        'UIAWindow' : ['window'],
        'UIANavigationBar': ['navigationBar']
    };

    // Build a RegExp for picking out type selectors.
    var typeSelectorREString = (function() {
        var key;
        var typeSelectorREString = "\\";
        for (key in typeShortcuts) {
            // Instruments' javascript runtime (Xcode 5) automatically adds
            // extra keys which are not in the shortcut list above, skip them
            if (Array.isArray(typeShortcuts[key])) {
                typeSelectorREString += key + "|";
                typeShortcuts[key].forEach(function(shortcut) { typeSelectorREString += shortcut + "|"; });
            }
        }
        return typeSelectorREString.substr(1, typeSelectorREString.length - 2);
    })();

    var patternName = "[^,\\[\\]]+"

    var selectorPatterns = {
      simple:          (new RegExp("^#("+patternName+")$"))
     ,byType:          (new RegExp("^("+typeSelectorREString+")$"))
     ,byAttr:          (new RegExp("^\\[(\\w+)=("+patternName+")\\]$"))
     ,byTypeAndAttr:   (new RegExp("^("+typeSelectorREString+")\\[(\\w+)=("+patternName+")\\]$"))
     ,children:        (new RegExp("^(.*) > (.*)$"))
     ,descendents:     (new RegExp("^(.+) +(.+)$"))
    }

    var searches = {
      simple:          function(name)         { return this.getElementsByName(name)          }
     ,byType:          function(type)         { return this.getElementsByType(type)          }
     ,byAttr:          function(attr,value)   { return this.getElementsByAttr(attr,value)    }
     ,byTypeAndAttr:   function(type,a,v)     { return $(type, this).filter('['+a+'='+v+']') }
     ,children:        function(parent,child) { return $(parent, this).children().filter(child) }
     ,descendents:     function(parent,child) { return $(child, $(parent, this))             }
    }

    var filters = {
       simple:        function(name)      { return this.name() == name                       }
      ,byType:        function(type)      { return this.isType(type)                         }
      ,byAttr:        function(attr,value){ return this[attr] && this[attr]() == value       }
      ,byTypeAndAttr: function(type,a,v ) { return this.isType(type) && this[a]() == v  }
    }

    function Z(dom, selector){
        dom = dom || emptyArray;
        dom.__proto__ = Z.prototype;
        dom.selector = selector || '';
        if (dom === emptyArray) {
            UIALogger.logWarning("element " + selector + " have not been found");
        }
        return dom;
    }

    function $(selector, context) {
        if (!selector) return Z();
        if (context !== undefined) return $(context).find(selector);
        else if (selector instanceof Z) return selector;
        else {
            var dom;
            if (isA(selector)) dom = compact(selector);
            else if (selector instanceof UIAElement) dom = [selector];
            else dom = $$(app, selector);
            return Z(dom, selector);
        }
    }

    $.qsa = $$ = function(element, selector) {
        var ret = [],
            groups = selector.split(/ *, */),
            matches
        $.each(groups, function() {
          for (type in searches) {
            if (matches = this.match(selectorPatterns[type])) {
              matches.shift()
              ret = ret.concat($(searches[type].apply(element, matches)))
              break
            }
          }
        })
        return $(ret)
    };

    // Add functions to UIAElement to make object graph searching easier.
    UIAElement.prototype.getElementsByName = function(name) {
        return this.getElementsByAttr('name', name)
    };

    UIAElement.prototype.getElementsByAttr = function(attr, value) {
        return $.map(this.elements(), function(el) {
            var matches = el.getElementsByAttr(attr, value),
                val = el[attr]
            if (typeof val == 'function') val = val.apply(el)
            if (typeof val != 'undefined' && val == value)
              matches.push(el)
            return matches
        })
    }
    UIAElement.prototype.getElementsByType = function(type) {
        return $.map(this.elements(), function(el) {
            var matches = el.getElementsByType(type);
            if (el.isType(type)) matches.unshift(el);
            return matches;
        });
    };
    UIAElement.prototype.isType = function(type) {
        var thisType = this.toString().split(" ")[1];
        thisType = thisType.substr(0, thisType.length - 1);
        if (type === thisType) return true;
        else if (typeShortcuts[thisType] !== undefined && typeShortcuts[thisType].indexOf(type) >= 0) return true;
        else if (type === '*' || type === 'UIAElement') return true;
        else return false;
    };

    function isF(value) { return ({}).toString.call(value) == "[object Function]"; }
    function isO(value) { return value instanceof Object; }
    function isA(value) { return value instanceof Array; }
    function likeArray(obj) { return typeof obj.length == 'number'; }

    function compact(array) { return array.filter(function(item){ return item !== undefined && item !== null; }); }
    function flatten(array) { return array.length > 0 ? [].concat.apply([], array) : array; }

    function uniq(array) { return array.filter(function(item,index,array){ return array.indexOf(item) == index; }); }

    function filtered(elements, selector) {
        return selector === undefined ? $(elements) : $(elements).filter(selector);
    }

    $.extend = function(target){
        var key;
        slice.call(arguments, 1).forEach(function(source) {
            for (key in source) target[key] = source[key];
        });
        return target;
    };

    $.inArray = function(elem, array, i) {
        return emptyArray.indexOf.call(array, elem, i);
    };

    $.map = function(elements, callback) {
        var value, values = [], i, key;
        if (likeArray(elements)) {
            for (i = 0; i < elements.length; i++) {
                value = callback(elements[i], i);
                if (value != null) values.push(value);
            }
        } else {
            for (key in elements) {
                value = callback(elements[key], key);
                if (value != null) values.push(value);
            }
        }
        return flatten(values);
    };

    $.each = function(elements, callback) {
        var i, key;
        if (likeArray(elements)) {
            for(i = 0; i < elements.length; i++) {
                if(callback.call(elements[i], i, elements[i]) === false) return elements;
            }
        } else {
            for(key in elements) {
                if(callback.call(elements[key], key, elements[key]) === false) return elements;
            }
        }
        return elements;
    };

    $.fn = {
        forEach: emptyArray.forEach,
        reduce: emptyArray.reduce,
        push: emptyArray.push,
        indexOf: emptyArray.indexOf,
        concat: emptyArray.concat,
        map: function(fn){
            return $.map(this, function(el, i){ return fn.call(el, i, el); });
        },
        slice: function(){
            return $(slice.apply(this, arguments));
        },
        get: function(idx){ return idx === undefined ? slice.call(this) : this[idx]; },
        size: function(){ return this.length; },
        each: function(callback) {
            this.forEach(function(el, idx){ callback.call(el, idx, el); });
            return this;
        },
        filter: function(selector) {
          var matches
          for (type in filters) {
            if (matches = selector.match(selectorPatterns[type])) {
              matches.shift() // remove the original string, we only want the capture groups
              return $.map(this, function(e) {
                return filters[type].apply(e, matches) ? e : null
              })
            }
          }
        },
        end: function(){
            return this.prevObject || $();
        },
        andSelf:function(){
            return this.add(this.prevObject || $());
        },
        add:function(selector,context){
            return $(uniq(this.concat($(selector,context))));
        },
        is: function(selector){
            return this.length > 0 && $(this[0]).filter(selector).length > 0;
        },
        not: function(selector){
            var nodes=[];
            if (isF(selector) && selector.call !== undefined)
                this.each(function(idx){
                    if (!selector.call(this,idx)) nodes.push(this);
                });
            else {
                var excludes = typeof selector == 'string' ? this.filter(selector) :
                        (likeArray(selector) && isF(selector.item)) ? slice.call(selector) : $(selector);
                this.forEach(function(el){
                    if (excludes.indexOf(el) < 0) nodes.push(el);
                });
            }
            return $(nodes);
        },
        eq: function(idx){
            return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1);
        },
        first: function(){ var el = this[0]; return el && !isO(el) ? el : $(el); },
        last: function(){ var el = this[this.length - 1]; return el && !isO(el) ? el : $(el); },
        find: function(selector) {
            var result;
            if (this.length == 1) result = $$(this[0], selector);
            else result = this.map(function(){ return $$(this, selector); });
            return $(result);
        },
        predicate: function(predicate) {
            return this.map(function(el, idx) {
                if (typeof predicate == 'string') return el.withPredicate(predicate);
                else return null;
            });
        },
        valueForKey: function(key, value) {
            var result = this.map(function(idx, el) {
                if (key in el && el[key]() == value) {
                    return el;
                }
                return null;
            });
            return $(result);
        },
        valueInKey: function(key, val) {
            var result = this.map(function(idx, el) {
                if (key in el) {
                    var elKey = el[key]();
                    if (elKey === null) {
                        return null;
                    }
                    // make this a case insensitive search
                    elKey = elKey.toString().toLowerCase();
                    val = val.toString().toLowerCase();

                    if (elKey.indexOf(val) !== -1) {
                        return el;
                    }
                }
                return null;
            });
            return $(result);
        },
        closest: function(selector, context) {
            var el = this[0], candidates = $$(context || app, selector);
            if (!candidates.length) el = null;
            while (el && candidates.indexOf(el) < 0)
                el = el !== context && el !== app && el.parent();
            return $(el);
        },
        ancestry: function(selector) {
            var ancestors = [], elements = this;
            while (elements.length > 0)
                elements = $.map(elements, function(node){
                    if ((node = node.parent()) && !node.isType('UIAApplication') && ancestors.indexOf(node) < 0) {
                        ancestors.push(node);
                        return node;
                    }
                });
            return filtered(ancestors, selector);
        },
        parent: function(selector) {
            return filtered(uniq(this.map(function() { return this.parent(); })), selector);
        },
        children: function(selector) {
            return filtered(this.map(function(){ return slice.call(this.elements()); }), selector);
        },
        siblings: function(selector) {
            return filtered(this.map(function(i, el) {
                return slice.call(el.parent().elements()).filter(function(child){ return child!==el; });
            }), selector);
        },
        next: function(selector) {
            return filtered(this.map(function() {
                var els = this.parent().elements().toArray();
                return els[els.indexOf(this) + 1];
            }), selector);
        },
        prev: function(selector) {
            return filtered(this.map(function() {
                var els = this.parent().elements().toArray();
                return els[els.indexOf(this) - 1];
            }), selector);
        },
        index: function(element) {
            return element ? this.indexOf($(element)[0]) : this.parent().elements().toArray().indexOf(this[0]);
        },
        pluck: function(property) {
            return this.map(function() {
                if (typeof this[property] == 'function') return this[property]();
                else return this[property];
            });
        }
    };

    'filter,add,not,eq,first,last,find,closest,parents,parent,children,siblings'.split(',').forEach(function(property) {
        var fn = $.fn[property];
        $.fn[property] = function() {
            var ret = fn.apply(this, arguments);
            ret.prevObject = this;
            return ret;
        };
    });

    Z.prototype = $.fn;
    return $;
})();

var $ = $ || mechanic;  // expose $ shortcut
<|endoftext|>


<commit_before>'use strict';

angular.module('users').controller('AuthenticationController', ['$scope', '$http', '$location', 'Authentication',
	function($scope, $http, $location, Authentication) {
		$scope.authentication = Authentication;

		// If user is signed in then redirect back home
		if ($scope.authentication.user) $location.path('/');

		$scope.signup = function() {
			$http.post('/auth/signup', $scope.credentials).success(function(response) {
				// If successful we assign the response to the global user model
				$scope.authentication.user = response;

				// And redirect to the index page
				$location.path('/');
			}).error(function(response) {
				$scope.error = response.message;
			});
		};

		$scope.signin = function() {
			$http.post('/auth/signin', $scope.credentials).success(function(response) {
				// If successful we assign the response to the global user model
				$scope.authentication.user = response;

				// And redirect to the index page
				$location.path('/');
			}).error(function(response) {
				$scope.error = response.message;
			});
		};
	}
]);<commit_msg>Closes #77 (redirect to Dash after signup/signin)<commit_after>'use strict';

angular.module('users').controller('AuthenticationController', ['$scope', '$http', '$location', 'Authentication',
	function($scope, $http, $location, Authentication) {
		$scope.authentication = Authentication;

		// If user is signed in then redirect back home
		if ($scope.authentication.user) $location.path('/');

		$scope.signup = function() {
			$http.post('/auth/signup', $scope.credentials).success(function(response) {
				// If successful we assign the response to the global user model
				$scope.authentication.user = response;

				// And redirect to the index page
				$location.path('/splashes');
			}).error(function(response) {
				$scope.error = response.message;
			});
		};

		$scope.signin = function() {
			$http.post('/auth/signin', $scope.credentials).success(function(response) {
				// If successful we assign the response to the global user model
				$scope.authentication.user = response;

				// And redirect to the index page
				$location.path('/splashes');
			}).error(function(response) {
				$scope.error = response.message;
			});
		};
	}
]);<|endoftext|>


<commit_before>// Copyright 2013 Traceur Authors.
//
// 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.

'use strict';

var fs = require('fs');
var path = require('path');

var traceur = require('./traceur.js');

var inlineAndCompile = require('./inline-module.js').inlineAndCompile;
var util = require('./file-util.js');
var writeFile = util.writeFile;
var mkdirRecursive = util.mkdirRecursive;
var normalizePath = util.normalizePath;

var ErrorReporter = traceur.util.ErrorReporter;
var TreeWriter = traceur.outputgeneration.TreeWriter;
var SourceMapGenerator = traceur.outputgeneration.SourceMapGenerator;

function getSourceMapFileName(name) {
  return name.replace(/\.js$/, '.map');
}

function writeTreeToFile(tree, filename, useSourceMaps, opt_sourceRoot) {
  var options = null;
  if (useSourceMaps) {
    var sourceMapFilePath = getSourceMapFileName(filename);
    var config = {
      file: path.basename(filename),
      sourceRoot: opt_sourceRoot
    };
    var sourceMapGenerator = new SourceMapGenerator(config);
    options = {sourceMapGenerator: sourceMapGenerator};
  }

  var compiledCode = TreeWriter.write(tree, options);
  if (useSourceMaps) {
    compiledCode += '\n//@ sourceMappingURL=' +
        path.basename(sourceMapFilePath);
  }
  writeFile(filename, compiledCode);
  if (useSourceMaps)
    writeFile(sourceMapFilePath, options.sourceMap);
}

function compileToSingleFile(outputFile, includes, useSourceMaps) {
  var reporter = new ErrorReporter();
  var resolvedOutputFile = path.resolve(outputFile);
  var outputDir = path.dirname(resolvedOutputFile);

  // Resolve includes before changing directory.
  var resolvedIncludes = includes.map(function(include) {
    return path.resolve(include);
  });

  mkdirRecursive(outputDir);
  process.chdir(outputDir);

  // Make includes relative to output dir so that sourcemap paths are correct.
  resolvedIncludes = resolvedIncludes.map(function(include) {
    return normalizePath(path.relative(outputDir, include));
  });

  inlineAndCompile(resolvedIncludes, {}, reporter, function(tree) {
    writeTreeToFile(tree, resolvedOutputFile, useSourceMaps);
    process.exit(0);
  }, function(err) {
    process.exit(1);
  });
}

function compileToDirectory(outputFile, includes, useSourceMaps) {
  var reporter = new ErrorReporter();
  var outputDir = path.resolve(outputFile);

  var current = 0;

  function next() {
    if (current === includes.length)
      process.exit(0);

    inlineAndCompile(includes.slice(current, current + 1), {}, reporter,
        function(tree) {
          var outputFile = path.join(outputDir, includes[current]);
          var sourceRoot = path.relative(path.dirname(outputFile), '.');
          writeTreeToFile(tree, outputFile, useSourceMaps, sourceRoot);
          current++;
          next();
        },
        function(err) {
          process.exit(1);
        });
  }

  next();
}

exports.compileToSingleFile = compileToSingleFile;
exports.compileToDirectory = compileToDirectory;
<commit_msg>Update signal token for sourceURL/Map to //#.<commit_after>// Copyright 2013 Traceur Authors.
//
// 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.

'use strict';

var fs = require('fs');
var path = require('path');

var traceur = require('./traceur.js');

var inlineAndCompile = require('./inline-module.js').inlineAndCompile;
var util = require('./file-util.js');
var writeFile = util.writeFile;
var mkdirRecursive = util.mkdirRecursive;
var normalizePath = util.normalizePath;

var ErrorReporter = traceur.util.ErrorReporter;
var TreeWriter = traceur.outputgeneration.TreeWriter;
var SourceMapGenerator = traceur.outputgeneration.SourceMapGenerator;

function getSourceMapFileName(name) {
  return name.replace(/\.js$/, '.map');
}

function writeTreeToFile(tree, filename, useSourceMaps, opt_sourceRoot) {
  var options = null;
  if (useSourceMaps) {
    var sourceMapFilePath = getSourceMapFileName(filename);
    var config = {
      file: path.basename(filename),
      sourceRoot: opt_sourceRoot
    };
    var sourceMapGenerator = new SourceMapGenerator(config);
    options = {sourceMapGenerator: sourceMapGenerator};
  }

  var compiledCode = TreeWriter.write(tree, options);
  if (useSourceMaps) {
    compiledCode += '\n//# sourceMappingURL=' +
        path.basename(sourceMapFilePath) + '\n';
  }
  writeFile(filename, compiledCode);
  if (useSourceMaps)
    writeFile(sourceMapFilePath, options.sourceMap);
}

function compileToSingleFile(outputFile, includes, useSourceMaps) {
  var reporter = new ErrorReporter();
  var resolvedOutputFile = path.resolve(outputFile);
  var outputDir = path.dirname(resolvedOutputFile);

  // Resolve includes before changing directory.
  var resolvedIncludes = includes.map(function(include) {
    return path.resolve(include);
  });

  mkdirRecursive(outputDir);
  process.chdir(outputDir);

  // Make includes relative to output dir so that sourcemap paths are correct.
  resolvedIncludes = resolvedIncludes.map(function(include) {
    return normalizePath(path.relative(outputDir, include));
  });

  inlineAndCompile(resolvedIncludes, {}, reporter, function(tree) {
    writeTreeToFile(tree, resolvedOutputFile, useSourceMaps);
    process.exit(0);
  }, function(err) {
    process.exit(1);
  });
}

function compileToDirectory(outputFile, includes, useSourceMaps) {
  var reporter = new ErrorReporter();
  var outputDir = path.resolve(outputFile);

  var current = 0;

  function next() {
    if (current === includes.length)
      process.exit(0);

    inlineAndCompile(includes.slice(current, current + 1), {}, reporter,
        function(tree) {
          var outputFile = path.join(outputDir, includes[current]);
          var sourceRoot = path.relative(path.dirname(outputFile), '.');
          writeTreeToFile(tree, outputFile, useSourceMaps, sourceRoot);
          current++;
          next();
        },
        function(err) {
          process.exit(1);
        });
  }

  next();
}

exports.compileToSingleFile = compileToSingleFile;
exports.compileToDirectory = compileToDirectory;
<|endoftext|>


<commit_before>/**
 * GA4 Property Select component tests.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * Internal dependencies
 */
import PropertySelectIncludingGA4 from './PropertySelectIncludingGA4';
import { MODULES_ANALYTICS, ACCOUNT_CREATE } from '../../datastore/constants';
import { MODULES_ANALYTICS_4 } from '../../../analytics-4/datastore/constants';
import * as fixtures from '../../datastore/__fixtures__';
import * as analytics4Fixtures from '../../../analytics-4/datastore/__fixtures__';
import { provideSiteInfo } from '../../../../../../tests/js/utils';
import { fireEvent, act, render } from '../../../../../../tests/js/test-utils';

const {
	createProperty,
	createWebDataStream,
	properties: propertiesGA4,
	webDataStreams,
} = analytics4Fixtures;
const { accounts, properties: propertiesUA, profiles } = fixtures.accountsPropertiesProfiles;
const accountID = createProperty._accountID;
const propertyIDga4 = createWebDataStream._propertyID;
const propertyIDua = propertiesUA[ 0 ].id;

const setupRegistry = ( registry ) => {
	provideSiteInfo( registry );

	const { dispatch } = registry;

	dispatch( MODULES_ANALYTICS ).receiveGetSettings( { accountID } );
	dispatch( MODULES_ANALYTICS_4 ).receiveGetSettings( {} );
	dispatch( MODULES_ANALYTICS ).receiveGetExistingTag( null );

	dispatch( MODULES_ANALYTICS ).receiveGetAccounts( accounts );
	dispatch( MODULES_ANALYTICS ).finishResolution( 'getAccounts', [] );

	dispatch( MODULES_ANALYTICS ).receiveGetProperties( propertiesUA, { accountID } );
	dispatch( MODULES_ANALYTICS ).finishResolution( 'getProperties', [ accountID ] );

	dispatch( MODULES_ANALYTICS_4 ).receiveGetProperties( propertiesGA4, { accountID } );
	dispatch( MODULES_ANALYTICS_4 ).finishResolution( 'getProperties', [ accountID ] );

	dispatch( MODULES_ANALYTICS ).receiveGetProfiles( profiles, { accountID, propertyID: propertyIDua } );
	dispatch( MODULES_ANALYTICS ).finishResolution( 'getProfiles', [ accountID, propertyIDua ] );

	dispatch( MODULES_ANALYTICS_4 ).receiveGetWebDataStreams( webDataStreams, { propertyID: propertyIDga4 } );
	dispatch( MODULES_ANALYTICS_4 ).finishResolution( 'receiveGetWebDataStreams', { propertyID: propertyIDga4 } );
};

const setupEmptyRegistry = ( { dispatch } ) => {
	dispatch( MODULES_ANALYTICS ).receiveGetSettings( {} );
	dispatch( MODULES_ANALYTICS_4 ).receiveGetSettings( {} );
	dispatch( MODULES_ANALYTICS ).setAccountID( accountID );

	dispatch( MODULES_ANALYTICS ).receiveGetAccounts( accounts );
	dispatch( MODULES_ANALYTICS ).finishResolution( 'getAccounts', [] );

	dispatch( MODULES_ANALYTICS ).receiveGetProperties( [], { accountID } );
	dispatch( MODULES_ANALYTICS ).finishResolution( 'getProperties', [ accountID ] );

	dispatch( MODULES_ANALYTICS_4 ).receiveGetProperties( [], { accountID } );
	dispatch( MODULES_ANALYTICS_4 ).finishResolution( 'getProperties', [ accountID ] );
};

describe( 'PropertySelectIncludingGA4IncludingGA4', () => {
	it( 'should render an option for each analytics property of the currently selected account.', async () => {
		const { getAllByRole } = render( <PropertySelectIncludingGA4 />, { setupRegistry } );

		const listItems = getAllByRole( 'menuitem', { hidden: true } );
		// Note: we do length + 1 here because there should also be an item for
		// "Set up a new property".
		expect( listItems ).toHaveLength( propertiesUA.length + propertiesGA4.length + 1 );
	} );

	it( 'should not render in the absence of an valid account ID.', async () => {
		const { container, registry } = render( <PropertySelectIncludingGA4 />, {
			setupRegistry,
		} );

		// A valid accountID is provided, so ensure it is not currently disabled.
		const selectWrapper = container.querySelector( '.googlesitekit-analytics__select-property' );
		const selectedText = container.querySelector( '.mdc-select__selected-text' );
		expect( selectWrapper ).not.toHaveClass( 'mdc-select--disabled' );
		expect( selectedText ).not.toHaveAttribute( 'aria-disabled', 'true' );

		act( () => {
			registry.dispatch( MODULES_ANALYTICS ).setAccountID( ACCOUNT_CREATE );
			registry.dispatch( MODULES_ANALYTICS ).finishResolution( 'getProperties', [ ACCOUNT_CREATE ] );
			registry.dispatch( MODULES_ANALYTICS_4 ).finishResolution( 'getProperties', [ ACCOUNT_CREATE ] );
		} );
		// ACCOUNT_CREATE is an invalid accountID (but valid selection), so ensure the select is not rendered
		expect( container ).toBeEmptyDOMElement();
	} );

	it( 'should render a select box with only an option to create a new property if no properties are available.', async () => {
		const { getAllByRole } = render( <PropertySelectIncludingGA4 />, { setupRegistry: setupEmptyRegistry } );

		const listItems = getAllByRole( 'menuitem', { hidden: true } );
		expect( listItems ).toHaveLength( 1 );
		expect( listItems[ 0 ].textContent ).toMatch( /set up a new property/i );
	} );

	it( 'should change between UA and GA4 properties', async () => {
		const { getAllByRole, container, registry } = render( <PropertySelectIncludingGA4 />, { setupRegistry } );
		const ga4Properties = registry.select( MODULES_ANALYTICS_4 ).getProperties( accountID );
		// the selector getPropertiesIncludingGA4 sorts so this is rendered second in the select
		const ga4TargetProperty = ga4Properties[ 0 ];

		expect( container.querySelector( '.mdc-select__selected-text' ) ).toHaveTextContent( '' );

		fireEvent.click( container.querySelector( '.mdc-floating-label' ) );
		fireEvent.click( getAllByRole( 'menuitem', { hidden: true } )[ 1 ] );

		// The selected property is a GA4 property
		expect( registry.select( MODULES_ANALYTICS ).getPrimaryPropertyType() ).toBe( 'ga4' );
		const newGA4PropertyID = registry.select( MODULES_ANALYTICS_4 ).getPropertyID();
		expect( ga4TargetProperty._id ).toEqual( newGA4PropertyID );

		expect( container.querySelector( '.mdc-select__selected-text' ) )
			.toHaveTextContent( `${ ga4TargetProperty.displayName } (${ ga4TargetProperty._id })` );
		expect( container.querySelector( '.mdc-select__selected-text' ) )
			.toHaveTextContent( 'Test GA4 Property (1000)' );

		// the modules/analytics store's getPropertyID action should be reset
		expect( registry.select( MODULES_ANALYTICS ).getPropertyID() ).toBe( '' );

		// Select a UA property
		const uaProperties = registry.select( MODULES_ANALYTICS ).getProperties( accountID );

		const uaTargetProperty = uaProperties[ 0 ];

		fireEvent.click( container.querySelector( '.mdc-floating-label' ) );
		fireEvent.click( getAllByRole( 'menuitem', { hidden: true } )[ 7 ] );

		expect( registry.select( MODULES_ANALYTICS ).getPrimaryPropertyType() ).toBe( 'ua' );

		const newUAPropertyID = registry.select( MODULES_ANALYTICS ).getPropertyID();

		expect( uaTargetProperty.id ).toEqual( newUAPropertyID );

		expect( container.querySelector( '.mdc-select__selected-text' ) )
			.toHaveTextContent( `${ uaTargetProperty.name } (${ uaTargetProperty.id })` );
		expect( container.querySelector( '.mdc-select__selected-text' ) ).toHaveTextContent( 'wegweg (UA-152925174-1)' );

		expect( registry.select( MODULES_ANALYTICS_4 ).getPropertyID() ).toBe( '' );

		// Select a GA4 property again
		fireEvent.click( container.querySelector( '.mdc-floating-label' ) );
		fireEvent.click( getAllByRole( 'menuitem', { hidden: true } )[ 1 ] );

		expect( container.querySelector( '.mdc-select__selected-text' ) )
			.toHaveTextContent( `${ ga4TargetProperty.displayName } (${ ga4TargetProperty._id })` );
		expect( container.querySelector( '.mdc-select__selected-text' ) )
			.toHaveTextContent( 'Test GA4 Property (1000)' );

		expect( registry.select( MODULES_ANALYTICS ).getPropertyID() ).toBe( '' );
	} );
} );
<commit_msg>Receive account ID.<commit_after>/**
 * GA4 Property Select component tests.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * Internal dependencies
 */
import PropertySelectIncludingGA4 from './PropertySelectIncludingGA4';
import { MODULES_ANALYTICS, ACCOUNT_CREATE } from '../../datastore/constants';
import { MODULES_ANALYTICS_4 } from '../../../analytics-4/datastore/constants';
import * as fixtures from '../../datastore/__fixtures__';
import * as analytics4Fixtures from '../../../analytics-4/datastore/__fixtures__';
import { provideSiteInfo } from '../../../../../../tests/js/utils';
import { fireEvent, act, render } from '../../../../../../tests/js/test-utils';

const {
	createProperty,
	createWebDataStream,
	properties: propertiesGA4,
	webDataStreams,
} = analytics4Fixtures;
const { accounts, properties: propertiesUA, profiles } = fixtures.accountsPropertiesProfiles;
const accountID = createProperty._accountID;
const propertyIDga4 = createWebDataStream._propertyID;
const propertyIDua = propertiesUA[ 0 ].id;

const setupRegistry = ( registry ) => {
	provideSiteInfo( registry );

	const { dispatch } = registry;

	dispatch( MODULES_ANALYTICS ).receiveGetSettings( { accountID } );
	dispatch( MODULES_ANALYTICS_4 ).receiveGetSettings( {} );
	dispatch( MODULES_ANALYTICS ).receiveGetExistingTag( null );

	dispatch( MODULES_ANALYTICS ).receiveGetAccounts( accounts );
	dispatch( MODULES_ANALYTICS ).finishResolution( 'getAccounts', [] );

	dispatch( MODULES_ANALYTICS ).receiveGetProperties( propertiesUA, { accountID } );
	dispatch( MODULES_ANALYTICS ).finishResolution( 'getProperties', [ accountID ] );

	dispatch( MODULES_ANALYTICS_4 ).receiveGetProperties( propertiesGA4, { accountID } );
	dispatch( MODULES_ANALYTICS_4 ).finishResolution( 'getProperties', [ accountID ] );

	dispatch( MODULES_ANALYTICS ).receiveGetProfiles( profiles, { accountID, propertyID: propertyIDua } );
	dispatch( MODULES_ANALYTICS ).finishResolution( 'getProfiles', [ accountID, propertyIDua ] );

	dispatch( MODULES_ANALYTICS_4 ).receiveGetWebDataStreams( webDataStreams, { propertyID: propertyIDga4 } );
	dispatch( MODULES_ANALYTICS_4 ).finishResolution( 'receiveGetWebDataStreams', { propertyID: propertyIDga4 } );
};

const setupEmptyRegistry = ( { dispatch } ) => {
	dispatch( MODULES_ANALYTICS ).receiveGetSettings( { accountID } );
	dispatch( MODULES_ANALYTICS_4 ).receiveGetSettings( {} );

	dispatch( MODULES_ANALYTICS ).receiveGetAccounts( accounts );
	dispatch( MODULES_ANALYTICS ).finishResolution( 'getAccounts', [] );

	dispatch( MODULES_ANALYTICS ).receiveGetProperties( [], { accountID } );
	dispatch( MODULES_ANALYTICS ).finishResolution( 'getProperties', [ accountID ] );

	dispatch( MODULES_ANALYTICS_4 ).receiveGetProperties( [], { accountID } );
	dispatch( MODULES_ANALYTICS_4 ).finishResolution( 'getProperties', [ accountID ] );
};

describe( 'PropertySelectIncludingGA4IncludingGA4', () => {
	it( 'should render an option for each analytics property of the currently selected account.', async () => {
		const { getAllByRole } = render( <PropertySelectIncludingGA4 />, { setupRegistry } );

		const listItems = getAllByRole( 'menuitem', { hidden: true } );
		// Note: we do length + 1 here because there should also be an item for
		// "Set up a new property".
		expect( listItems ).toHaveLength( propertiesUA.length + propertiesGA4.length + 1 );
	} );

	it( 'should not render in the absence of an valid account ID.', async () => {
		const { container, registry } = render( <PropertySelectIncludingGA4 />, {
			setupRegistry,
		} );

		// A valid accountID is provided, so ensure it is not currently disabled.
		const selectWrapper = container.querySelector( '.googlesitekit-analytics__select-property' );
		const selectedText = container.querySelector( '.mdc-select__selected-text' );
		expect( selectWrapper ).not.toHaveClass( 'mdc-select--disabled' );
		expect( selectedText ).not.toHaveAttribute( 'aria-disabled', 'true' );

		act( () => {
			registry.dispatch( MODULES_ANALYTICS ).setAccountID( ACCOUNT_CREATE );
			registry.dispatch( MODULES_ANALYTICS ).finishResolution( 'getProperties', [ ACCOUNT_CREATE ] );
			registry.dispatch( MODULES_ANALYTICS_4 ).finishResolution( 'getProperties', [ ACCOUNT_CREATE ] );
		} );
		// ACCOUNT_CREATE is an invalid accountID (but valid selection), so ensure the select is not rendered
		expect( container ).toBeEmptyDOMElement();
	} );

	it( 'should render a select box with only an option to create a new property if no properties are available.', async () => {
		const { getAllByRole } = render( <PropertySelectIncludingGA4 />, { setupRegistry: setupEmptyRegistry } );

		const listItems = getAllByRole( 'menuitem', { hidden: true } );
		expect( listItems ).toHaveLength( 1 );
		expect( listItems[ 0 ].textContent ).toMatch( /set up a new property/i );
	} );

	it( 'should change between UA and GA4 properties', async () => {
		const { getAllByRole, container, registry } = render( <PropertySelectIncludingGA4 />, { setupRegistry } );
		const ga4Properties = registry.select( MODULES_ANALYTICS_4 ).getProperties( accountID );
		// the selector getPropertiesIncludingGA4 sorts so this is rendered second in the select
		const ga4TargetProperty = ga4Properties[ 0 ];

		expect( container.querySelector( '.mdc-select__selected-text' ) ).toHaveTextContent( '' );

		fireEvent.click( container.querySelector( '.mdc-floating-label' ) );
		fireEvent.click( getAllByRole( 'menuitem', { hidden: true } )[ 1 ] );

		// The selected property is a GA4 property
		expect( registry.select( MODULES_ANALYTICS ).getPrimaryPropertyType() ).toBe( 'ga4' );
		const newGA4PropertyID = registry.select( MODULES_ANALYTICS_4 ).getPropertyID();
		expect( ga4TargetProperty._id ).toEqual( newGA4PropertyID );

		expect( container.querySelector( '.mdc-select__selected-text' ) )
			.toHaveTextContent( `${ ga4TargetProperty.displayName } (${ ga4TargetProperty._id })` );
		expect( container.querySelector( '.mdc-select__selected-text' ) )
			.toHaveTextContent( 'Test GA4 Property (1000)' );

		// the modules/analytics store's getPropertyID action should be reset
		expect( registry.select( MODULES_ANALYTICS ).getPropertyID() ).toBe( '' );

		// Select a UA property
		const uaProperties = registry.select( MODULES_ANALYTICS ).getProperties( accountID );

		const uaTargetProperty = uaProperties[ 0 ];

		fireEvent.click( container.querySelector( '.mdc-floating-label' ) );
		fireEvent.click( getAllByRole( 'menuitem', { hidden: true } )[ 7 ] );

		expect( registry.select( MODULES_ANALYTICS ).getPrimaryPropertyType() ).toBe( 'ua' );

		const newUAPropertyID = registry.select( MODULES_ANALYTICS ).getPropertyID();

		expect( uaTargetProperty.id ).toEqual( newUAPropertyID );

		expect( container.querySelector( '.mdc-select__selected-text' ) )
			.toHaveTextContent( `${ uaTargetProperty.name } (${ uaTargetProperty.id })` );
		expect( container.querySelector( '.mdc-select__selected-text' ) ).toHaveTextContent( 'wegweg (UA-152925174-1)' );

		expect( registry.select( MODULES_ANALYTICS_4 ).getPropertyID() ).toBe( '' );

		// Select a GA4 property again
		fireEvent.click( container.querySelector( '.mdc-floating-label' ) );
		fireEvent.click( getAllByRole( 'menuitem', { hidden: true } )[ 1 ] );

		expect( container.querySelector( '.mdc-select__selected-text' ) )
			.toHaveTextContent( `${ ga4TargetProperty.displayName } (${ ga4TargetProperty._id })` );
		expect( container.querySelector( '.mdc-select__selected-text' ) )
			.toHaveTextContent( 'Test GA4 Property (1000)' );

		expect( registry.select( MODULES_ANALYTICS ).getPropertyID() ).toBe( '' );
	} );
} );
<|endoftext|>


<commit_before>import _ from 'lodash'
import dbg from 'debug'
import async from 'async'
import {params, normalize} from './query'
import {ONE_TO_MANY, MANY_TO_ONE} from './relationships'
import filter from './odata/filter'
import * as errors from 'netiam-errors'
import list from './methods/list'
import create from './methods/create'
import read from './methods/read'
import update from './methods/update'
import remove from './methods/remove'

const debug = dbg('netiam:rest:resource')

/**
 * A main resource has a list of subresources.
 *
 * Example:
 *
 * ```javascript
 * app.get('/users/:user/projects'
 *   api()
 *    .rest({
 *      idParam: 'user',
 *      collection: User
 *      relationship: hasMany(Project, {field: 'projects', param: 'user'})
 *    })
 * )
 * ```
 *
 * @param {Object} Model
 * @param {Object} spec
 * @returns {Object}
 */
export function hasMany(Model, spec) {
  if (!Model) {
    throw errors.internalServerError(
      'A "hasMany" relationship must must define a target "Model"')
  }

  if (!spec.field) {
    throw errors.internalServerError(
      'A "hasMany" relationship must define option "field"')
  }

  return Object.assign({
    idField: '_id',
    type: ONE_TO_MANY,
    Model: Model
  }, spec)
}

/**
 * A subresource has a reference to a main resource.
 *
 * Example:
 *
 * ```javascript
 * app.get('/projects/:project/campaigns'
 *   api()
 *    .rest({
 *      collection: Campaign
 *      relationship: belongsTo(Project, {field: 'project', param: 'project'})
 *    })
 * )
 * ```
 *
 * @param {Object} Model
 * @param {Object} spec
 * @returns {Object}
 */
export function belongsTo(Model, spec) {
  if (!Model) {
    throw errors.internalServerError(
      'A "belongsTo" relationship must must define a base "Model"')
  }

  if (!spec.field) {
    throw errors.internalServerError(
      'A "belongsTo" relationship must define option "field"')
  }

  return Object.assign({
    idField: '_id',
    type: MANY_TO_ONE,
    Model: Model
  }, spec)
}

export default function resource(spec) {
  spec.idParam = spec.idParam || 'id'
  spec.idField = spec.idField || '_id'

  return Object.freeze({
    list: (req) => list(Object.assign({req}, spec)),
    create: (req) => create(Object.assign({req}, spec)),
    read: (req) => read(Object.assign({req}, spec)),
    update: (req) => update(Object.assign({req}, spec)),
    remove: (req) => remove(Object.assign({req}, spec))
  })
}
<commit_msg>fix: add missing default setting to relationship factory<commit_after>import _ from 'lodash'
import dbg from 'debug'
import async from 'async'
import {params, normalize} from './query'
import {ONE_TO_MANY, MANY_TO_ONE} from './relationships'
import filter from './odata/filter'
import * as errors from 'netiam-errors'
import list from './methods/list'
import create from './methods/create'
import read from './methods/read'
import update from './methods/update'
import remove from './methods/remove'

const debug = dbg('netiam:rest:resource')

/**
 * A main resource has a list of subresources.
 *
 * Example:
 *
 * ```javascript
 * app.get('/users/:user/projects'
 *   api()
 *    .rest({
 *      idParam: 'user',
 *      collection: User
 *      relationship: hasMany(Project, {field: 'projects', param: 'user'})
 *    })
 * )
 * ```
 *
 * @param {Object} Model
 * @param {Object} spec
 * @returns {Object}
 */
export function hasMany(Model, spec) {
  if (!Model) {
    throw errors.internalServerError(
      'A "hasMany" relationship must must define a target "Model"')
  }

  if (!spec.field) {
    throw errors.internalServerError(
      'A "hasMany" relationship must define option "field"')
  }

  return Object.assign({
    idField: '_id',
    idParam: 'id',
    type: ONE_TO_MANY,
    Model: Model
  }, spec)
}

/**
 * A subresource has a reference to a main resource.
 *
 * Example:
 *
 * ```javascript
 * app.get('/projects/:project/campaigns'
 *   api()
 *    .rest({
 *      collection: Campaign
 *      relationship: belongsTo(Project, {field: 'project', param: 'project'})
 *    })
 * )
 * ```
 *
 * @param {Object} Model
 * @param {Object} spec
 * @returns {Object}
 */
export function belongsTo(Model, spec) {
  if (!Model) {
    throw errors.internalServerError(
      'A "belongsTo" relationship must must define a base "Model"')
  }

  if (!spec.field) {
    throw errors.internalServerError(
      'A "belongsTo" relationship must define option "field"')
  }

  return Object.assign({
    idField: '_id',
    idParam: 'id',
    type: MANY_TO_ONE,
    Model: Model
  }, spec)
}

export default function resource(spec) {
  spec.idParam = spec.idParam || 'id'
  spec.idField = spec.idField || '_id'

  return Object.freeze({
    list: (req) => list(Object.assign({req}, spec)),
    create: (req) => create(Object.assign({req}, spec)),
    read: (req) => read(Object.assign({req}, spec)),
    update: (req) => update(Object.assign({req}, spec)),
    remove: (req) => remove(Object.assign({req}, spec))
  })
}
<|endoftext|>


<commit_before>/*
 * Cookie Calculator / scales/length.js
 * copyright (c) 2016 Susisu
 */

"use strict";

import { SIUnit } from "../units.js";

let values = [
    {
        value: 1.616199e-35,
        description:
            `1 Planck Length

            Size of the hypothetical quantum strings`
    },
    {
        value: 2e-23,
        description:
            `Effective cross section radius of
            1 MeV neutrinos`
    },
    {
        value: 1e-21,
        description:
            `Effective cross section radius of
            high energy neutrinos`
    },
    {
        value: 3.10e-19,
        description:
            `De Broglie wavelength of 4 TeV
            protons at the
            LHC`
    },
    {
        value: 1e-18,
        description:
            `Upper limit for the size of quarks and
            electrons

            Sensitivity of the LIGO detector for
            gravitational waves`
    },
    {
        value: 1e-17,
        description:
            `Range of the <a href="https://en.wikipedia.org/wiki/Weak_interaction">weak force</a>`
    },
    {
        value: 1e-15,
        description:
            `Scale of the <a href="https://en.wikipedia.org/wiki/Atomic_nucleus">atomic nuculeus</a>`
    },
    {
        value: 1e-12,
        description:
            `Longest wavelength of <a href="https://en.wikipedia.org/wiki/Gamma_ray">gamma rays</a>`
    },
    {
        value: 5e-12,
        description:
            `Shortest wavelength of <a href="https://en.wikipedia.org/wiki/X-ray">X-rays</a>`
    },
    {
        value: 2.5e-11,
        description:
            `Radius of <a href="https://en.wikipedia.org/wiki/Hydrogen_atom">hydrogen atom</a>`
    },
    {
        value: 5.3e-11,
        description:
            `<a href="https://en.wikipedia.org/wiki/Bohr_radius">Bohr radius</a>`
    },
    {
        value: 1e-10,
        description:
            `1 <a href="https://en.wikipedia.org/wiki/Ångström">Ångström</a>`
    },
    {
        value: 5e-10,
        description:
            `Width of <a href="https://en.wikipedia.org/wiki/Alpha_helix">α helix</a>`
    },
    {
        value: 1e-9,
        description:
            `Diameter of a <a href="https://en.wikipedia.org/wiki/Carbon_nanotube">carbon nanotube</a>`
    },
    {
        value: 4e-8,
        description:
            `Wavelength of extreme ultraviolet`
    },
    {
        value: 4e-7,
        description:
            `Wavelength of violet light`
    },
    {
        value: 7e-7,
        description:
            `Wavelength of red light`
    },
    {
        value: 7e-6,
        description:
            `Diameter of a red blood cell`
    },
    {
        value: 1e-5,
        description:
            `Typical size of fog water droplet`
    },
    {
        value: 1e-4,
        description:
            `Average width of a human hair`
    },
    {
        value: 5e-3,
        description:
            `Ant`
    },
    {
        value: 1.5e-2,
        description:
            `Mosquito`
    },
    {
        value: 2.54e-2,
        description:
            `1 inch`
    },
    {
        value: 1e-1,
        description:
            `Wavelength of the highest UHF radio frequency`
    },
    {
        value: 3.048e-1,
        description:
            `1 foot`
    },
    {
        value: 9.144e-1,
        description:
            `1 yard`
    },
    {
        value: 1.7,
        description:
            `Human`
    },
    {
        value: 3.3e+1,
        description:
            `Blue whale, the largest animal`
    },
    {
        value: 9.347e+1,
        description:
            `Height of the Statue of Liberty`
    },
    {
        value: 1.37e+2,
        description:
            `Height of the Great Pyramid of Giza`
    },
    {
        value: 8.848e+3,
        description:
            `Height of the highest mountain on Earth, Mount Everest`
    },
    {
        value: 1.0911e+4,
        description:
            `Depth of the deepest part of the Ocean, Mariana Trench`
    },
    {
        value: 9.0e+4,
        description:
            `Width of the Bering Strait`
    },
    {
        value: 9.746e+5,
        description:
            `Greatest diameter of the dwarf planet Ceres`
    }
];

export default values.map(x => ({
    quantity   : SIUnit.METRE.value(x.value),
    description: x.description
}));
<commit_msg>Add length scales<commit_after>/*
 * Cookie Calculator / scales/length.js
 * copyright (c) 2016 Susisu
 */

"use strict";

import { SIUnit } from "../units.js";

let values = [
    {
        value: 1.616199e-35,
        description:
            `1 Planck Length

            Size of the hypothetical quantum strings`
    },
    {
        value: 2e-23,
        description:
            `Effective cross section radius of
            1 MeV neutrinos`
    },
    {
        value: 1e-21,
        description:
            `Effective cross section radius of
            high energy neutrinos`
    },
    {
        value: 3.10e-19,
        description:
            `De Broglie wavelength of 4 TeV
            protons at the
            LHC`
    },
    {
        value: 1e-18,
        description:
            `Upper limit for the size of quarks and
            electrons

            Sensitivity of the LIGO detector for
            gravitational waves`
    },
    {
        value: 1e-17,
        description:
            `Range of the <a href="https://en.wikipedia.org/wiki/Weak_interaction">weak force</a>`
    },
    {
        value: 1e-15,
        description:
            `Scale of the <a href="https://en.wikipedia.org/wiki/Atomic_nucleus">atomic nuculeus</a>`
    },
    {
        value: 1e-12,
        description:
            `Longest wavelength of <a href="https://en.wikipedia.org/wiki/Gamma_ray">gamma rays</a>`
    },
    {
        value: 5e-12,
        description:
            `Shortest wavelength of <a href="https://en.wikipedia.org/wiki/X-ray">X-rays</a>`
    },
    {
        value: 2.5e-11,
        description:
            `Radius of <a href="https://en.wikipedia.org/wiki/Hydrogen_atom">hydrogen atom</a>`
    },
    {
        value: 5.3e-11,
        description:
            `<a href="https://en.wikipedia.org/wiki/Bohr_radius">Bohr radius</a>`
    },
    {
        value: 1e-10,
        description:
            `1 <a href="https://en.wikipedia.org/wiki/Ångström">Ångström</a>`
    },
    {
        value: 5e-10,
        description:
            `Width of <a href="https://en.wikipedia.org/wiki/Alpha_helix">α helix</a>`
    },
    {
        value: 1e-9,
        description:
            `Diameter of a <a href="https://en.wikipedia.org/wiki/Carbon_nanotube">carbon nanotube</a>`
    },
    {
        value: 4e-8,
        description:
            `Wavelength of extreme ultraviolet`
    },
    {
        value: 4e-7,
        description:
            `Wavelength of violet light`
    },
    {
        value: 7e-7,
        description:
            `Wavelength of red light`
    },
    {
        value: 7e-6,
        description:
            `Diameter of a red blood cell`
    },
    {
        value: 1e-5,
        description:
            `Typical size of fog water droplet`
    },
    {
        value: 1e-4,
        description:
            `Average width of a human hair`
    },
    {
        value: 5e-3,
        description:
            `Ant`
    },
    {
        value: 1.5e-2,
        description:
            `Mosquito`
    },
    {
        value: 2.54e-2,
        description:
            `1 inch`
    },
    {
        value: 1e-1,
        description:
            `Wavelength of the highest UHF radio frequency`
    },
    {
        value: 3.048e-1,
        description:
            `1 foot`
    },
    {
        value: 9.144e-1,
        description:
            `1 yard`
    },
    {
        value: 1.7,
        description:
            `Human`
    },
    {
        value: 3.3e+1,
        description:
            `Blue whale, the largest animal`
    },
    {
        value: 9.347e+1,
        description:
            `Height of the Statue of Liberty`
    },
    {
        value: 1.37e+2,
        description:
            `Height of the Great Pyramid of Giza`
    },
    {
        value: 8.848e+3,
        description:
            `Height of the highest mountain on Earth, Mount Everest`
    },
    {
        value: 1.0911e+4,
        description:
            `Depth of the deepest part of the Ocean, Mariana Trench`
    },
    {
        value: 9.0e+4,
        description:
            `Width of the Bering Strait`
    },
    {
        value: 9.746e+5,
        description:
            `Greatest diameter of the dwarf planet Ceres`
    },
    {
        value: 2.39e+6,
        description:
            `Diameter of Pluto`
    },
    {
        value: 3.48e+6,
        description:
            `Diameter of the Moon`
    },
    {
        value: 6.4e+6,
        description:
            `Length of the Great Wall of China`
    },
    {
        value: 1.2756e+7,
        description:
            `Equatorial diameter of Earth`
    },
    {
        value: 4.0075e+7,
        description:
            `Length of Earth's equator`
    },
    {
        value: 1.42984e+8,
        description:
            `Diameter of Jupiter`
    },
    {
        value: 2.99792458e+8,
        description:
            `Distance traveled by light in one second`
    },
    {
        value: 3.84e+8,
        description:
            `Moon's orbital distance from Earth`
    }
];

export default values.map(x => ({
    quantity   : SIUnit.METRE.value(x.value),
    description: x.description
}));
<|endoftext|>


<commit_before>Atmo.Models.Machine = Atmo.Models.Base.extend({
	defaults: { 'model_name': 'machine' },
	initialize: function () {
		this.set('name_or_id', this.get('name') || this.get('id'));
	},
	parse: function(response) {
		var attributes = response;

		attributes.id = response.alias;
		attributes.name = response.name;
		attributes.architecture = response.architecture;
		attributes.create_date = response.start_date;
		attributes.featured = response.featured;
		attributes.image_url = Atmo.profile.get_icon(response.alias_hash);
		attributes.ownerid = response.ownerid;
		attributes.state = response.state;

		return attributes;
	}
});

_.extend(Atmo.Models.Machine.defaults, Atmo.Models.Base.defaults);
<commit_msg>Custom machine icons display on New Instance screen.<commit_after>Atmo.Models.Machine = Atmo.Models.Base.extend({
	defaults: { 'model_name': 'machine' },
	initialize: function () {
		this.set('name_or_id', this.get('name') || this.get('id'));
	},
	parse: function(response) {
		var attributes = response;

		attributes.id = response.alias;
		attributes.name = response.name;
		attributes.architecture = response.architecture;
		attributes.create_date = response.start_date;
		attributes.featured = response.featured;

		if (response.icon)
			attributes.image_url = response.icon;
		else
			attributes.image_url = Atmo.profile.get_icon(response.alias_hash);

		attributes.ownerid = response.ownerid;
		attributes.state = response.state;

		return attributes;
	}
});

_.extend(Atmo.Models.Machine.defaults, Atmo.Models.Base.defaults);
<|endoftext|>


<commit_before>import superagent from 'superagent';

const methods = ['get', 'post', 'put', 'patch', 'del'];

class _ApiClient {
  constructor(req) {
    methods.forEach((method) => {
      this[method] = (path, { params, data } = {}) => new Promise((resolve, reject) => {
        const request = superagent[method](path);

        if (params) {
          request.query(params);
        }

        if (__SERVER__ && req.get('cookie')) {
          request.set('cookie', req.get('cookie'));
        }

        if (data) {
          request.send(data);
        }

        request.end((err, { body } = {}) => err ? reject(body || err) : resolve(body));
      });
    });
  }
}

const ApiClient = _ApiClient;

export default ApiClient;
<commit_msg>Fixed eslint error<commit_after>import superagent from 'superagent';

const methods = ['get', 'post', 'put', 'patch', 'del'];

class _ApiClient {
  constructor(req) {
    methods.forEach((method) => {
      this[method] = (path, { params, data } = {}) => new Promise((resolve, reject) => {
        const request = superagent[method](path);

        if (params) {
          request.query(params);
        }

        if (__SERVER__ && req.get('cookie')) {
          request.set('cookie', req.get('cookie'));
        }

        if (data) {
          request.send(data);
        }

        request.end((err, { body } = {}) => (err ? reject(body || err) : resolve(body)));
      });
    });
  }
}

const ApiClient = _ApiClient;

export default ApiClient;
<|endoftext|>