<commit_before>function findElementsWithClass(className) {
	return document.getElementsByClassName(className);
}

function findElementWithId(id) {
	return document.getElementById(id);
}

module('Entity', {
	setup: function () {
		enchant();
		var game = new Core(320, 320);
	},
	teardown: function () {
		// Coreインスタンスを破棄したいのだがそんな処理は無い様子
	}
});

/**
 * @see https://github.com/wise9/enchant.js/issues/14
 */
test('Entity.frame issue 14', function() {
	var sprite = new enchant.Sprite(32, 32);
	var error;

    try{
        sprite.frame = 0;
    	sprite.image = enchant.Core.instance.assets['start.png'];
    }catch(e){
        error = e;
    }
    equal(error, undefined);

});

/**
 * @see https://github.com/wise9/enchant.js/issues/18
 */
test('Entity.buttonMode issue 18', function () {
	var sprite = new Sprite();
	sprite.buttonMode = 'a';

	ok(!sprite.buttonPressed);
	sprite.dispatchEvent(new enchant.Event('touchstart'))
	ok(sprite.buttonPressed);
	sprite.dispatchEvent(new enchant.Event('touchend'))
	ok(!sprite.buttonPressed);
});

/**
 * add/remove/clearEventListener
 */
test('add/remove/clear EventListeners', function () {
	var sprite = new Sprite();
	listener = function(){};
	listener2 = function(){};

    // clear before test
    sprite.clearEventListener('enterframe');

    sprite.addEventListener('enterframe', listener);
    equal(sprite._listeners['enterframe'].length, 1);
    sprite.removeEventListener('enterframe', listener);
    equal(sprite._listeners['enterframe'].length, 0);

    sprite.addEventListener('enterframe', listener);
    equal(sprite._listeners['enterframe'].length, 1);
    sprite.addEventListener('enterframe', listener2);
    equal(sprite._listeners['enterframe'].length, 2);
    sprite.clearEventListener('enterframe');
    equal(sprite._listeners['enterframe'], undefined);

    sprite.addEventListener('enterframe', listener);
    equal(sprite._listeners['enterframe'].length, 1);
    sprite.addEventListener('enterframe', listener2);
    equal(sprite._listeners['enterframe'].length, 2);
    sprite.clearEventListener();
    equal(sprite._listeners['enterframe'], undefined);
    console.log(sprite._listeners);

});

/**
 * 異なるGroupの中のEntity同士についてintersectやwithinが誤動作
 */
test('Entity#intersect, #within between two entities in different Group', function() {
    var a = new enchant.Sprite(32, 32);
    var b = new enchant.Sprite(32, 32);
    var scene = new enchant.Scene();
    var ga = new enchant.Group();
    var gb = new enchant.Group();
    ga.addChild(a);
    gb.addChild(b);
    scene.addChild(ga);
    scene.addChild(gb);

    equal(a.intersect(b), true);
    equal(a.within(b), true);

    a.x = 64;
    equal(a.intersect(b), false);
    equal(a.within(b), false);

    ga.x = -64;
    equal(a.intersect(b), true);
    equal(a.within(b), true);

    b.y = 64;
    equal(a.intersect(b), false);
    equal(a.within(b), false);

    gb.y = -64;
    equal(a.intersect(b), true);
    equal(a.within(b), true);
});

/**
 * @see https://github.com/wise9/enchant.js/issues/95
 */
test('Sprite should draw a image repetitively, ' +
    'when the image is smaller than the sprite', function() {
    var surface = new enchant.Surface(24, 24);
    var context = surface.context;
    // Draw checkerboard pattern.
    context.fillStyle = '#FFFFFF';
    context.fillRect(0, 0, 24, 24);
    context.fillStyle = '#000000';
    context.fillRect(0, 0, 12, 12);
    context.fillRect(12, 12, 12, 12);

    var expected = new enchant.Surface(32, 32);
    var ctx = expected.context;
    ctx.fillStyle = '#FFFFFF';
    ctx.fillRect(0, 0, 32, 32);
    ctx.fillStyle = '#000000';
    ctx.fillRect(0, 0, 12, 12);
    ctx.fillRect(12, 12, 12, 12);
    ctx.fillRect(24, 0, 8, 12);
    ctx.fillRect(0, 24, 12, 8);
    ctx.fillRect(24, 24, 8, 8);
    var expectedURL = expected._element.toDataURL();

    var sprite = new enchant.Sprite(32, 32);
    sprite.image = surface;

    var actual = new enchant.Surface(32, 32);
    sprite.cvsRender(actual.context);
    var actualURL = actual._element.toDataURL();

    equal(actualURL, expectedURL);
});
<commit_msg>Stop using data URLs.<commit_after>function findElementsWithClass(className) {
	return document.getElementsByClassName(className);
}

function findElementWithId(id) {
	return document.getElementById(id);
}

module('Entity', {
	setup: function () {
		enchant();
		var game = new Core(320, 320);
	},
	teardown: function () {
		// Coreインスタンスを破棄したいのだがそんな処理は無い様子
	}
});

/**
 * @see https://github.com/wise9/enchant.js/issues/14
 */
test('Entity.frame issue 14', function() {
	var sprite = new enchant.Sprite(32, 32);
	var error;

    try{
        sprite.frame = 0;
    	sprite.image = enchant.Core.instance.assets['start.png'];
    }catch(e){
        error = e;
    }
    equal(error, undefined);

});

/**
 * @see https://github.com/wise9/enchant.js/issues/18
 */
test('Entity.buttonMode issue 18', function () {
	var sprite = new Sprite();
	sprite.buttonMode = 'a';

	ok(!sprite.buttonPressed);
	sprite.dispatchEvent(new enchant.Event('touchstart'))
	ok(sprite.buttonPressed);
	sprite.dispatchEvent(new enchant.Event('touchend'))
	ok(!sprite.buttonPressed);
});

/**
 * add/remove/clearEventListener
 */
test('add/remove/clear EventListeners', function () {
	var sprite = new Sprite();
	listener = function(){};
	listener2 = function(){};

    // clear before test
    sprite.clearEventListener('enterframe');

    sprite.addEventListener('enterframe', listener);
    equal(sprite._listeners['enterframe'].length, 1);
    sprite.removeEventListener('enterframe', listener);
    equal(sprite._listeners['enterframe'].length, 0);

    sprite.addEventListener('enterframe', listener);
    equal(sprite._listeners['enterframe'].length, 1);
    sprite.addEventListener('enterframe', listener2);
    equal(sprite._listeners['enterframe'].length, 2);
    sprite.clearEventListener('enterframe');
    equal(sprite._listeners['enterframe'], undefined);

    sprite.addEventListener('enterframe', listener);
    equal(sprite._listeners['enterframe'].length, 1);
    sprite.addEventListener('enterframe', listener2);
    equal(sprite._listeners['enterframe'].length, 2);
    sprite.clearEventListener();
    equal(sprite._listeners['enterframe'], undefined);
    console.log(sprite._listeners);

});

/**
 * 異なるGroupの中のEntity同士についてintersectやwithinが誤動作
 */
test('Entity#intersect, #within between two entities in different Group', function() {
    var a = new enchant.Sprite(32, 32);
    var b = new enchant.Sprite(32, 32);
    var scene = new enchant.Scene();
    var ga = new enchant.Group();
    var gb = new enchant.Group();
    ga.addChild(a);
    gb.addChild(b);
    scene.addChild(ga);
    scene.addChild(gb);

    equal(a.intersect(b), true);
    equal(a.within(b), true);

    a.x = 64;
    equal(a.intersect(b), false);
    equal(a.within(b), false);

    ga.x = -64;
    equal(a.intersect(b), true);
    equal(a.within(b), true);

    b.y = 64;
    equal(a.intersect(b), false);
    equal(a.within(b), false);

    gb.y = -64;
    equal(a.intersect(b), true);
    equal(a.within(b), true);
});

/**
 * @see https://github.com/wise9/enchant.js/issues/95
 */
test('Sprite should draw a image repetitively, ' +
    'when the image is smaller than the sprite', function() {
    var surface = new enchant.Surface(24, 24);
    var context = surface.context;
    // Draw checkerboard pattern.
    context.fillStyle = '#FFFFFF';
    context.fillRect(0, 0, 24, 24);
    context.fillStyle = '#000000';
    context.fillRect(0, 0, 12, 12);
    context.fillRect(12, 12, 12, 12);

    var expected = new enchant.Surface(32, 32);
    var ctx = expected.context;
    ctx.fillStyle = '#FFFFFF';
    ctx.fillRect(0, 0, 32, 32);
    ctx.fillStyle = '#000000';
    ctx.fillRect(0, 0, 12, 12);
    ctx.fillRect(12, 12, 12, 12);
    ctx.fillRect(24, 0, 8, 12);
    ctx.fillRect(0, 24, 12, 8);
    ctx.fillRect(24, 24, 8, 8);
    var expectedArray = ctx.getImageData(0, 0, 32, 32).data;

    var sprite = new enchant.Sprite(32, 32);
    sprite.image = surface;

    var actual = new enchant.Surface(32, 32);
    sprite.cvsRender(actual.context);
    var actualArray = actual.context.getImageData(0, 0, 32, 32).data;

    equal(actualArray.length, expectedArray.length);
    for (var i = 0; i < actualArray.length; i++)
        equal(actualArray[i], expectedArray[i]);
});
<|endoftext|>


<commit_before>//
//  ____  _                           _
// / ___|| |_ __ _ _ __   ___  ___   (_)___  (*)
// \___ \| __/ _` | '_ \ / _ \/ __|  | / __|
//  ___) | || (_| | |_) |  __/\__ \_ | \__ \
// |____/ \__\__,_| .__/ \___||___(_)/ |___/
//              |_|              |__/
//
// (*) a (really) tiny Javascript MVC microframework
//
// (c) Hay Kranen < hay@bykr.org >
// Version 0.2 - Released under the terms of the MIT license
// < http://en.wikipedia.org/wiki/MIT_License >
//
// Stapes.js : http://hay.github.com/stapes

(function() {
    var VERSION = "0.3pre";

    /** Utility functions
     *
     *  Note that these functions are only used inside Stapes, and therefore
     *  aren't that failsafe as the options in libraries
     *  such as Underscore.js, so that's why they're not usable outside
     *  the private scope.
     */
    var util = {
        bind : function(fn, ctx) {
            if (Function.prototype.bind) {
                // Native
                return fn.bind(ctx);
            } else {
                // Non-native
                return function() {
                    return fn.apply(ctx, arguments);
                };
            }
        },

        clone : function(obj) {
            if (util.isArray(obj)) {
                return obj.slice();
            } else if (util.isObject(obj)) {
                var newObj = {};

                util.each(obj, function(value, key) {
                    newObj[key] = value;
                });

                return newObj;
            } else {
                return obj;
            }
        },

        create : function(context) {
            var instance;

            if (typeof Object.create === "function") {
                // Native
                instance = Object.create(context);
            } else {
                // Non-native
                var F = function(){};
                F.prototype = context;
                instance = new F();
            }

            instance._guid = guid++;
            Stapes._attributes[instance._guid] = {};
            Stapes._eventHandlers[instance._guid] = {};

            return instance;
        },

        each : function(list, fn) {
            if (util.isArray(list)) {
                if (Array.prototype.forEach) {
                    // Native forEach
                    list.forEach( fn );
                } else {
                    for (var i = 0, l = list.length; i < l; i++) {
                        fn( list[i], i);
                    }
                }
            } else {
                for (var key in list) {
                    fn( list[key], key );
                }
            }
        },

        isArray : function(val) {
            return Object.prototype.toString.call( val ) === "[object Array]";
        },

        isObject : function(val) {
            return (typeof val === "object") && (!util.isArray(val) && val !== null);
        },

        // from http://stackoverflow.com/a/2117523/152809
        makeUuid : function() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
                return v.toString(16);
            });
        },

        toArray : function(val) {
            if (util.isObject(val)) {
                return util.values(val);
            } else {
                return Array.prototype.slice.call(val, 0);
            }
        },

        values : function(obj) {
            var values = [];

            util.each(obj, function(value, key) {
                values.push(value);
            });

            return values;
        }
    };

    /** Private helper functions */
    function addEvent(event) {
        // If we don't have any handlers for this type of event, add a new
        // array we can use to push new handlers
        if (!Stapes._eventHandlers[event.guid][event.type]) {
            Stapes._eventHandlers[event.guid][event.type] = [];
        }

        // Push an event object
        Stapes._eventHandlers[event.guid][event.type].push({
            "guid" : event.guid,
            "handler" : event.handler,
            "scope" : event.scope,
            "type" : event.type
        });
    }

    function addEventHandler(argTypeOrMap, argHandlerOrScope, argScope) {
        var eventMap = {},
            scope;

        if (typeof argTypeOrMap === "string") {
            scope = argScope || false;
            eventMap[ argTypeOrMap ] = argHandlerOrScope;
        } else {
            scope = argHandlerOrScope || false;
            eventMap = argTypeOrMap;
        }

        util.each(eventMap, util.bind(function(handler, eventString) {
            var events = eventString.split(" ");

            util.each(events, util.bind(function(eventType) {
                addEvent.call(this, {
                    "guid" : this._guid,
                    "handler" : handler,
                    "scope" : scope,
                    "type" : eventType
                });
            }, this));
        }, this));
    }

    function emitEvents(type, data, explicitType, explicitGuid) {
        explicitType = explicitType || false;
        explicitGuid = explicitGuid || this._guid;

        util.each(Stapes._eventHandlers[explicitGuid][type], util.bind(function(event) {
            var scope = (event.scope) ? event.scope : this;
            if (explicitType) {
                event.type = explicitType;
            }
            event.scope = scope;
            event.handler.call(event.scope, data, event);
        }, this));
    }

    function setAttribute(key, value) {
        // We need to do this before we actually add the item :)
        var itemExists = this.has(key),
            oldValue = Stapes._attributes[this._guid][key];

        // Is the value different than the oldValue? If not, ignore this call
        if (value === oldValue) {
            return;
        }

        // Actually add the item to the attributes
        Stapes._attributes[this._guid][key] = value;

        // Throw a generic event
        this.emit('change', key);

        // And a namespaced event as well, NOTE that we pass value instead of
        // key here!
        this.emit('change:' + key, value);

        // Throw namespaced and non-namespaced 'mutate' events as well with
        // the old value data as well and some extra metadata such as the key
        var mutateData = {
            "key" : key,
            "newValue" : value,
            "oldValue" : oldValue || null
        };

        this.emit('mutate', mutateData);
        this.emit('mutate:' + key, mutateData);

        // Also throw a specific event for this type of set
        var specificEvent = itemExists ? 'update' : 'create';

        this.emit(specificEvent, key);

        // And a namespaced event as well, NOTE that we pass value instead of key
        this.emit(specificEvent + ':' + key, value);
    }

    function updateAttribute(key, fn) {
        console.log(key, fn);
        var item = this.get(key),
            newValue = fn( util.clone(item) );

        setAttribute.call(this, key, newValue);
    }

    var guid = 1;

    var Module = {
        create : function() {
            return util.create(this);
        },

        emit : function(types, data) {
            data = data || null;

            util.each(types.split(" "), util.bind(function(type) {
                // First 'all' type events: is there an 'all' handler in the
                // global stack?
                if (Stapes._eventHandlers[-1].all) {
                    emitEvents.call(this, "all", data, type, -1);
                }

                // Catch all events for this type?
                if (Stapes._eventHandlers[-1][type]) {
                    emitEvents.call(this, type, data, type, -1);
                }

                if (typeof this._guid == 'number') {
                    // 'all' event for this specific module?
                    if (Stapes._eventHandlers[this._guid]["all"]) {
                        emitEvents.call(this, "all", data, type);
                    }

                    // Finally, normal events :)
                    if (Stapes._eventHandlers[this._guid][type]) {
                        emitEvents.call(this, type, data);
                    }
                }
            }, this));
        },

        extend : function(objectOrValues, valuesIfObject) {
            var object = (valuesIfObject) ? objectOrValues : this,
                values = (valuesIfObject) ? valuesIfObject : objectOrValues;

            util.each(values, function(value, key) {
                object[key] = value;
            });

            return this;
        },

        filter : function(fn) {
            var items = [];

            util.each(Stapes._attributes[this._guid], function(item) {
                if (fn(item)) {
                    items.push(item);
                }
            });

            return items;
        },

        get : function(input) {
            if (typeof input === "string") {
                return this.has(input) ? Stapes._attributes[this._guid][input] : null;
            } else if (typeof input === "function") {
                var items = this.filter(input);
                return (items.length) ? items[0] : false;
            }
        },

        getAll : function() {
            return Stapes._attributes[this._guid];
        },

        getAllAsArray : function() {
            var arr = [];

            util.each(Stapes._attributes[this._guid], function(value, key) {
                if (util.isObject(value)) {
                    value.id = key;
                }

                arr.push(value);
            });

            return arr;

        },

        has : function(key) {
            return (typeof Stapes._attributes[this._guid][key] !== "undefined");
        },

        init : function() {
            this.emit('ready');
            return this;
        },

        on : function() {
            addEventHandler.apply(this, arguments);
        },

        // Akin to set(), but makes a unique id
        push : function(input) {
            if (util.isArray(input)) {
                util.each(input, util.bind(function(value) {
                    setAttribute.call(this, util.makeUuid(), value);
                }, this));
            } else {
                setAttribute.call(this, util.makeUuid(), input);
            }
        },

        remove : function(input) {
            if (typeof input === "function") {
                util.each(Stapes._attributes[this._guid], util.bind(function(item, key) {
                    if (input(item)) {
                        delete Stapes._attributes[this._guid][key];
                        this.emit('remove change');
                    }
                }, this));
            } else {
                if (typeof input === "string") {
                    input = [input];
                }

                util.each(util.toArray(input), util.bind(function(id) {
                    if (this.has(id)) {
                        delete Stapes._attributes[this._guid][id];
                        this.emit('remove change');
                    }
                }, this));
            }
        },

        set : function(objOrKey, value) {
            if (util.isObject(objOrKey)) {
                util.each(objOrKey, util.bind(function(value, key) {
                    setAttribute.call(this, key, value);
                }, this));
            } else {
                setAttribute.call(this, objOrKey, value);
            }
        },

        update : function(keyOrFn, fn) {
            if (typeof keyOrFn === "string") {
                updateAttribute.call(this, keyOrFn, fn);
            } else if (typeof keyOrFn === "function") {
                util.each(this.getAll(), util.bind(function(value, key) {
                    updateAttribute.call(this, key, keyOrFn);
                }, this));
            }
        }
    };

    var Stapes = {
        "_attributes" : {},

        "_eventHandlers" : {
            "-1" : {} // '-1' is used for the global event handling
        },

        "_guid" : -1,

        "create" : function() {
            return util.create(Module);
        },

        "extend" : function(obj) {
            util.each(obj, function(value, key) {
                Module[key] = value;
            });
        },

        "on" : function() {
            addEventHandler.apply(this, arguments);
        },

        "version" : VERSION
    };

    // This library can be used as an AMD module, a Node.js module, or an
    // old fashioned global
    if (typeof exports !== "undefined") {
        // Server
        if (typeof module !== "undefined" && module.exports) {
            exports = module.exports = Stapes;
        }
        exports.Stapes = Stapes;
    } else if (typeof define === "function" && define.amd) {
        // AMD
        define(function() {
            return Stapes;
        });
    } else {
        // Global scope
        window.Stapes = Stapes;
    }
})();<commit_msg>console.log doesn't belong here<commit_after>//
//  ____  _                           _
// / ___|| |_ __ _ _ __   ___  ___   (_)___  (*)
// \___ \| __/ _` | '_ \ / _ \/ __|  | / __|
//  ___) | || (_| | |_) |  __/\__ \_ | \__ \
// |____/ \__\__,_| .__/ \___||___(_)/ |___/
//              |_|              |__/
//
// (*) a (really) tiny Javascript MVC microframework
//
// (c) Hay Kranen < hay@bykr.org >
// Version 0.2 - Released under the terms of the MIT license
// < http://en.wikipedia.org/wiki/MIT_License >
//
// Stapes.js : http://hay.github.com/stapes

(function() {
    var VERSION = "0.3pre";

    /** Utility functions
     *
     *  Note that these functions are only used inside Stapes, and therefore
     *  aren't that failsafe as the options in libraries
     *  such as Underscore.js, so that's why they're not usable outside
     *  the private scope.
     */
    var util = {
        bind : function(fn, ctx) {
            if (Function.prototype.bind) {
                // Native
                return fn.bind(ctx);
            } else {
                // Non-native
                return function() {
                    return fn.apply(ctx, arguments);
                };
            }
        },

        clone : function(obj) {
            if (util.isArray(obj)) {
                return obj.slice();
            } else if (util.isObject(obj)) {
                var newObj = {};

                util.each(obj, function(value, key) {
                    newObj[key] = value;
                });

                return newObj;
            } else {
                return obj;
            }
        },

        create : function(context) {
            var instance;

            if (typeof Object.create === "function") {
                // Native
                instance = Object.create(context);
            } else {
                // Non-native
                var F = function(){};
                F.prototype = context;
                instance = new F();
            }

            instance._guid = guid++;
            Stapes._attributes[instance._guid] = {};
            Stapes._eventHandlers[instance._guid] = {};

            return instance;
        },

        each : function(list, fn) {
            if (util.isArray(list)) {
                if (Array.prototype.forEach) {
                    // Native forEach
                    list.forEach( fn );
                } else {
                    for (var i = 0, l = list.length; i < l; i++) {
                        fn( list[i], i);
                    }
                }
            } else {
                for (var key in list) {
                    fn( list[key], key );
                }
            }
        },

        isArray : function(val) {
            return Object.prototype.toString.call( val ) === "[object Array]";
        },

        isObject : function(val) {
            return (typeof val === "object") && (!util.isArray(val) && val !== null);
        },

        // from http://stackoverflow.com/a/2117523/152809
        makeUuid : function() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
                return v.toString(16);
            });
        },

        toArray : function(val) {
            if (util.isObject(val)) {
                return util.values(val);
            } else {
                return Array.prototype.slice.call(val, 0);
            }
        },

        values : function(obj) {
            var values = [];

            util.each(obj, function(value, key) {
                values.push(value);
            });

            return values;
        }
    };

    /** Private helper functions */
    function addEvent(event) {
        // If we don't have any handlers for this type of event, add a new
        // array we can use to push new handlers
        if (!Stapes._eventHandlers[event.guid][event.type]) {
            Stapes._eventHandlers[event.guid][event.type] = [];
        }

        // Push an event object
        Stapes._eventHandlers[event.guid][event.type].push({
            "guid" : event.guid,
            "handler" : event.handler,
            "scope" : event.scope,
            "type" : event.type
        });
    }

    function addEventHandler(argTypeOrMap, argHandlerOrScope, argScope) {
        var eventMap = {},
            scope;

        if (typeof argTypeOrMap === "string") {
            scope = argScope || false;
            eventMap[ argTypeOrMap ] = argHandlerOrScope;
        } else {
            scope = argHandlerOrScope || false;
            eventMap = argTypeOrMap;
        }

        util.each(eventMap, util.bind(function(handler, eventString) {
            var events = eventString.split(" ");

            util.each(events, util.bind(function(eventType) {
                addEvent.call(this, {
                    "guid" : this._guid,
                    "handler" : handler,
                    "scope" : scope,
                    "type" : eventType
                });
            }, this));
        }, this));
    }

    function emitEvents(type, data, explicitType, explicitGuid) {
        explicitType = explicitType || false;
        explicitGuid = explicitGuid || this._guid;

        util.each(Stapes._eventHandlers[explicitGuid][type], util.bind(function(event) {
            var scope = (event.scope) ? event.scope : this;
            if (explicitType) {
                event.type = explicitType;
            }
            event.scope = scope;
            event.handler.call(event.scope, data, event);
        }, this));
    }

    function setAttribute(key, value) {
        // We need to do this before we actually add the item :)
        var itemExists = this.has(key),
            oldValue = Stapes._attributes[this._guid][key];

        // Is the value different than the oldValue? If not, ignore this call
        if (value === oldValue) {
            return;
        }

        // Actually add the item to the attributes
        Stapes._attributes[this._guid][key] = value;

        // Throw a generic event
        this.emit('change', key);

        // And a namespaced event as well, NOTE that we pass value instead of
        // key here!
        this.emit('change:' + key, value);

        // Throw namespaced and non-namespaced 'mutate' events as well with
        // the old value data as well and some extra metadata such as the key
        var mutateData = {
            "key" : key,
            "newValue" : value,
            "oldValue" : oldValue || null
        };

        this.emit('mutate', mutateData);
        this.emit('mutate:' + key, mutateData);

        // Also throw a specific event for this type of set
        var specificEvent = itemExists ? 'update' : 'create';

        this.emit(specificEvent, key);

        // And a namespaced event as well, NOTE that we pass value instead of key
        this.emit(specificEvent + ':' + key, value);
    }

    function updateAttribute(key, fn) {
        var item = this.get(key),
            newValue = fn( util.clone(item) );

        setAttribute.call(this, key, newValue);
    }

    var guid = 1;

    var Module = {
        create : function() {
            return util.create(this);
        },

        emit : function(types, data) {
            data = data || null;

            util.each(types.split(" "), util.bind(function(type) {
                // First 'all' type events: is there an 'all' handler in the
                // global stack?
                if (Stapes._eventHandlers[-1].all) {
                    emitEvents.call(this, "all", data, type, -1);
                }

                // Catch all events for this type?
                if (Stapes._eventHandlers[-1][type]) {
                    emitEvents.call(this, type, data, type, -1);
                }

                if (typeof this._guid == 'number') {
                    // 'all' event for this specific module?
                    if (Stapes._eventHandlers[this._guid]["all"]) {
                        emitEvents.call(this, "all", data, type);
                    }

                    // Finally, normal events :)
                    if (Stapes._eventHandlers[this._guid][type]) {
                        emitEvents.call(this, type, data);
                    }
                }
            }, this));
        },

        extend : function(objectOrValues, valuesIfObject) {
            var object = (valuesIfObject) ? objectOrValues : this,
                values = (valuesIfObject) ? valuesIfObject : objectOrValues;

            util.each(values, function(value, key) {
                object[key] = value;
            });

            return this;
        },

        filter : function(fn) {
            var items = [];

            util.each(Stapes._attributes[this._guid], function(item) {
                if (fn(item)) {
                    items.push(item);
                }
            });

            return items;
        },

        get : function(input) {
            if (typeof input === "string") {
                return this.has(input) ? Stapes._attributes[this._guid][input] : null;
            } else if (typeof input === "function") {
                var items = this.filter(input);
                return (items.length) ? items[0] : false;
            }
        },

        getAll : function() {
            return Stapes._attributes[this._guid];
        },

        getAllAsArray : function() {
            var arr = [];

            util.each(Stapes._attributes[this._guid], function(value, key) {
                if (util.isObject(value)) {
                    value.id = key;
                }

                arr.push(value);
            });

            return arr;

        },

        has : function(key) {
            return (typeof Stapes._attributes[this._guid][key] !== "undefined");
        },

        init : function() {
            this.emit('ready');
            return this;
        },

        on : function() {
            addEventHandler.apply(this, arguments);
        },

        // Akin to set(), but makes a unique id
        push : function(input) {
            if (util.isArray(input)) {
                util.each(input, util.bind(function(value) {
                    setAttribute.call(this, util.makeUuid(), value);
                }, this));
            } else {
                setAttribute.call(this, util.makeUuid(), input);
            }
        },

        remove : function(input) {
            if (typeof input === "function") {
                util.each(Stapes._attributes[this._guid], util.bind(function(item, key) {
                    if (input(item)) {
                        delete Stapes._attributes[this._guid][key];
                        this.emit('remove change');
                    }
                }, this));
            } else {
                if (typeof input === "string") {
                    input = [input];
                }

                util.each(util.toArray(input), util.bind(function(id) {
                    if (this.has(id)) {
                        delete Stapes._attributes[this._guid][id];
                        this.emit('remove change');
                    }
                }, this));
            }
        },

        set : function(objOrKey, value) {
            if (util.isObject(objOrKey)) {
                util.each(objOrKey, util.bind(function(value, key) {
                    setAttribute.call(this, key, value);
                }, this));
            } else {
                setAttribute.call(this, objOrKey, value);
            }
        },

        update : function(keyOrFn, fn) {
            if (typeof keyOrFn === "string") {
                updateAttribute.call(this, keyOrFn, fn);
            } else if (typeof keyOrFn === "function") {
                util.each(this.getAll(), util.bind(function(value, key) {
                    updateAttribute.call(this, key, keyOrFn);
                }, this));
            }
        }
    };

    var Stapes = {
        "_attributes" : {},

        "_eventHandlers" : {
            "-1" : {} // '-1' is used for the global event handling
        },

        "_guid" : -1,

        "create" : function() {
            return util.create(Module);
        },

        "extend" : function(obj) {
            util.each(obj, function(value, key) {
                Module[key] = value;
            });
        },

        "on" : function() {
            addEventHandler.apply(this, arguments);
        },

        "version" : VERSION
    };

    // This library can be used as an AMD module, a Node.js module, or an
    // old fashioned global
    if (typeof exports !== "undefined") {
        // Server
        if (typeof module !== "undefined" && module.exports) {
            exports = module.exports = Stapes;
        }
        exports.Stapes = Stapes;
    } else if (typeof define === "function" && define.amd) {
        // AMD
        define(function() {
            return Stapes;
        });
    } else {
        // Global scope
        window.Stapes = Stapes;
    }
})();<|endoftext|>


<commit_before>/*
 *
 * Backpack - Skyscanner's Design System
 *
 * Copyright 2017 Skyscanner Ltd
 *
 * 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.
 *
 */

// See http://danger.systems/js if you're not sure what this is.

import fs from 'fs';
import { includes } from 'lodash';
import { danger, fail, warn, message } from 'danger';
import { props, propKeys } from './packages/bpk-tokens/tokens/base.raw.ios.json';

const createdFiles = danger.git.created_files;
const modifiedFiles = danger.git.modified_files;
const fileChanges = [...modifiedFiles, ...createdFiles];

// Always be nice.
message('Thanks for the PR 🎉.');

// Ensure new web components are extensible by consumers.
const webComponentIntroduced = createdFiles.some(filePath => (
  filePath.match(/packages\/bpk-component.+\/src\/.+\.js/)
));

if (webComponentIntroduced) {
  warn('It looks like you are introducing a web component. Ensure the component style is extensible via `className`.');
}

// Ensure new native components are extensible by consumers.
const nativeComponentIntroduced = createdFiles.some(filePath => (
  filePath.match(/native\/packages\/react-native-bpk-component.+\/src\/.+\.js/)
));

if (nativeComponentIntroduced) {
  warn('It looks like you are introducing a native component. Ensure the component style is extensible via `style`.');
}

// If any of the packages have changed, the changelog should have been updated.
const changelogModified = includes(modifiedFiles, 'changelog.md');
const packagesModified = fileChanges.some(filePath => (
  (filePath.startsWith('packages/') || filePath.startsWith('native/packages/')) &&
  !filePath.startsWith('packages/bpk-docs/')
));
if (packagesModified && !changelogModified) {
  warn('One or more packages have changed, but `changelog.md` wasn\'t updated.');
}

// If source files have changed, the snapshots should have been updated.
const componentSourceFilesModified = fileChanges.some(filePath => (
  // packages/(one or more chars)/src/(one or more chars).js
  filePath.match(/packages\/.*bpk-component.+\/src\/.+\.js/) && !filePath.includes('-test.')
));

const snapshotsModified = fileChanges.some(filePath => (
  filePath.endsWith('.js.snap')
));

if (componentSourceFilesModified && !snapshotsModified) {
  warn('Package source files (e.g. `package/packageName/src/packageName.js`) were updated, but snapshots weren\'t. Have you checked that the tests still pass?'); // eslint-disable-line max-len
}

// Ensure shrinkwrap changes are intentional.
const shrinkwrapUpdated = includes(modifiedFiles, 'npm-shrinkwrap.json');
if (shrinkwrapUpdated) {
  warn('`npm-shrinkwrap.json` was updated. Ensure that this was intentional.');
}

// New files should include the Backpack license heading.
const unlicensedFiles = createdFiles.filter((filePath) => {
  // Applies to js, css, scss and sh files that are not located in dist folders.
  if (filePath.match(/\.(js|css|scss|sh)$/) && !filePath.includes('dist/')) {
    const fileContent = fs.readFileSync(filePath);
    return !fileContent.includes('Licensed under the Apache License, Version 2.0 (the "License")');
  }
  return false;
});
if (unlicensedFiles.length > 0) {
  fail(`These new files do not include the license heading: ${unlicensedFiles.join(', ')}`);
}

// Encourage smaller PRs.
const bigPRThreshold = 8;
if (fileChanges.length > bigPRThreshold) {
  warn(`This PR contains ${fileChanges.length} files (${createdFiles.length} new, ${modifiedFiles.length} modified). Consider splitting it into multiple PRs.`); // eslint-disable-line max-len
}

// iOS tokens should not appear in Android snapshot files
const androidSnapshotsWithIosTokens = fileChanges.filter((filePath) => {
  if (!filePath.match(/\.android\.js\.snap$/)) {
    return false;
  }

  const fileContent = fs.readFileSync(filePath).toString();

  const formatToken = ({ value, type }) => {
    const FORMATS = {
      font: `"fontFamily": ${value},`,
      'font-size': `"fontSize": ${value},`,
    };

    return FORMATS[type] || null;
  };

  return propKeys.some((tokenName) => {
    const token = props[tokenName];

    const formattedToken = formatToken(token);

    if (!formattedToken) {
      return false;
    }

    return fileContent.includes(formattedToken);
  });
});

if (androidSnapshotsWithIosTokens.length > 0) {
  // eslint-disable-next-line max-len
  fail(`iOS tokens have been found in the following Android snapshots:\n  - ${androidSnapshotsWithIosTokens.join('\n  - ')}`);
}
<commit_msg>[NOJIRA] Rename `props` and `propKeys` to be ios specific<commit_after>/*
 *
 * Backpack - Skyscanner's Design System
 *
 * Copyright 2017 Skyscanner Ltd
 *
 * 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.
 *
 */

// See http://danger.systems/js if you're not sure what this is.

import fs from 'fs';
import { includes } from 'lodash';
import { danger, fail, warn, message } from 'danger';
import { props as iosProps, propKeys as iosPropKeys } from './packages/bpk-tokens/tokens/base.raw.ios.json';

const createdFiles = danger.git.created_files;
const modifiedFiles = danger.git.modified_files;
const fileChanges = [...modifiedFiles, ...createdFiles];

// Always be nice.
message('Thanks for the PR 🎉.');

// Ensure new web components are extensible by consumers.
const webComponentIntroduced = createdFiles.some(filePath => (
  filePath.match(/packages\/bpk-component.+\/src\/.+\.js/)
));

if (webComponentIntroduced) {
  warn('It looks like you are introducing a web component. Ensure the component style is extensible via `className`.');
}

// Ensure new native components are extensible by consumers.
const nativeComponentIntroduced = createdFiles.some(filePath => (
  filePath.match(/native\/packages\/react-native-bpk-component.+\/src\/.+\.js/)
));

if (nativeComponentIntroduced) {
  warn('It looks like you are introducing a native component. Ensure the component style is extensible via `style`.');
}

// If any of the packages have changed, the changelog should have been updated.
const changelogModified = includes(modifiedFiles, 'changelog.md');
const packagesModified = fileChanges.some(filePath => (
  (filePath.startsWith('packages/') || filePath.startsWith('native/packages/')) &&
  !filePath.startsWith('packages/bpk-docs/')
));
if (packagesModified && !changelogModified) {
  warn('One or more packages have changed, but `changelog.md` wasn\'t updated.');
}

// If source files have changed, the snapshots should have been updated.
const componentSourceFilesModified = fileChanges.some(filePath => (
  // packages/(one or more chars)/src/(one or more chars).js
  filePath.match(/packages\/.*bpk-component.+\/src\/.+\.js/) && !filePath.includes('-test.')
));

const snapshotsModified = fileChanges.some(filePath => (
  filePath.endsWith('.js.snap')
));

if (componentSourceFilesModified && !snapshotsModified) {
  warn('Package source files (e.g. `package/packageName/src/packageName.js`) were updated, but snapshots weren\'t. Have you checked that the tests still pass?'); // eslint-disable-line max-len
}

// Ensure shrinkwrap changes are intentional.
const shrinkwrapUpdated = includes(modifiedFiles, 'npm-shrinkwrap.json');
if (shrinkwrapUpdated) {
  warn('`npm-shrinkwrap.json` was updated. Ensure that this was intentional.');
}

// New files should include the Backpack license heading.
const unlicensedFiles = createdFiles.filter((filePath) => {
  // Applies to js, css, scss and sh files that are not located in dist folders.
  if (filePath.match(/\.(js|css|scss|sh)$/) && !filePath.includes('dist/')) {
    const fileContent = fs.readFileSync(filePath);
    return !fileContent.includes('Licensed under the Apache License, Version 2.0 (the "License")');
  }
  return false;
});
if (unlicensedFiles.length > 0) {
  fail(`These new files do not include the license heading: ${unlicensedFiles.join(', ')}`);
}

// Encourage smaller PRs.
const bigPRThreshold = 8;
if (fileChanges.length > bigPRThreshold) {
  warn(`This PR contains ${fileChanges.length} files (${createdFiles.length} new, ${modifiedFiles.length} modified). Consider splitting it into multiple PRs.`); // eslint-disable-line max-len
}

// iOS tokens should not appear in Android snapshot files
const androidSnapshotsWithIosTokens = fileChanges.filter((filePath) => {
  if (!filePath.match(/\.android\.js\.snap$/)) {
    return false;
  }

  const fileContent = fs.readFileSync(filePath).toString();

  const formatToken = ({ value, type }) => {
    const FORMATS = {
      font: `"fontFamily": ${value},`,
      'font-size': `"fontSize": ${value},`,
    };

    return FORMATS[type] || null;
  };

  return iosPropKeys.some((tokenName) => {
    const token = iosProps[tokenName];

    const formattedToken = formatToken(token);

    if (!formattedToken) {
      return false;
    }

    return fileContent.includes(formattedToken);
  });
});

if (androidSnapshotsWithIosTokens.length > 0) {
  // eslint-disable-next-line max-len
  fail(`iOS tokens have been found in the following Android snapshots:\n  - ${androidSnapshotsWithIosTokens.join('\n  - ')}`);
}
<|endoftext|>


<commit_before>// var GLOBAL_CURRENT_STYLE = null;

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.type === 'get') {
        chrome.storage.local.get('allPages', function (data) {
            if (!data || !data.allPages) {
                sendResponse({allPages: []});
            }
            sendResponse({allPages: data.allPages});
        })
    }
    if (request.type === 'set') {
        chrome.storage.local.set({'allPages': request.pages});
    }
    if (request.type === 'remove') {
        chrome.storage.local.remove('allPages');
        chrome.storage.local.remove('title');
    }
    if (request.type === 'get title') {
        chrome.storage.local.get('title', function (data) {
            if (!data || !data.title || data.title.trim().length === 0) {
                sendResponse({title: 'eBook'});
            } else {
                sendResponse({title: data.title});
            }
        })
    }
    if (request.type === 'set title') {
        chrome.storage.local.set({'title': request.title});
    }
    if (request.type === 'get styles') {
        chrome.storage.local.get('styles', function (data) {
            if (!data || !data.styles) {
                // TODO move defaultStyles in a different file/location ?
                var defaultStyles = [
                    {
                        title: 'reddit',
                        url: 'reddit.com',
                        style: `.class: {
    display: none;
}
`
                    }
                ];
                sendResponse({styles: defaultStyles});
            } else {
                sendResponse({styles: data.styles});
            }
        });
    }
    if (request.type === 'set styles') {
        chrome.storage.local.set({'styles': request.styles});
    }
    if (request.type === 'get current style') {
        chrome.storage.local.get('currentStyle', function (data) {
            if (!data || !data.currentStyle) {
                sendResponse({currentStyle: 0});
            } else {
                sendResponse({currentStyle: data.currentStyle});
            }
        });
    }
    if (request.type === 'set current style') {
        chrome.storage.local.set({'currentStyle': request.currentStyle});
    }
    return true;
});
<commit_msg>fix for default style<commit_after>// var GLOBAL_CURRENT_STYLE = null;

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.type === 'get') {
        chrome.storage.local.get('allPages', function (data) {
            if (!data || !data.allPages) {
                sendResponse({allPages: []});
            }
            sendResponse({allPages: data.allPages});
        })
    }
    if (request.type === 'set') {
        chrome.storage.local.set({'allPages': request.pages});
    }
    if (request.type === 'remove') {
        chrome.storage.local.remove('allPages');
        chrome.storage.local.remove('title');
    }
    if (request.type === 'get title') {
        chrome.storage.local.get('title', function (data) {
            if (!data || !data.title || data.title.trim().length === 0) {
                sendResponse({title: 'eBook'});
            } else {
                sendResponse({title: data.title});
            }
        })
    }
    if (request.type === 'set title') {
        chrome.storage.local.set({'title': request.title});
    }
    if (request.type === 'get styles') {
        chrome.storage.local.get('styles', function (data) {
            if (!data || !data.styles) {
                // TODO move defaultStyles in a different file/location ?
                var defaultStyles = [
                    {
                        title: 'reddit',
                        url: 'reddit.com',
                        style: `.class {
    display: none;
}
`
                    }
                ];
                sendResponse({styles: defaultStyles});
            } else {
                sendResponse({styles: data.styles});
            }
        });
    }
    if (request.type === 'set styles') {
        chrome.storage.local.set({'styles': request.styles});
    }
    if (request.type === 'get current style') {
        chrome.storage.local.get('currentStyle', function (data) {
            if (!data || !data.currentStyle) {
                sendResponse({currentStyle: 0});
            } else {
                sendResponse({currentStyle: data.currentStyle});
            }
        });
    }
    if (request.type === 'set current style') {
        chrome.storage.local.set({'currentStyle': request.currentStyle});
    }
    return true;
});
<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const path = require('path');
const bunyan = require('bunyan');
const through = require('through');
const spawn = require('child_process').spawn;

const LOGGER_LEVELS = ['info', 'debug', 'error', 'fatal', 'trace', 'warn'];

const ENV_VARS = getEnvVariables();

const logOptions = {
  serializers: bunyan.stdSerializers,
  src: false
};

module.exports.TRACE = bunyan.TRACE;
module.exports.DEBUG = bunyan.DEBUG;
module.exports.INFO = bunyan.INFO;
module.exports.WARN = bunyan.WARN;
module.exports.ERROR = bunyan.ERROR;
module.exports.FATAL = bunyan.FATAL;
module.exports.resolveLevel = bunyan.resolveLevel;
module.exports.levelFromName = bunyan.levelFromName;
module.exports.nameFromLevel = bunyan.nameFromLevel;

module.exports = {
  getLogger,
  logLevels: LOGGER_LEVELS,
  TRACE: bunyan.TRACE,
  DEBUG: bunyan.DEBUG,
  INFO: bunyan.INFO,
  WARN: bunyan.WARN,
  ERROR: bunyan.ERROR,
  FATAL: bunyan.FATAL,
  resolveLevel: bunyan.resolveLevel,
  levelFromName: bunyan.levelFromName,
  nameFromLevel: bunyan.nameFromLevel,
  LOGGER_LEVELS
};

/**
 * Return an instance of Bunyan logger.
 *  Simple Code example:
 *    const yoBow = require('yo-bow');
 *    const logger = yoBow.getLogger('test 1');
 *    logger.info('Yeah!!');
 *
 *  Or pass in an object:
 *    const yoBow = require('yo-bow');
 *    const thisLogOptions = {
 *      name: 'test 3',
 *      src: false,         // Include line number and source file; default: false
 *      logLevel: 'trace',  // Set to a certain log level for this logger instance if log level is not set in the
 *                          // environment variable: process.env.LOG_LEVEL
 *      env: 'local',       // If env is local, console log will be in colors based on the log levels. env looks at
 *                          // process.env.NODE_ENV; default: production
 *      logToJson: false    // Default: false. If true, output will be in JSON format. Or the environment variable,
 *                          // process.env.LOG_TO_JSON can be set.
 *    };
 *
 *    const logger = yoBow.getLogger(thisLogOptions);
 *    logger.trace('Yo! Bow!!');
 *
 *
 *
 * @param logConfig
 */
function getLogger(logConfig) {
  let options = {
    serializers: logOptions.serializers,
    src: logOptions.src
  };

  let logLevel = ENV_VARS.logLevel;
  let logToJson = ENV_VARS.logToJson;
  let env = ENV_VARS.env;
  let streams = [];

  if (Object.prototype.toString.call(logConfig).indexOf('String') > -1) {
    options.name = logConfig;
  } else {
    options.name = logConfig.name;
    options.src = logConfig.src || false;
    if (logConfig.logLevel) {
      logLevel = logConfig.logLevel;
    }
    if (logConfig.logToJson !== undefined) {
      logToJson = logConfig.logToJson;
    }
    if (logConfig.env) {
      env = logConfig.env;
    }
    if (logConfig.streams && logConfig.streams.length > 0) {
      streams = logConfig.streams;
    }
  }

  let argColor = '--no-color';
  if (env === 'local') {
    argColor = '--color';
  }

  const args = [argColor];
  let baseStream = {
    level: logLevel,
    stream: prettyStream(args)
  };

  if (logToJson) {
    baseStream = {
      level: logLevel,
      stream: process.stdout
    };
  }
  streams.push(baseStream);
  options.streams = streams;
  return bunyan.createLogger(options);
}

// based on the work from https://github.com/trentm/node-bunyan/issues/13#issuecomment-22439322
function prettyStream(args) {
  let bin = path.resolve(
    path.dirname(require.resolve('bunyan')),
    '..',
    'bin',
    'bunyan'
  );

  if (/^win/.test(process.platform)) {
    args = ['/c', 'bunyan'].concat(args);
    bin = 'cmd';
  }

  const stream = through(
    function write(data) {
      this.queue(data);
    },
    function end() {
      this.queue(null);
    }
  );

  if ((bin && fs.existsSync(bin)) || bin === 'cmd') {
    const formatter = spawn(bin, args, {
      stdio: [null, process.stdout, process.stderr]
    });
    stream.pipe(formatter.stdin);
  }

  return stream;
}

function getEnvVariables() {
  return {
    env: process.env.NODE_ENV || 'production',
    logLevel: getLoggerLevel(process.env.LOG_LEVEL),
    logToJson: process.env.LOG_TO_JSON === 'true'
  };
}

/***
 * Returns a log level. Default: info level
 * @param logName
 * @returns a log level and if it's not one of the 6 choices, return "info"
 */
function getLoggerLevel(logName) {
  let foundLoggerIdx = LOGGER_LEVELS.indexOf(logName);
  if (foundLoggerIdx < 0) {
    foundLoggerIdx = 0;
  }

  return LOGGER_LEVELS[foundLoggerIdx];
}
<commit_msg>Change levels to use Bunyan<commit_after>'use strict';

const fs = require('fs');
const path = require('path');
const bunyan = require('bunyan');
const through = require('through');
const spawn = require('child_process').spawn;

const LOGGER_LEVELS = Object.keys(bunyan.levelFromName);

const ENV_VARS = getEnvVariables();

module.exports = {
  getLogger,
  logLevels: LOGGER_LEVELS,
  TRACE: bunyan.TRACE,
  DEBUG: bunyan.DEBUG,
  INFO: bunyan.INFO,
  WARN: bunyan.WARN,
  ERROR: bunyan.ERROR,
  FATAL: bunyan.FATAL,
  resolveLevel: bunyan.resolveLevel,
  levelFromName: bunyan.levelFromName,
  nameFromLevel: bunyan.nameFromLevel,
  LOGGER_LEVELS
};

/**
 * Return an instance of Bunyan logger.
 *  Simple Code example:
 *    const logger = require('yo-bow').getLogger('test 1');
 *    logger.info('Yeah!!');
 *
 *  Or pass in an object:
 *    const yoBow = require('yo-bow');
 *    const thisLogOptions = {
 *      name: 'test 2',
 *      src: true,          // default: false
 *      logLevel: 'trace',  // default: info
 *      env: 'local',       // default: production
 *      logToJson: false    // default: false
 *    };
 *
 *    const logger = yoBow.getLogger(thisLogOptions);
 *    logger.trace('Yo! Bow!!');
 *
 *
 *
 * @param {Object}  options           Configuration for logging
 * @param {String}  options.name      Name of the logger
 * @param {Boolean} options.src       If true, show line number
 * @param {String}  options.logLevel  Set to a log level for this logger
 *                                      instance Level: trace, debug, info,
 *                                      warn, error, fatal.
 *                                      Or from process.env.LOG_LEVEL
 * @param {Boolean} options.logToJson If true, log is in JSON format.
 *                                      Or from process.env.LOG_TO_JSON
 * @param {String}  options.env       If env == 'local', console log
 *                                      will be in colors based on the
 *                                      log levels.
 *                                      Or from process.env.NODE_ENV.
 *                                      Default: production
 * @param {Array}   options.streams   A list of writable streams will be
 *                                      included with a default stream
 *                                      that outputs to console.
 *
 */
function getLogger(options) {
  options = resolveOptions(options);

  let baseStream = {
    level: options.logLevel,
    stream: process.stdout
  };

  if (!options.logToJson) {
    baseStream = {
      level: options.logLevel,
      stream:
        options.env == 'local'
          ? prettyStream(['--color'])
          : prettyStream(['--no-color'])
    };
  }

  const streams = options.streams;
  streams.push(baseStream);
  options.streams = streams;
  options.serializers = bunyan.stdSerializers;
  return bunyan.createLogger(options);
}

// based on the work from https://github.com/trentm/node-bunyan/issues/13#issuecomment-22439322
function prettyStream(args) {
  let bin = path.resolve(
    path.dirname(require.resolve('bunyan')),
    '..',
    'bin',
    'bunyan'
  );

  if (/^win/.test(process.platform)) {
    args = ['/c', 'bunyan'].concat(args);
    bin = 'cmd';
  }

  const stream = through(
    function write(data) {
      this.queue(data);
    },
    function end() {
      this.queue(null);
    }
  );

  if ((bin && fs.existsSync(bin)) || bin === 'cmd') {
    const formatter = spawn(bin, args, {
      stdio: [null, process.stdout, process.stderr]
    });
    stream.pipe(formatter.stdin);
  }

  return stream;
}

function resolveOptions(options) {
  if (isTypeOf(options, 'String')) {
    options = {name: options};
  }
  options.src = options.src == 'true' ? true : false;
  options.logLevel = options.logLevel || ENV_VARS.logLevel;
  options.logToJson = options.logToJson || ENV_VARS.logToJson;
  options.env = options.env || ENV_VARS.env;
  options.streams = options.streams || [];

  return options;
}
function getEnvVariables() {
  return {
    env: process.env.NODE_ENV || 'production',
    logLevel: getLoggerLevelName(process.env.LOG_LEVEL),
    logToJson: process.env.LOG_TO_JSON == 'true'
  };
}

/***
 * Returns a log level. Default: info level
 * @param {String} logName  Log level name
 * @return {String}         A level: one of LOGGER_LEVELS
 */
function getLoggerLevelName(logName) {
  if (!logName) {
    return 'info';
  }
  const foundLoggerIdx = LOGGER_LEVELS.indexOf(logName.toLowerCase());
  if (foundLoggerIdx < 0) {
    return 'info';
  }

  return LOGGER_LEVELS[foundLoggerIdx];
}

/**
 *
 * @param {String} variable  this variable
 * @param {String} type      object type
 * @return {Boolean}         True, if the type of variable matches with type
 */
function isTypeOf(variable, type) {
  const toString = Object.prototype.toString;
  const varType = toString.call(variable).toLowerCase();

  return varType.indexOf(type.toLowerCase()) > 7;
}
<|endoftext|>


<commit_before>export default ({children, links, typekitKey, title, gaKey, appContent, styletronSheets, meta}) => {
  return (
  <html lang="en">
  <head>
  <title>{title}</title>
  {meta ? meta.map(attrs => <meta {...attrs}/>) : ''}
  {styletronSheets.map(sheet =>
    <style className="styletron" media={sheet.media} dangerouslySetInnerHTML={{__html:
    sheet.css
  }}/>
  )}
  {typekitKey ? <script src={
    `https://use.typekit.net/${typekitKey}.js`
  }/> : ''}
  {typekitKey ? <script dangerouslySetInnerHTML={{__html:
    'try{Typekit.load({async:true});}catch(e){}'
  }}/> : ''}
  {links ? links.map(attrs => <link {...attrs}/>) : ''}
  </head>
  <body>
  <div
    id="app"
    dangerouslySetInnerHTML={{__html: appContent}}
  />
  </body>
  <script src="/client.bundle.js"></script>
  {gaKey ? <script dangerouslySetInnerHTML={{__html: gaScript(gaKey)}}/> : ''}
  </html>
)};

function gaScript(key) {
  return (
    `
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

    ga('create', '${key}', 'auto');
    ga('send', 'pageview');

    `);
}
<commit_msg>Update Google Analytics script<commit_after>export default ({children, links, typekitKey, title, gaKey, appContent, styletronSheets, meta}) => {
  return (
  <html lang="en">
  <head>
  <title>{title}</title>
  {meta ? meta.map(attrs => <meta {...attrs}/>) : ''}
  {styletronSheets.map(sheet =>
    <style className="styletron" media={sheet.media} dangerouslySetInnerHTML={{__html:
    sheet.css
  }}/>
  )}
  {typekitKey ? <script src={
    `https://use.typekit.net/${typekitKey}.js`
  }/> : ''}
  {typekitKey ? <script dangerouslySetInnerHTML={{__html:
    'try{Typekit.load({async:true});}catch(e){}'
  }}/> : ''}
  {links ? links.map(attrs => <link {...attrs}/>) : ''}
  </head>
  <body>
  <div
    id="app"
    dangerouslySetInnerHTML={{__html: appContent}}
  />
  </body>
  <script src="/client.bundle.js"></script>
  {gaKey ? <script dangerouslySetInnerHTML={{__html: gaScript(gaKey)}}/> : ''}
  {gaKey ? <script src="https://www.google-analytics.com/analytics.js" async defer/> : ''}
  </html>
)};

function gaScript(key) {
  return [
    `window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;`,
    `ga('create','${key}','auto');ga('send','pageview')`
  ].join('');
}
<|endoftext|>


<commit_before>$(document).ready(function(){

   // load all projects
   $('a#projects').click(function(){
      console.log('Loading projects...');
      $.ajax({
         type:'GET',
         url:'/api/projects',
         success:function(json){
            console.log("Retrieved projects:");
            alert(json);
            $.each(json, function(key, project){
               console.log("Project name: " + project.name);
            });
            console.log("Finished loading projects");
         }
      });
   });
});
<commit_msg>Append to<commit_after>$(document).ready(function(){

   // load all projects
   $('a#projects').click(function(){
      console.log('Loading projects...');
      $.ajax({
         type:'GET',
         url:'/api/projects',
         success:function(json){
            console.log("Retrieved projects:");
            $.each(json, function(key, project){
               console.log("Project name: " + project.name);
               $('.content').append(project.name + '<br/>');
            });
            console.log("Finished loading projects");
         }
      });
   });
});
<|endoftext|>


<commit_before>const ExtractTextPlugin = require('extract-text-webpack-plugin');

exports.modifyWebpackConfig = ({ config, stage }) => {

    switch (stage) {
        case 'develop':
        case 'build-css':
        case 'build-html':
        case 'build-javascript':
            config.loader('sass', {
                test: /\.(sass|scss)$/,
                exclude: /\.module\.(sass|scss)$/,
                loader: null
            });

            config.loader('babel!react-markdown', {
               test: /\.md$/
            });

            break;
    }

    return config
};<commit_msg>fix: Gatsby config<commit_after>const ExtractTextPlugin = require('extract-text-webpack-plugin');

exports.modifyWebpackConfig = ({ config, stage }) => {

    switch (stage) {
        case 'develop':
            config.loader('sass', {
                test: /\.(sass|scss)$/,
                exclude: /\.module\.(sass|scss)$/,
                loaders: ['style', 'css', 'sass'],
            });

            break;

        case 'build-css':
            config.loader('sass', {
                test: /\.(sass|scss)$/,
                exclude: /\.module\.(sass|scss)$/,
                loader: ExtractTextPlugin.extract(['css?minimize', 'sass']),
            });

            break;

        case 'build-html':
            config.loader('sass', {
                test: /\.(sass|scss)$/,
                exclude: /\.module\.(sass|scss)$/,
                loader: 'null',
            });

            break;

        case 'build-javascript':
            config.loader('sass', {
                test: /\.(sass|scss)$/,
                exclude: /\.module\.(sass|scss)$/,
                loader: 'null',
            });

            break;
    }

    return config
}<|endoftext|>


<commit_before>//author: Blair Vanderhoof
//https://github.com/blairvanderhoof/gist-embed
$(function(){
  var gistMarkerId = 'gist-';

  //find all code elements containing "gist-" the id attribute.
  $('code[id*="'+gistMarkerId+'"]').each(function(){
    var $elem = $(this),
      id,
      url,
      file,
      line,
      data = {};

    id = $elem.attr('id') || '';
    file = $elem.attr('data-file');
    line = $elem.attr('data-line');
    splittedFileName = file.split('.').join('-');

    if(file){
      data.file = file;
    }

    //if the id doesn't begin with 'gist-', then ignore the code block
    if (!id || id.indexOf('gist-') !== 0) return false;

    //make block level so loading text shows properly
    $elem.css('display', 'block');

    //get the numeric id from the id attribute of the element holder
    id = id.substr(0, gistMarkerId.length) === gistMarkerId ? id.replace(gistMarkerId, '') : null;

    //make sure result is a numeric id
    if(!isNaN(parseInt(id, 10))){
      url = 'https://gist.github.com/' + id + '.json';
      //loading
      $elem.html('Loading gist ' + url + (data.file ? ', file: ' + data.file : '') + '...');
      //request the json version of this gist
      $.ajax({
        url: url,
        data: data,
        dataType: 'jsonp',
        timeout: 10000,
        success: function(response){
          //the html payload is in the div property
          if(response && response.div){
            //add the stylesheet if it does not exist
            if(response.stylesheet && $('link[href="' + response.stylesheet + '"]').length === 0){
              var l = document.createElement("link"),
                head = document.getElementsByTagName("head")[0];

              l.type = "text/css";
              l.rel = "stylesheet";
              l.href = response.stylesheet;
              head.insertBefore(l, head.firstChild);
            }
            if(line){
              if($(response.div).find('#file-' + splittedFileName + '-LC' + line)[0]){
                lineCode = $(response.div).find('#file-' + splittedFileName + '-LC' + line)[0].innerHTML;
                basicStructureWithSingleLine = '

' +
                                               '

' +
                                               '
' +
                                               '

' +
                                               '
' +
                                               lineCode + '

';
                $elem.html(basicStructureWithSingleLine);
              }
              else{
                $elem.html($(response.div).html("Invalid line number specified."));
              }
            }
            else{
              $elem.html(response.div);
            }
          }else{
            $elem.html('Failed loading gist ' + url);
          }
        },
        error: function(){
          $elem.html('Failed loading gist ' + url);
        }
      });
    }else{
      $elem.html('Failed loading gist with incorrect id format: ' + $elem.attr('id'));
    }
  });
});
<commit_msg>show multiple lines feature added<commit_after>//author: Blair Vanderhoof
//https://github.com/blairvanderhoof/gist-embed
$(function(){
  var gistMarkerId = 'gist-';

  //find all code elements containing "gist-" the id attribute.
  $('code[id*="'+gistMarkerId+'"]').each(function(){
    var $elem = $(this),
      id,
      url,
      file,
      line,
      data = {};

    id = $elem.attr('id') || '';
    file = $elem.attr('data-file');
    line = $elem.attr('data-line');
    splittedFileName = file.split('.').join('-');

    if(file){
      data.file = file;
    }

    //if the id doesn't begin with 'gist-', then ignore the code block
    if (!id || id.indexOf('gist-') !== 0) return false;

    //make block level so loading text shows properly
    $elem.css('display', 'block');

    //get the numeric id from the id attribute of the element holder
    id = id.substr(0, gistMarkerId.length) === gistMarkerId ? id.replace(gistMarkerId, '') : null;

    //make sure result is a numeric id
    if(!isNaN(parseInt(id, 10))){
      url = 'https://gist.github.com/' + id + '.json';
      //loading
      $elem.html('Loading gist ' + url + (data.file ? ', file: ' + data.file : '') + '...');
      //request the json version of this gist
      $.ajax({
        url: url,
        data: data,
        dataType: 'jsonp',
        timeout: 10000,
        success: function(response){
          //the html payload is in the div property
          if(response && response.div){
            //add the stylesheet if it does not exist
            if(response.stylesheet && $('link[href="' + response.stylesheet + '"]').length === 0){
              var l = document.createElement("link"),
                head = document.getElementsByTagName("head")[0];

              l.type = "text/css";
              l.rel = "stylesheet";
              l.href = response.stylesheet;
              head.insertBefore(l, head.firstChild);
            }
            if(line){
              var lineNumbers = getLineNumbers(line);
              var lineCodes = new Array(lineNumbers.length);

              for(var i = 0; i < lineNumbers.length; i++){
                if($(response.div).find('#file-' + splittedFileName + '-LC' + lineNumbers[i])[0]){
                  lineCodes[i] = $(response.div).find('#file-' + splittedFileName + '-LC' + line)[0].innerHTML;
                }
              }
              $elem.html(basicStructureForMultipleLines(id, lineCodes, splittedFileName));
            }
            else{
              $elem.html(response.div);
            }
          }else{
            $elem.html('Failed loading gist ' + url);
          }
        },
        error: function(){
          $elem.html('Failed loading gist ' + url);
        }
      });
    }else{
      $elem.html('Failed loading gist with incorrect id format: ' + $elem.attr('id'));
    }
  });
});

function getLineNumbers(lineRangeString){
  var lineNumbers = [];
  var lineNumberSections = lineRangeString.split(',');
  $(lineNumberSections).each(function(){
    var range = $(this).split('-');
    if(range.length == 2){
      for(var i = range[0]; i <= range[1]; i++){
        lineNumbers.push(i);
      }
    }
    elseif(range.length == 1){
      lineNumbers.push(range[0]);
    }
  });
  return lineNumbers;
}

function basicStructureForMultipleLines(gistId, lineCodes, splittedFileName){
  html = '

' +
         '

' +
         '
' +
         '

';
  for(var i = 0; i < lineCodes.length; i++){
    html += '
' +
    lineCodes[i] + '
';
  }
  html += '

';
}
<|endoftext|>


<commit_before>var assert = require('assert'),
    sys = require('sys'),
    redis = require('redis-client'),
    EventEmitter = require('events').EventEmitter;

var _fresnel = require('fresnel');
var Fresnel = _fresnel.Fresnel;

_fresnel.AUTO_CLOSE = true;

process.addListener('uncaughtException', function(err) {
    console.log("Caught exception: " + err);
});

function randomTask() {
    return {
        "class": randomString(),
        "args": []
    };
}

var CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

function randomString(length) {
    length = length || 16;
    var text = "";

    for (var i=0; i < length; i++) {
        text += CHARACTERS.charAt(Math.floor(Math.random() * CHARACTERS.length));
    }

    return text;
}

function replaceClientMethod(fresnel, method, func) {
    var _getClient = fresnel._getClient;

    fresnel._getClient = function() {
        var client = _getClient.apply(this);
        client[method] = function() {
            var callback = arguments[arguments.length - 1];
            callback(null, func.apply(null, arguments));
        };
        return client;
    }
}

module.exports = {
    'should be an EventEmitter': function(assert) {
        var fresnel = new Fresnel();
        assert.ok(fresnel instanceof EventEmitter);
    },
    'should buffer tasks into a local queue': function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        // create some tasks in Redis
        var task = randomTask();

        fresnel.createTask(task, function() {
            fresnel.bufferTasks(function() {
                fresnel.getUnbufferedQueueLength(function(length) {
                    assert.equal(0, length);
                });
            });
        });

        beforeExit(function() {
            assert.equal(task.toString(), fresnel.BUFFERED_TASKS[0].toString());
        });
    },
    'should mark buffered tasks as pending': function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        fresnel.createTask(randomTask(), function() {
            fresnel.bufferTasks(function() {
                fresnel.getPendingCount(function(count) {
                    assert.equal(1, count);
                });
            });
        });
    },
    'should buffer tasks with no callback': function(assert) {
        var fresnel = new Fresnel(randomString());

        fresnel.createTask(randomTask(), function() {
            fresnel.bufferTasks();
        });
    },
    'should succeed when no tasks are available to be buffered': function(assert) {
        var fresnel = new Fresnel(randomString());

        fresnel.bufferTasks();
    },
    'should succeed when no tasks are available to be buffered and no callback was provided': function(assert) {
        var fresnel = new Fresnel(randomString());

        fresnel.bufferTasks();
    },
    'Duplicate tasks should only be inserted once': function(assert) {
        var fresnel = new Fresnel(randomString());

        var task = randomTask();

        fresnel.createTask(task, function() {
            fresnel.createTask(task, function() {
                fresnel.getUnbufferedQueueLength(function(length) {
                    assert.equal(1, length);
                });
            });
        });
    },
    'Locally buffered tasks should be run': function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var task = randomTask();
        task.id = "1234";

        fresnel.BUFFERED_TASKS = [task];

        fresnel.runBufferedTasks();

        beforeExit(function() {
            assert.equal(0, fresnel.BUFFERED_TASKS.length);
        });
    },
    'should create tasks with no callback': function(assert) {
        var fresnel = new Fresnel(randomString());

        fresnel.createTask(randomTask());
    },
    "shouldn't fail when creating a duplicate task with no callback": function(assert) {
        var fresnel = new Fresnel(randomString());

        var task = randomTask();

        fresnel.createTask(task, function() {
            fresnel.createTask(task);
        });
    },
    "should add to the 'tasks' set when creating tasks": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var calledWithKey;

        replaceClientMethod(fresnel, 'sadd', function(key, value, callback) {
            calledWithKey = key;
        });

        fresnel.createTask(randomTask());

        beforeExit(function() {
            assert.equal(fresnel._namespace("tasks"), calledWithKey);
        });
    },
    "should add to the 'queue' sorted set when creating tasks": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var calledWithKey;

        replaceClientMethod(fresnel, 'zadd', function(key, score, value, callback) {
            calledWithKey = key;
        });

        fresnel.createTask(randomTask());

        beforeExit(function() {
            assert.equal(fresnel._namespace("queue"), calledWithKey);
        });
    },
    "should form a task definition when creating tasks": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var calledWithKey;

        replaceClientMethod(fresnel, 'set', function(key, value, callback) {
            calledWithKey = key;
        });

        var task = randomTask();

        fresnel.createTask(task);

        beforeExit(function() {
            assert.equal(fresnel._namespace("tasks:" + task.id), calledWithKey);
        });
    },
    "update definition should store an internal definition": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var resultTask;

        var taskId = 42;
        var task = randomTask();
        assert.ok(task.id == null);

        fresnel._getClient = function() {
            return {
                "set": function(key, value) {
                    resultTask = JSON.parse(value);
                }
            };
        }

        fresnel._updateDefinition(taskId, task);

        beforeExit(function() {
            assert.equal(taskId, resultTask.id);
        });
    },
    "hash function should only consider public fields": function(assert) {
        var fresnel = new Fresnel(randomString());

        var task = randomTask();
        var hash = fresnel._hash(task);

        task.id = "1234";

        assert.equal(hash, fresnel._hash(task));
    },
    "when tasks execute successfully, they should be removed from the 'tasks' set": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var removedKeys = [];

        var task = randomTask();

        replaceClientMethod(fresnel, 'srem', function(key, value, callback) {
            removedKeys.push(key);
        });

        fresnel.createTask(task, function() {
            fresnel._executeTask(task);
        });

        beforeExit(function() {
            assert.ok(removedKeys.indexOf(fresnel._namespace("tasks")) >= 0);
        });
    },
    "when tasks execute successfully, they should be removed from the 'pending' set": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var removedKeys = [];

        var task = randomTask();

        replaceClientMethod(fresnel, 'srem', function(key, value, callback) {
            removedKeys.push(key);
        });

        fresnel.createTask(task, function() {
            fresnel._executeTask(task);
        });

        beforeExit(function() {
            assert.ok(removedKeys.indexOf(fresnel._namespace("pending")) >= 0);
        });
    },
    "when tasks execute successfully, their task definition should be removed": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var removedKeys = [];

        var task = randomTask();

        replaceClientMethod(fresnel, 'del', function(key, callback) {
            removedKeys.push(key);
        });

        fresnel.createTask(task, function() {
            fresnel._executeTask(task);
        });

        beforeExit(function() {
            assert.ok(removedKeys.indexOf(fresnel._namespace("tasks:" + task.id)) >= 0);
        });
    },
}
<commit_msg>Tests for _getDefinitions()<commit_after>var assert = require('assert'),
    sys = require('sys'),
    redis = require('redis-client'),
    EventEmitter = require('events').EventEmitter;

var _fresnel = require('fresnel');
var Fresnel = _fresnel.Fresnel;

_fresnel.AUTO_CLOSE = true;

process.addListener('uncaughtException', function(err) {
    console.log("Caught exception: " + err);
});

function randomTask() {
    return {
        "class": randomString(),
        "args": []
    };
}

var CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

function randomString(length) {
    length = length || 16;
    var text = "";

    for (var i=0; i < length; i++) {
        text += CHARACTERS.charAt(Math.floor(Math.random() * CHARACTERS.length));
    }

    return text;
}

function range(end) {
    var range = [];
    for (var i = 0; i < end; i++) {
        range.push(i);
    }

    return range;
}

function replaceClientMethod(fresnel, method, func) {
    var _getClient = fresnel._getClient;

    fresnel._getClient = function() {
        var client = _getClient.apply(this);
        client[method] = function() {
            var callback = arguments[arguments.length - 1];
            callback(null, func.apply(null, arguments));
        };
        return client;
    }
}

module.exports = {
    'should be an EventEmitter': function(assert) {
        var fresnel = new Fresnel();
        assert.ok(fresnel instanceof EventEmitter);
    },
    'should buffer tasks into a local queue': function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        // create some tasks in Redis
        var task = randomTask();

        fresnel.createTask(task, function() {
            fresnel.bufferTasks(function() {
                fresnel.getUnbufferedQueueLength(function(length) {
                    assert.equal(0, length);
                });
            });
        });

        beforeExit(function() {
            assert.equal(task.toString(), fresnel.BUFFERED_TASKS[0].toString());
        });
    },
    'should mark buffered tasks as pending': function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        fresnel.createTask(randomTask(), function() {
            fresnel.bufferTasks(function() {
                fresnel.getPendingCount(function(count) {
                    assert.equal(1, count);
                });
            });
        });
    },
    'should buffer tasks with no callback': function(assert) {
        var fresnel = new Fresnel(randomString());

        fresnel.createTask(randomTask(), function() {
            fresnel.bufferTasks();
        });
    },
    'should succeed when no tasks are available to be buffered': function(assert) {
        var fresnel = new Fresnel(randomString());

        fresnel.bufferTasks();
    },
    'should succeed when no tasks are available to be buffered and no callback was provided': function(assert) {
        var fresnel = new Fresnel(randomString());

        fresnel.bufferTasks();
    },
    'Duplicate tasks should only be inserted once': function(assert) {
        var fresnel = new Fresnel(randomString());

        var task = randomTask();

        fresnel.createTask(task, function() {
            fresnel.createTask(task, function() {
                fresnel.getUnbufferedQueueLength(function(length) {
                    assert.equal(1, length);
                });
            });
        });
    },
    'Locally buffered tasks should be run': function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var task = randomTask();
        task.id = "1234";

        fresnel.BUFFERED_TASKS = [task];

        fresnel.runBufferedTasks();

        beforeExit(function() {
            assert.equal(0, fresnel.BUFFERED_TASKS.length);
        });
    },
    'should create tasks with no callback': function(assert) {
        var fresnel = new Fresnel(randomString());

        fresnel.createTask(randomTask());
    },
    "shouldn't fail when creating a duplicate task with no callback": function(assert) {
        var fresnel = new Fresnel(randomString());

        var task = randomTask();

        fresnel.createTask(task, function() {
            fresnel.createTask(task);
        });
    },
    "should add to the 'tasks' set when creating tasks": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var calledWithKey;

        replaceClientMethod(fresnel, 'sadd', function(key, value, callback) {
            calledWithKey = key;
        });

        fresnel.createTask(randomTask());

        beforeExit(function() {
            assert.equal(fresnel._namespace("tasks"), calledWithKey);
        });
    },
    "should add to the 'queue' sorted set when creating tasks": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var calledWithKey;

        replaceClientMethod(fresnel, 'zadd', function(key, score, value, callback) {
            calledWithKey = key;
        });

        fresnel.createTask(randomTask());

        beforeExit(function() {
            assert.equal(fresnel._namespace("queue"), calledWithKey);
        });
    },
    "should form a task definition when creating tasks": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var calledWithKey;

        replaceClientMethod(fresnel, 'set', function(key, value, callback) {
            calledWithKey = key;
        });

        var task = randomTask();

        fresnel.createTask(task);

        beforeExit(function() {
            assert.equal(fresnel._namespace("tasks:" + task.id), calledWithKey);
        });
    },
    "update definition should store an internal definition": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var resultTask;

        var taskId = 42;
        var task = randomTask();
        assert.ok(task.id == null);

        fresnel._getClient = function() {
            return {
                "set": function(key, value) {
                    resultTask = JSON.parse(value);
                }
            };
        }

        fresnel._updateDefinition(taskId, task);

        beforeExit(function() {
            assert.equal(taskId, resultTask.id);
        });
    },
    "_getDefinitions should load multiple task definitions": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var tasks = [];
        var taskIds = [];
        var taskDefs = [];

        var insertCount = 0;

        for (var i = 0; i < 5; i++) {
            tasks.push(randomTask());
        }

        tasks.forEach(function(task) {
            var taskId;
            do {
                taskId = Math.floor(Math.random() * 10);
            } while (taskIds.indexOf(taskId) >= 0);

            taskIds.push(taskId);
            task.id = taskId;

            fresnel._updateDefinition(taskId, task, function() {
                if (++insertCount == tasks.length) {
                    fresnel._getDefinitions(taskIds.slice(0, 2), function(defs) {
                        taskDefs = defs;
                    });
                }
            });
        });

        beforeExit(function() {
            assert.eql(tasks.slice(0, 2), taskDefs);
        });
    },
    "_getDefinitions should load individual task definitions": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var task = randomTask();
        var taskDefs;
        task.id = Math.floor(Math.random() * 10);

        fresnel._updateDefinition(task.id, task, function() {
            fresnel._getDefinitions(task.id, function(defs) {
                taskDefs = defs;
            });
        });

        beforeExit(function() {
            assert.eql(task, taskDefs[0]);
        });
    },
    "hash function should only consider public fields": function(assert) {
        var fresnel = new Fresnel(randomString());

        var task = randomTask();
        var hash = fresnel._hash(task);

        task.id = "1234";

        assert.equal(hash, fresnel._hash(task));
    },
    "when tasks execute successfully, they should be removed from the 'tasks' set": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var removedKeys = [];

        var task = randomTask();

        replaceClientMethod(fresnel, 'srem', function(key, value, callback) {
            removedKeys.push(key);
        });

        fresnel.createTask(task, function() {
            fresnel._executeTask(task);
        });

        beforeExit(function() {
            assert.ok(removedKeys.indexOf(fresnel._namespace("tasks")) >= 0);
        });
    },
    "when tasks execute successfully, they should be removed from the 'pending' set": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var removedKeys = [];

        var task = randomTask();

        replaceClientMethod(fresnel, 'srem', function(key, value, callback) {
            removedKeys.push(key);
        });

        fresnel.createTask(task, function() {
            fresnel._executeTask(task);
        });

        beforeExit(function() {
            assert.ok(removedKeys.indexOf(fresnel._namespace("pending")) >= 0);
        });
    },
    "when tasks execute successfully, their task definition should be removed": function(assert, beforeExit) {
        var fresnel = new Fresnel(randomString());

        var removedKeys = [];

        var task = randomTask();

        replaceClientMethod(fresnel, 'del', function(key, callback) {
            removedKeys.push(key);
        });

        fresnel.createTask(task, function() {
            fresnel._executeTask(task);
        });

        beforeExit(function() {
            assert.ok(removedKeys.indexOf(fresnel._namespace("tasks:" + task.id)) >= 0);
        });
    },
}
<|endoftext|>