<commit_before>"use strict";

var referee = require("@sinonjs/referee");
var sinon = require("../../lib/sinon");
var createStub = require("../../lib/sinon/stub");
var assert = referee.assert;
var refute = referee.refute;
var globalXHR = global.XMLHttpRequest;
var globalAXO = global.ActiveXObject;

describe("issues", function () {
    beforeEach(function () {
        this.sandbox = sinon.createSandbox();
    });

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

    it("#283", function () {
        function testSinonFakeTimersWith(interval, ticks) {
            var clock = sinon.useFakeTimers();

            var spy = sinon.spy();
            var id = setInterval(spy, interval);
            assert(!spy.calledOnce);
            clock.tick(ticks);
            assert(spy.callCount === Math.floor(ticks / interval));

            clearInterval(id);
            clock.restore();
        }

        testSinonFakeTimersWith(10, 101);
        testSinonFakeTimersWith(99, 101);
        testSinonFakeTimersWith(100, 200);
        testSinonFakeTimersWith(199, 200);
        testSinonFakeTimersWith(500, 1001);
        testSinonFakeTimersWith(1000, 1001);
    });

    describe("#458", function () {
        if (typeof require("fs").readFileSync !== "undefined") {
            describe("on node", function () {
                it("stub out fs.readFileSync", function () {
                    var fs = require("fs");
                    var testCase = this;

                    refute.exception(function () {
                        testCase.sandbox.stub(fs, "readFileSync");
                    });
                });
            });
        }
    });

    describe("#624", function () {
        // eslint-disable-next-line mocha/no-skipped-tests
        it.skip("useFakeTimers should be idempotent", function () {
            // Issue #624 shows that useFakeTimers is not idempotent when it comes to
            // using Date.now
            // This test verifies that it's working, at least for Date.now
            var clock;

            clock = sinon.useFakeTimers(new Date("2014-12-29").getTime());
            assert.equals(clock.now, Date.now());

            clock = sinon.useFakeTimers(new Date("2015-12-15").getTime());
            assert.equals(clock.now, Date.now());

            clock = sinon.useFakeTimers(new Date("2015-1-5").getTime());
            assert.equals(clock.now, Date.now());
        });
    });

    describe("#852 - createStubInstance on intherited constructors", function () {
        it("must not throw error", function () {
            var A = function () {};
            var B = function () {};

            B.prototype = Object.create(A.prototype);
            B.prototype.constructor = A;

            refute.exception(function () {
                sinon.createStubInstance(B);
            });
        });
    });

    describe("#852(2) - createStubInstance should on same constructor", function () {
        it("must be idempotent", function () {
            var A = function () {};
            refute.exception(function () {
                sinon.createStubInstance(A);
                sinon.createStubInstance(A);
            });
        });
    });

    describe("#950 - first execution of a spy as a method renames that spy", function () {
        function bob() {}

        // IE 11 does not support the function name property
        if (bob.name) {
            it("should not rename spies", function () {
                var expectedName = "proxy";
                var spy = sinon.spy(bob);

                assert.equals(spy.name, expectedName);

                var obj = { methodName: spy };
                assert.equals(spy.name, expectedName);

                spy();
                assert.equals(spy.name, expectedName);

                obj.methodName.call(null);
                assert.equals(spy.name, expectedName);

                obj.methodName();
                assert.equals(spy.name, expectedName);

                obj.otherProp = spy;
                obj.otherProp();
                assert.equals(spy.name, expectedName);
            });
        }
    });

    describe("#1026", function () {
        it("should stub `watch` method on any Object", function () {
            // makes sure that Object.prototype.watch is set back to its old value
            function restore(oldWatch) {
                if (oldWatch) {
                    Object.prototype.watch = oldWatch; // eslint-disable-line no-extend-native
                } else {
                    delete Object.prototype.watch;
                }
            }

            try { // eslint-disable-line no-restricted-syntax
                var oldWatch = Object.prototype.watch;

                if (typeof Object.prototype.watch !== "function") {
                    Object.prototype.watch = function rolex() {}; // eslint-disable-line no-extend-native
                }

                var stubbedObject = sinon.stub({
                    watch: function () {}
                });

                stubbedObject.watch();

                assert.isArray(stubbedObject.watch.args);
            } catch (error) {
                restore(oldWatch);
                throw error;
            }

            restore(oldWatch);
        });
    });

    describe("#1154", function () {
        it("Ensures different matchers will not be tested against each other", function () {
            var match = sinon.match;
            var stub = sinon.stub;
            var readFile = stub();

            function endsWith(str, suffix) {
                return str.indexOf(suffix) + suffix.length === str.length;
            }

            function suffixA(fileName) {
                return endsWith(fileName, "suffixa");
            }

            function suffixB(fileName) {
                return endsWith(fileName, "suffixb");
            }

            var argsA = match(suffixA);
            var argsB = match(suffixB);

            var firstFake = readFile
                .withArgs(argsA);

            var secondFake = readFile
                .withArgs(argsB);

            assert(firstFake !== secondFake);
        });
    });

    describe("#1372 - sandbox.resetHistory", function () {
        it("should reset spies", function () {
            var spy = this.sandbox.spy();

            spy();
            assert.equals(spy.callCount, 1);

            spy();
            assert.equals(spy.callCount, 2);

            this.sandbox.resetHistory();

            spy();
            assert.equals(spy.callCount, 1); // should not fail but fails
        });
    });

    describe("#1398", function () {
        it("Call order takes into account both calledBefore and callCount", function () {
            var s1 = sinon.spy();
            var s2 = sinon.spy();

            s1();
            s2();
            s1();

            assert.exception(function () {
                sinon.assert.callOrder(s2, s1, s2);
            });
        });
    });

    describe("#1474 - promise library should be propagated through fakes and behaviors", function () {

        var stub;

        function makeAssertions(fake, expected) {
            assert.isFunction(fake.then);
            assert.isFunction(fake.tap);

            assert.equals(fake.tap(), expected);
        }

        before(function () {
            if (!global.Promise) { this.skip(); }
        });

        beforeEach(function () {
            var promiseLib = {
                resolve: function (value) {
                    var promise = Promise.resolve(value);
                    promise.tap = function () {
                        return "tap " + value;
                    };

                    return promise;
                }
            };

            stub = sinon.stub().usingPromise(promiseLib);

            stub.resolves("resolved");
        });

        it("stub.onCall", function () {
            stub.onSecondCall().resolves("resolved again");

            makeAssertions(stub(), "tap resolved");
            makeAssertions(stub(), "tap resolved again");
        });

        it("stub.withArgs", function () {
            stub.withArgs(42).resolves("resolved again");
            stub.withArgs(true).resolves("okay");

            makeAssertions(stub(), "tap resolved");
            makeAssertions(stub(42), "tap resolved again");
            makeAssertions(stub(true), "tap okay");
        });
    });

    describe("#1456", function () {
        var sandbox;

        function throwsOnUnconfigurableProperty() {
            /* eslint-disable no-restricted-syntax */
            try {
                var preDescriptor = Object.getOwnPropertyDescriptor(window, "innerHeight"); //backup val
                Object.defineProperty(window, "innerHeight", { value: 10, configureable: true, writeable: true });
                Object.defineProperty(window, "innerHeight", preDescriptor); //restore
                return false;
            } catch (err) {
                return true;
            }
            /* eslint-enable no-restricted-syntax */
        }

        beforeEach(function () {
            if (typeof window === "undefined" || throwsOnUnconfigurableProperty()) { this.skip(); }

            sandbox = sinon.createSandbox();
        });

        afterEach(function () {
            sandbox.restore();
        });

        it("stub window innerHeight", function () {
            sandbox.stub(window, "innerHeight").value(111);

            assert.equals(window.innerHeight, 111);
        });
    });

    describe("#1487 - withArgs() returnValue", function () {
        beforeEach(function () {
            this.stub = createStub().throws("Nothing set");
            this.stub.withArgs("arg").returns("return value");
            this.stub("arg");
        });

        it("sets correct firstCall.returnValue", function () {
            assert.equals(this.stub.withArgs("arg").firstCall.returnValue, "return value");
        });

        it("sets correct lastCall.returnValue", function () {
            assert.equals(this.stub.withArgs("arg").lastCall.returnValue, "return value");
        });
    });

    describe("#1512 - sandbox.stub(obj,protoMethod)", function () {
        var sandbox;

        beforeEach(function () {
            sandbox = sinon.createSandbox();
        });

        afterEach(function () {
            sandbox.restore();
        });

        it("can stub methods on the prototype", function () {
            var proto = { someFunction: function () {} };
            var instance = Object.create(proto);

            var stub = sandbox.stub(instance, "someFunction");
            instance.someFunction();
            assert(stub.called);
        });
    });

    describe("#1521 - stubbing Array.prototype.filter", function () {
        var orgFilter;

        before(function () {
            orgFilter = Array.prototype.filter;
        });

        afterEach(function () {
            /* eslint-disable no-extend-native */
            Array.prototype.filter = orgFilter;
        });

        it("should be possible stub filter", function () {
            var stub = sinon.stub(Array.prototype, "filter");
            [1, 2, 3].filter(function () { return false; });
            assert(stub.calledOnce);
        });

    });

    describe("#1531 - some copied functions on root sinon module throw", function () {
        it("should create a fake server without throwing", function () {
            refute.exception(function () {
                sinon.createFakeServer();
            });
        });

        it("should create a fake server with clock without throwing", function () {
            refute.exception(function () {
                sinon.createFakeServerWithClock();
            });
        });
    });

    describe("#1442 - callThrough with a mock expectation", function () {
        it("should call original method", function () {
            var foo = {
                bar: function () { }
            };

            var mock = this.sandbox.mock(foo);
            mock.expects("bar").callThrough();

            foo.bar();

            mock.verify();
        });
    });

    describe("#1648 - resetHistory ", function () {
        it("should reset property spies", function () {
            var obj = {
                func: function () {},
                get prop() {
                    return 1;
                }
            };

            var sandbox = sinon.createSandbox();
            var spyFunc = sandbox.spy(obj, "func");
            var spyProp = sandbox.spy(obj, "prop", ["get"]);

            refute.isTrue(spyFunc.called);
            refute.isTrue(spyProp.get.called);

            obj.func();
            //eslint-disable-next-line no-unused-expressions
            obj.prop;

            assert.isTrue(spyFunc.called);
            assert.isTrue(spyProp.get.called);

            sandbox.resetHistory();

            refute.isTrue(spyFunc.called);
            refute.isTrue(spyProp.get.called);
        });
    });

    // this error was caused by overwriting methods with imported ones don't use the collection
    // and thus were not restorable
    describe("#1775 - sinon.restore", function () {
        it("should restore all stubs", function () {
            var myApi = {
                someMethod: function someMethod() {
                    // eslint-disable-next-line no-console
                    console.log("test method!");
                }
            };

            sinon.stub(myApi, "someMethod");
            sinon.restore();
            sinon.stub(myApi, "someMethod");
            // TypeError: Attempted to wrap someMethod which is already wrapped
        });

        it("should restore all spies", function () {
            var myApi = {
                someMethod: function someMethod() {
                    // eslint-disable-next-line no-console
                    console.log("test method!");
                }
            };

            sinon.spy(myApi, "someMethod");
            sinon.restore();
            sinon.spy(myApi, "someMethod");
            // TypeError: Attempted to wrap someMethod which is already wrapped
        });

        it("should restore all mocks", function () {
            var myApi = {
                someMethod: function someMethod() {
                    // eslint-disable-next-line no-console
                    console.log("test method!");
                }
            };

            sinon.mock(myApi);
            sinon.restore();
            sinon.mock(myApi);
            // TypeError: Attempted to wrap someMethod which is already wrapped
        });
    });

    describe("#1801 - sinon.restore spied fakeTimers", function () {
        it("should restore spied fake timers", function () {
            var originalSetTimeout = setTimeout;

            sinon.useFakeTimers();
            sinon.spy(global, "setTimeout");

            sinon.restore();

            assert.same(originalSetTimeout, global.setTimeout, "fakeTimers restored");
        });
    });

    describe("#1840 - sinon.restore useFakeXMLHttpRequest", function () {
        it("should restore XMLHttpRequest and ActiveXObject", function () {
            sinon.useFakeXMLHttpRequest();
            sinon.restore();

            assert.same(global.XMLHttpRequest, globalXHR);
            assert.same(global.ActiveXObject, globalAXO);
        });

    });

    describe("#1709 - deepEqual fails on cyclic references", function () {
        it("should not blow up", function () {
            var spy = sinon.spy();

            var firstObj = {};
            firstObj.aKeyName = firstObj;

            var secondObj = {};
            secondObj.aKeyName = secondObj;

            spy(firstObj);

            sinon.assert.calledWith(spy, secondObj);
        });
    });

    describe("#1796 - cannot stub Array.prototype.sort", function () {
        it("it should not fail with RangeError", function () {
            var stub = sinon.stub(Array.prototype, "sort");
            [1, 2, 3].sort();
            stub.restore();
        });
    });
});
<commit_msg>Review: add assertion<commit_after>"use strict";

var referee = require("@sinonjs/referee");
var sinon = require("../../lib/sinon");
var createStub = require("../../lib/sinon/stub");
var assert = referee.assert;
var refute = referee.refute;
var globalXHR = global.XMLHttpRequest;
var globalAXO = global.ActiveXObject;

describe("issues", function () {
    beforeEach(function () {
        this.sandbox = sinon.createSandbox();
    });

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

    it("#283", function () {
        function testSinonFakeTimersWith(interval, ticks) {
            var clock = sinon.useFakeTimers();

            var spy = sinon.spy();
            var id = setInterval(spy, interval);
            assert(!spy.calledOnce);
            clock.tick(ticks);
            assert(spy.callCount === Math.floor(ticks / interval));

            clearInterval(id);
            clock.restore();
        }

        testSinonFakeTimersWith(10, 101);
        testSinonFakeTimersWith(99, 101);
        testSinonFakeTimersWith(100, 200);
        testSinonFakeTimersWith(199, 200);
        testSinonFakeTimersWith(500, 1001);
        testSinonFakeTimersWith(1000, 1001);
    });

    describe("#458", function () {
        if (typeof require("fs").readFileSync !== "undefined") {
            describe("on node", function () {
                it("stub out fs.readFileSync", function () {
                    var fs = require("fs");
                    var testCase = this;

                    refute.exception(function () {
                        testCase.sandbox.stub(fs, "readFileSync");
                    });
                });
            });
        }
    });

    describe("#624", function () {
        // eslint-disable-next-line mocha/no-skipped-tests
        it.skip("useFakeTimers should be idempotent", function () {
            // Issue #624 shows that useFakeTimers is not idempotent when it comes to
            // using Date.now
            // This test verifies that it's working, at least for Date.now
            var clock;

            clock = sinon.useFakeTimers(new Date("2014-12-29").getTime());
            assert.equals(clock.now, Date.now());

            clock = sinon.useFakeTimers(new Date("2015-12-15").getTime());
            assert.equals(clock.now, Date.now());

            clock = sinon.useFakeTimers(new Date("2015-1-5").getTime());
            assert.equals(clock.now, Date.now());
        });
    });

    describe("#852 - createStubInstance on intherited constructors", function () {
        it("must not throw error", function () {
            var A = function () {};
            var B = function () {};

            B.prototype = Object.create(A.prototype);
            B.prototype.constructor = A;

            refute.exception(function () {
                sinon.createStubInstance(B);
            });
        });
    });

    describe("#852(2) - createStubInstance should on same constructor", function () {
        it("must be idempotent", function () {
            var A = function () {};
            refute.exception(function () {
                sinon.createStubInstance(A);
                sinon.createStubInstance(A);
            });
        });
    });

    describe("#950 - first execution of a spy as a method renames that spy", function () {
        function bob() {}

        // IE 11 does not support the function name property
        if (bob.name) {
            it("should not rename spies", function () {
                var expectedName = "proxy";
                var spy = sinon.spy(bob);

                assert.equals(spy.name, expectedName);

                var obj = { methodName: spy };
                assert.equals(spy.name, expectedName);

                spy();
                assert.equals(spy.name, expectedName);

                obj.methodName.call(null);
                assert.equals(spy.name, expectedName);

                obj.methodName();
                assert.equals(spy.name, expectedName);

                obj.otherProp = spy;
                obj.otherProp();
                assert.equals(spy.name, expectedName);
            });
        }
    });

    describe("#1026", function () {
        it("should stub `watch` method on any Object", function () {
            // makes sure that Object.prototype.watch is set back to its old value
            function restore(oldWatch) {
                if (oldWatch) {
                    Object.prototype.watch = oldWatch; // eslint-disable-line no-extend-native
                } else {
                    delete Object.prototype.watch;
                }
            }

            try { // eslint-disable-line no-restricted-syntax
                var oldWatch = Object.prototype.watch;

                if (typeof Object.prototype.watch !== "function") {
                    Object.prototype.watch = function rolex() {}; // eslint-disable-line no-extend-native
                }

                var stubbedObject = sinon.stub({
                    watch: function () {}
                });

                stubbedObject.watch();

                assert.isArray(stubbedObject.watch.args);
            } catch (error) {
                restore(oldWatch);
                throw error;
            }

            restore(oldWatch);
        });
    });

    describe("#1154", function () {
        it("Ensures different matchers will not be tested against each other", function () {
            var match = sinon.match;
            var stub = sinon.stub;
            var readFile = stub();

            function endsWith(str, suffix) {
                return str.indexOf(suffix) + suffix.length === str.length;
            }

            function suffixA(fileName) {
                return endsWith(fileName, "suffixa");
            }

            function suffixB(fileName) {
                return endsWith(fileName, "suffixb");
            }

            var argsA = match(suffixA);
            var argsB = match(suffixB);

            var firstFake = readFile
                .withArgs(argsA);

            var secondFake = readFile
                .withArgs(argsB);

            assert(firstFake !== secondFake);
        });
    });

    describe("#1372 - sandbox.resetHistory", function () {
        it("should reset spies", function () {
            var spy = this.sandbox.spy();

            spy();
            assert.equals(spy.callCount, 1);

            spy();
            assert.equals(spy.callCount, 2);

            this.sandbox.resetHistory();

            spy();
            assert.equals(spy.callCount, 1); // should not fail but fails
        });
    });

    describe("#1398", function () {
        it("Call order takes into account both calledBefore and callCount", function () {
            var s1 = sinon.spy();
            var s2 = sinon.spy();

            s1();
            s2();
            s1();

            assert.exception(function () {
                sinon.assert.callOrder(s2, s1, s2);
            });
        });
    });

    describe("#1474 - promise library should be propagated through fakes and behaviors", function () {

        var stub;

        function makeAssertions(fake, expected) {
            assert.isFunction(fake.then);
            assert.isFunction(fake.tap);

            assert.equals(fake.tap(), expected);
        }

        before(function () {
            if (!global.Promise) { this.skip(); }
        });

        beforeEach(function () {
            var promiseLib = {
                resolve: function (value) {
                    var promise = Promise.resolve(value);
                    promise.tap = function () {
                        return "tap " + value;
                    };

                    return promise;
                }
            };

            stub = sinon.stub().usingPromise(promiseLib);

            stub.resolves("resolved");
        });

        it("stub.onCall", function () {
            stub.onSecondCall().resolves("resolved again");

            makeAssertions(stub(), "tap resolved");
            makeAssertions(stub(), "tap resolved again");
        });

        it("stub.withArgs", function () {
            stub.withArgs(42).resolves("resolved again");
            stub.withArgs(true).resolves("okay");

            makeAssertions(stub(), "tap resolved");
            makeAssertions(stub(42), "tap resolved again");
            makeAssertions(stub(true), "tap okay");
        });
    });

    describe("#1456", function () {
        var sandbox;

        function throwsOnUnconfigurableProperty() {
            /* eslint-disable no-restricted-syntax */
            try {
                var preDescriptor = Object.getOwnPropertyDescriptor(window, "innerHeight"); //backup val
                Object.defineProperty(window, "innerHeight", { value: 10, configureable: true, writeable: true });
                Object.defineProperty(window, "innerHeight", preDescriptor); //restore
                return false;
            } catch (err) {
                return true;
            }
            /* eslint-enable no-restricted-syntax */
        }

        beforeEach(function () {
            if (typeof window === "undefined" || throwsOnUnconfigurableProperty()) { this.skip(); }

            sandbox = sinon.createSandbox();
        });

        afterEach(function () {
            sandbox.restore();
        });

        it("stub window innerHeight", function () {
            sandbox.stub(window, "innerHeight").value(111);

            assert.equals(window.innerHeight, 111);
        });
    });

    describe("#1487 - withArgs() returnValue", function () {
        beforeEach(function () {
            this.stub = createStub().throws("Nothing set");
            this.stub.withArgs("arg").returns("return value");
            this.stub("arg");
        });

        it("sets correct firstCall.returnValue", function () {
            assert.equals(this.stub.withArgs("arg").firstCall.returnValue, "return value");
        });

        it("sets correct lastCall.returnValue", function () {
            assert.equals(this.stub.withArgs("arg").lastCall.returnValue, "return value");
        });
    });

    describe("#1512 - sandbox.stub(obj,protoMethod)", function () {
        var sandbox;

        beforeEach(function () {
            sandbox = sinon.createSandbox();
        });

        afterEach(function () {
            sandbox.restore();
        });

        it("can stub methods on the prototype", function () {
            var proto = { someFunction: function () {} };
            var instance = Object.create(proto);

            var stub = sandbox.stub(instance, "someFunction");
            instance.someFunction();
            assert(stub.called);
        });
    });

    describe("#1521 - stubbing Array.prototype.filter", function () {
        var orgFilter;

        before(function () {
            orgFilter = Array.prototype.filter;
        });

        afterEach(function () {
            /* eslint-disable no-extend-native */
            Array.prototype.filter = orgFilter;
        });

        it("should be possible stub filter", function () {
            var stub = sinon.stub(Array.prototype, "filter");
            [1, 2, 3].filter(function () { return false; });
            assert(stub.calledOnce);
        });

    });

    describe("#1531 - some copied functions on root sinon module throw", function () {
        it("should create a fake server without throwing", function () {
            refute.exception(function () {
                sinon.createFakeServer();
            });
        });

        it("should create a fake server with clock without throwing", function () {
            refute.exception(function () {
                sinon.createFakeServerWithClock();
            });
        });
    });

    describe("#1442 - callThrough with a mock expectation", function () {
        it("should call original method", function () {
            var foo = {
                bar: function () { }
            };

            var mock = this.sandbox.mock(foo);
            mock.expects("bar").callThrough();

            foo.bar();

            mock.verify();
        });
    });

    describe("#1648 - resetHistory ", function () {
        it("should reset property spies", function () {
            var obj = {
                func: function () {},
                get prop() {
                    return 1;
                }
            };

            var sandbox = sinon.createSandbox();
            var spyFunc = sandbox.spy(obj, "func");
            var spyProp = sandbox.spy(obj, "prop", ["get"]);

            refute.isTrue(spyFunc.called);
            refute.isTrue(spyProp.get.called);

            obj.func();
            //eslint-disable-next-line no-unused-expressions
            obj.prop;

            assert.isTrue(spyFunc.called);
            assert.isTrue(spyProp.get.called);

            sandbox.resetHistory();

            refute.isTrue(spyFunc.called);
            refute.isTrue(spyProp.get.called);
        });
    });

    // this error was caused by overwriting methods with imported ones don't use the collection
    // and thus were not restorable
    describe("#1775 - sinon.restore", function () {
        it("should restore all stubs", function () {
            var myApi = {
                someMethod: function someMethod() {
                    // eslint-disable-next-line no-console
                    console.log("test method!");
                }
            };

            sinon.stub(myApi, "someMethod");
            sinon.restore();
            sinon.stub(myApi, "someMethod");
            // TypeError: Attempted to wrap someMethod which is already wrapped
        });

        it("should restore all spies", function () {
            var myApi = {
                someMethod: function someMethod() {
                    // eslint-disable-next-line no-console
                    console.log("test method!");
                }
            };

            sinon.spy(myApi, "someMethod");
            sinon.restore();
            sinon.spy(myApi, "someMethod");
            // TypeError: Attempted to wrap someMethod which is already wrapped
        });

        it("should restore all mocks", function () {
            var myApi = {
                someMethod: function someMethod() {
                    // eslint-disable-next-line no-console
                    console.log("test method!");
                }
            };

            sinon.mock(myApi);
            sinon.restore();
            sinon.mock(myApi);
            // TypeError: Attempted to wrap someMethod which is already wrapped
        });
    });

    describe("#1801 - sinon.restore spied fakeTimers", function () {
        it("should restore spied fake timers", function () {
            var originalSetTimeout = setTimeout;

            sinon.useFakeTimers();
            sinon.spy(global, "setTimeout");

            sinon.restore();

            assert.same(originalSetTimeout, global.setTimeout, "fakeTimers restored");
        });
    });

    describe("#1840 - sinon.restore useFakeXMLHttpRequest", function () {
        it("should restore XMLHttpRequest and ActiveXObject", function () {
            sinon.useFakeXMLHttpRequest();
            sinon.restore();

            assert.same(global.XMLHttpRequest, globalXHR);
            assert.same(global.ActiveXObject, globalAXO);
        });

    });

    describe("#1709 - deepEqual fails on cyclic references", function () {
        it("should not blow up", function () {
            var spy = sinon.spy();

            var firstObj = {};
            firstObj.aKeyName = firstObj;

            var secondObj = {};
            secondObj.aKeyName = secondObj;

            spy(firstObj);

            sinon.assert.calledWith(spy, secondObj);
        });
    });

    describe("#1796 - cannot stub Array.prototype.sort", function () {
        it("it should not fail with RangeError", function () {
            refute.exception(function () {
                var stub = sinon.stub(Array.prototype, "sort");
                [1, 2, 3].sort();
                stub.restore();
            });
        });
    });
});
<|endoftext|>


<commit_before>var parseGenbank = require('../parsers/genbankToJSON');
var jsonToGenbank = require('../parsers/jsonToGenbank');
var path = require("path");
var fs = require('fs');
var chai = require('chai');
var chaiSubset = require('chai-subset');
chai.use(chaiSubset);
chai.use(require('chai-things'));
chai.should();
describe('genbank exporter/parser conversion', function() {
    it('can interconvert between our parser and our exporter with a malformed genbank', function(done) {
        var string = fs.readFileSync(path.join(__dirname, './testData/breakingGenbank.gb'), "utf8");
        parseGenbank(string, function(result) {
            var feat1 = {
                notes: {},
                name: 'araC',
                start: 6,
                end: 882,
                type: 'CDS',
                strand: -1
            }
            var feat2 = {
                notes: {},
                name: 'T0',
                start: 4300,
                end: 4403,
                type: 'terminator',
                strand: 1
            }
            result.should.be.an('array');
            result[0].success.should.be.true;
            result[0].parsedSequence.features.should.be.length(13);
            result[0].parsedSequence.features.should.include.something.that.deep.equals(feat1);
            result[0].parsedSequence.features.should.include.something.that.deep.equals(feat2);
            var exportedGenbankString = jsonToGenbank(result[0].parsedSequence);
            parseGenbank(exportedGenbankString, function(result) {
                result.should.be.an('array');
                result[0].success.should.be.true;
                result[0].parsedSequence.features.should.be.length(13);

                result[0].parsedSequence.features.should.include.something.that.deep.equals(feat1);
                result[0].parsedSequence.features.should.include.something.that.deep.equals(feat2);
                done();
            });
        });
    });

    it('parses and converts pj5_00001 (aka testGenbankFile.gb) correctly', function(done) {
        var string = fs.readFileSync(path.join(__dirname, './testData/genbank/testGenbankFile.gb'), "utf8");
        parseGenbank(string, function(result) {
            result[0].parsedSequence.name.should.equal('pj5_00001');
            result[0].parsedSequence.circular.should.equal(true);
            result[0].parsedSequence.extraLines.length.should.equal(3);
            result[0].parsedSequence.features.length.should.equal(21);
            result[0].parsedSequence.features.should.include.something.that.deep.equals({
                notes: {
                    pragma: ['Teselagen_Part'],
                    preferred3PrimeOverhangs: [''],
                    preferred5PrimeOverhangs: ['']
                },
                name: 'pS8c-gfpuv_sig_pep_vector_backbone',
                start: 1238,
                end: 1234,
                type: 'misc_feature',
                strand: 1
            });
            result[0].parsedSequence.sequence.length.should.equal(5299);
            var exportedGenbankString = jsonToGenbank(result[0].parsedSequence);
            console.log('exportedGenbankString: ' + exportedGenbankString);
            parseGenbank(exportedGenbankString, function(result) {
                result[0].parsedSequence.name.should.equal('pj5_00001');
                result[0].parsedSequence.circular.should.equal(true);
                result[0].parsedSequence.extraLines.length.should.equal(3);
                result[0].parsedSequence.features.length.should.equal(21);
                result[0].parsedSequence.features.should.include.something.that.deep.equals({
                    notes: {
                        pragma: ['Teselagen_Part'],
                        preferred3PrimeOverhangs: [''],
                        preferred5PrimeOverhangs: ['']
                    },
                    name: 'pS8c-gfpuv_sig_pep_vector_backbone',
                    start: 1238,
                    end: 1234,
                    type: 'misc_feature',
                    strand: 1
                });
                result[0].parsedSequence.sequence.length.should.equal(5299);
                done();
            });
        });
    });

    it('parses and converts a genbank with just feature start locations correctly', function(done) {
        var string = fs.readFileSync(path.join(__dirname, './testData/rhaBp-Pfu-pUN_alt.gb'), "utf8");
        parseGenbank(string, function(result) {
            result.should.be.an('array');
            result[0].success.should.be.true;
            result[0].parsedSequence.features.should.containSubset([{
                name: 'mutation',
                start: 264,
                end: 264,
            },{
                name: 'TSS',
                start: 291,
                end: 291,
            }]);
            var exportedGenbankString = jsonToGenbank(result[0].parsedSequence);
            parseGenbank(exportedGenbankString, function(result) {
                result.should.be.an('array');
                result[0].success.should.be.true;
                result[0].parsedSequence.features.should.containSubset([{
                    name: 'mutation',
                    start: 264,
                    end: 264,
                },{
                    name: 'TSS',
                    start: 291,
                    end: 291,
                }]);
                done();
            });
        });
    });

    // it('parses a genbank that is implicitly non-circular as circular because it contains circular features', function(done) {
    //     var string = fs.readFileSync(path.join(__dirname, './testData/Ecoli_DERA_Implicitly_Circular.gb'), "utf8");
    //     parseGenbank(string, function(result) {
    //         result.should.be.an('array');
    //         result[0].success.should.be.true;
    //         result[0].parsedSequence.circular.should.equal(true);
    //         result[0].parsedSequence.features.should.containSubset([{
    //             name: 'rhaBADp',
    //             start: 410,
    //             end: 182,
    //         }]);
    //         done();
    //     });
    // });

    // it('parses a genbank that is implicitly linear and has no circular featuers as linear', function(done) {
    //     var string = fs.readFileSync(path.join(__dirname, './testData/Ecoli_DERA_Implicitly_Linear.gb'), "utf8");
    //     parseGenbank(string, function(result) {
    //         result.should.be.an('array');
    //         result[0].success.should.be.true;
    //         result[0].parsedSequence.circular.should.equal(false);
    //         done();
    //     });
    // });

    // it('parses plasmid with run-on feature note (pBbS0c-RFP.gb) correctly', function(done) {
    //     var string = fs.readFileSync(path.join(__dirname, './testData/pBbS0c-RFP.gb'), "utf8");
    //     parseGenbank(string, function(result) {
    //         // console.log('JSON.stringify(result,null,4): ' + JSON.stringify(result,null,4));
    //         result[0].parsedSequence.features.should.include.something.that.deep.equals({
    //             notes: {
    //                 note: [
    //                     "REP_ORIGIN REP_ORIGIN pSC101* aka pMPP6, gives plasmid number 3 -4 copies per cell, BglII site in pSC101* ori has been dele ted by quick change agatcT changed to agatcA giving pSC101* * pSC101* aka pMPP6, gives plasmid number 3-4copies p er cell, BglII site in pSC101* ori has been deleted by quic k change agatcT changed to agatcA giving pSC101** [pBbS0a-RFP]",
    //                     "pSC101* aka pMPP6, gives plasmid number 3-4 copies per cell, BglII site in pSC101* ori has been deleted by quic k change agatcT changed to agatcA giving pSC101**"
    //                 ],
    //                 gene: ["SC101** Ori"],
    //                 vntifkey: ["33"]
    //             },
    //             name: 'pSC101**',
    //             start: 1073,
    //             end: 3301,
    //             type: 'rep_origin',
    //             strand: -1
    //         });
    //         result.should.be.an('array');
    //         result.should.be.length(1);
    //         result[0].parsedSequence.features.should.be.length(5);
    //         result[0].parsedSequence.circular.should.equal(true);
    //         // console.log('result: ' + JSON.stringify(result,null,4));
    //         result[0].parsedSequence.size.should.equal(4224);
    //         done();
    //     });
    // });
    // it('parses pBbE0c-RFP.gb correctly', function(done) {
    //     var string = fs.readFileSync(path.join(__dirname, './testData/pBbE0c-RFP.gb'), "utf8");
    //     parseGenbank(string, function(result) {
    //         result.should.be.an('array');
    //         result.should.be.length(1);
    //         result[0].parsedSequence.features.should.be.length(4);
    //         result[0].parsedSequence.circular.should.equal(true);
    //         // console.log('result: ' + JSON.stringify(result,null,4));
    //         result[0].parsedSequence.size.should.equal(2815);
    //         result[0].parsedSequence.features.should.include.something.that.deep.equals({
    //             notes: {
    //                 note: ["GENE [ZFP-GG destination LacUV5 p15A CmR]", "[ZFP-GG destination LacUV5 p15A CmR]"],
    //                 vntifkey: ["22"],
    //                 gene: ["CmR"]
    //             },
    //             name: 'CmR',
    //             start: 2010,
    //             end: 2669,
    //             type: 'gene',
    //             strand: -1
    //         });
    //         done();
    //     });
    // });
    // it('handles parsing of a multi-seq genbank correctly', function(done) {
    //     var string = fs.readFileSync(path.join(__dirname, './testData/multi-seq-genbank.gb'), "utf8");
    //     parseGenbank(string, function(result) {
    //         result.should.be.an('array');
    //         result.should.be.length(4);
    //         result[0].parsedSequence.features.should.be.length(0);
    //         // console.log('result: ' + JSON.stringify(result,null,4));
    //         result[0].parsedSequence.size.should.equal(109);

    //         result.forEach(function(innerResult) {
    //             innerResult.success.should.be.true;
    //         });
    //         done();
    //     });
    // });

});
<commit_msg>fixing name<commit_after>var parseGenbank = require('../parsers/genbankToJson');
var jsonToGenbank = require('../parsers/jsonToGenbank');
var path = require("path");
var fs = require('fs');
var chai = require('chai');
var chaiSubset = require('chai-subset');
chai.use(chaiSubset);
chai.use(require('chai-things'));
chai.should();
describe('genbank exporter/parser conversion', function() {
    it('can interconvert between our parser and our exporter with a malformed genbank', function(done) {
        var string = fs.readFileSync(path.join(__dirname, './testData/breakingGenbank.gb'), "utf8");
        parseGenbank(string, function(result) {
            var feat1 = {
                notes: {},
                name: 'araC',
                start: 6,
                end: 882,
                type: 'CDS',
                strand: -1
            }
            var feat2 = {
                notes: {},
                name: 'T0',
                start: 4300,
                end: 4403,
                type: 'terminator',
                strand: 1
            }
            result.should.be.an('array');
            result[0].success.should.be.true;
            result[0].parsedSequence.features.should.be.length(13);
            result[0].parsedSequence.features.should.include.something.that.deep.equals(feat1);
            result[0].parsedSequence.features.should.include.something.that.deep.equals(feat2);
            var exportedGenbankString = jsonToGenbank(result[0].parsedSequence);
            parseGenbank(exportedGenbankString, function(result) {
                result.should.be.an('array');
                result[0].success.should.be.true;
                result[0].parsedSequence.features.should.be.length(13);

                result[0].parsedSequence.features.should.include.something.that.deep.equals(feat1);
                result[0].parsedSequence.features.should.include.something.that.deep.equals(feat2);
                done();
            });
        });
    });

    it('parses and converts pj5_00001 (aka testGenbankFile.gb) correctly', function(done) {
        var string = fs.readFileSync(path.join(__dirname, './testData/genbank/testGenbankFile.gb'), "utf8");
        parseGenbank(string, function(result) {
            result[0].parsedSequence.name.should.equal('pj5_00001');
            result[0].parsedSequence.circular.should.equal(true);
            result[0].parsedSequence.extraLines.length.should.equal(3);
            result[0].parsedSequence.features.length.should.equal(21);
            result[0].parsedSequence.features.should.include.something.that.deep.equals({
                notes: {
                    pragma: ['Teselagen_Part'],
                    preferred3PrimeOverhangs: [''],
                    preferred5PrimeOverhangs: ['']
                },
                name: 'pS8c-gfpuv_sig_pep_vector_backbone',
                start: 1238,
                end: 1234,
                type: 'misc_feature',
                strand: 1
            });
            result[0].parsedSequence.sequence.length.should.equal(5299);
            var exportedGenbankString = jsonToGenbank(result[0].parsedSequence);
            console.log('exportedGenbankString: ' + exportedGenbankString);
            parseGenbank(exportedGenbankString, function(result) {
                result[0].parsedSequence.name.should.equal('pj5_00001');
                result[0].parsedSequence.circular.should.equal(true);
                result[0].parsedSequence.extraLines.length.should.equal(3);
                result[0].parsedSequence.features.length.should.equal(21);
                result[0].parsedSequence.features.should.include.something.that.deep.equals({
                    notes: {
                        pragma: ['Teselagen_Part'],
                        preferred3PrimeOverhangs: [''],
                        preferred5PrimeOverhangs: ['']
                    },
                    name: 'pS8c-gfpuv_sig_pep_vector_backbone',
                    start: 1238,
                    end: 1234,
                    type: 'misc_feature',
                    strand: 1
                });
                result[0].parsedSequence.sequence.length.should.equal(5299);
                done();
            });
        });
    });

    it('parses and converts a genbank with just feature start locations correctly', function(done) {
        var string = fs.readFileSync(path.join(__dirname, './testData/rhaBp-Pfu-pUN_alt.gb'), "utf8");
        parseGenbank(string, function(result) {
            result.should.be.an('array');
            result[0].success.should.be.true;
            result[0].parsedSequence.features.should.containSubset([{
                name: 'mutation',
                start: 264,
                end: 264,
            },{
                name: 'TSS',
                start: 291,
                end: 291,
            }]);
            var exportedGenbankString = jsonToGenbank(result[0].parsedSequence);
            parseGenbank(exportedGenbankString, function(result) {
                result.should.be.an('array');
                result[0].success.should.be.true;
                result[0].parsedSequence.features.should.containSubset([{
                    name: 'mutation',
                    start: 264,
                    end: 264,
                },{
                    name: 'TSS',
                    start: 291,
                    end: 291,
                }]);
                done();
            });
        });
    });

    // it('parses a genbank that is implicitly non-circular as circular because it contains circular features', function(done) {
    //     var string = fs.readFileSync(path.join(__dirname, './testData/Ecoli_DERA_Implicitly_Circular.gb'), "utf8");
    //     parseGenbank(string, function(result) {
    //         result.should.be.an('array');
    //         result[0].success.should.be.true;
    //         result[0].parsedSequence.circular.should.equal(true);
    //         result[0].parsedSequence.features.should.containSubset([{
    //             name: 'rhaBADp',
    //             start: 410,
    //             end: 182,
    //         }]);
    //         done();
    //     });
    // });

    // it('parses a genbank that is implicitly linear and has no circular featuers as linear', function(done) {
    //     var string = fs.readFileSync(path.join(__dirname, './testData/Ecoli_DERA_Implicitly_Linear.gb'), "utf8");
    //     parseGenbank(string, function(result) {
    //         result.should.be.an('array');
    //         result[0].success.should.be.true;
    //         result[0].parsedSequence.circular.should.equal(false);
    //         done();
    //     });
    // });

    // it('parses plasmid with run-on feature note (pBbS0c-RFP.gb) correctly', function(done) {
    //     var string = fs.readFileSync(path.join(__dirname, './testData/pBbS0c-RFP.gb'), "utf8");
    //     parseGenbank(string, function(result) {
    //         // console.log('JSON.stringify(result,null,4): ' + JSON.stringify(result,null,4));
    //         result[0].parsedSequence.features.should.include.something.that.deep.equals({
    //             notes: {
    //                 note: [
    //                     "REP_ORIGIN REP_ORIGIN pSC101* aka pMPP6, gives plasmid number 3 -4 copies per cell, BglII site in pSC101* ori has been dele ted by quick change agatcT changed to agatcA giving pSC101* * pSC101* aka pMPP6, gives plasmid number 3-4copies p er cell, BglII site in pSC101* ori has been deleted by quic k change agatcT changed to agatcA giving pSC101** [pBbS0a-RFP]",
    //                     "pSC101* aka pMPP6, gives plasmid number 3-4 copies per cell, BglII site in pSC101* ori has been deleted by quic k change agatcT changed to agatcA giving pSC101**"
    //                 ],
    //                 gene: ["SC101** Ori"],
    //                 vntifkey: ["33"]
    //             },
    //             name: 'pSC101**',
    //             start: 1073,
    //             end: 3301,
    //             type: 'rep_origin',
    //             strand: -1
    //         });
    //         result.should.be.an('array');
    //         result.should.be.length(1);
    //         result[0].parsedSequence.features.should.be.length(5);
    //         result[0].parsedSequence.circular.should.equal(true);
    //         // console.log('result: ' + JSON.stringify(result,null,4));
    //         result[0].parsedSequence.size.should.equal(4224);
    //         done();
    //     });
    // });
    // it('parses pBbE0c-RFP.gb correctly', function(done) {
    //     var string = fs.readFileSync(path.join(__dirname, './testData/pBbE0c-RFP.gb'), "utf8");
    //     parseGenbank(string, function(result) {
    //         result.should.be.an('array');
    //         result.should.be.length(1);
    //         result[0].parsedSequence.features.should.be.length(4);
    //         result[0].parsedSequence.circular.should.equal(true);
    //         // console.log('result: ' + JSON.stringify(result,null,4));
    //         result[0].parsedSequence.size.should.equal(2815);
    //         result[0].parsedSequence.features.should.include.something.that.deep.equals({
    //             notes: {
    //                 note: ["GENE [ZFP-GG destination LacUV5 p15A CmR]", "[ZFP-GG destination LacUV5 p15A CmR]"],
    //                 vntifkey: ["22"],
    //                 gene: ["CmR"]
    //             },
    //             name: 'CmR',
    //             start: 2010,
    //             end: 2669,
    //             type: 'gene',
    //             strand: -1
    //         });
    //         done();
    //     });
    // });
    // it('handles parsing of a multi-seq genbank correctly', function(done) {
    //     var string = fs.readFileSync(path.join(__dirname, './testData/multi-seq-genbank.gb'), "utf8");
    //     parseGenbank(string, function(result) {
    //         result.should.be.an('array');
    //         result.should.be.length(4);
    //         result[0].parsedSequence.features.should.be.length(0);
    //         // console.log('result: ' + JSON.stringify(result,null,4));
    //         result[0].parsedSequence.size.should.equal(109);

    //         result.forEach(function(innerResult) {
    //             innerResult.success.should.be.true;
    //         });
    //         done();
    //     });
    // });

});
<|endoftext|>


<commit_before>/**
 * Created by tom on 23/10/15.
 */

import System                   from 'systemjs';
import sinon                    from 'sinon';
import '../../config.js';

export function mockDependency(dependency, replacement){
    System.delete(System.normalizeSync(dependency));
    if(!replacement){
        replacement = sinon.stub;
    }
    if(typeof replacement === 'function'){
        let originalReplacement = replacement;
        replacement = {default: replacement};
    }
    System.set(System.normalizeSync(dependency), System.newModule(replacement));
}

export function loadDependencies(dependencies) {
    let imports = {};
    let promises = [];

    for (let key in dependencies) {
        let dependencyLocation = dependencies[key];
        promises.push(System.import(dependencyLocation).then((importedObject) => {
            imports[key] = importedObject[key] || importedObject.default || importedObject;
            global[key] = imports[key];
        }));
    }

    return Promise.all(promises).then(() => { return Promise.resolve(imports); });
}<commit_msg>Fix behavior of TestBootStrap<commit_after>/**
 * Created by tom on 23/10/15.
 */

import System                   from 'systemjs';
import sinon                    from 'sinon';
import '../../config.js';

export function mockDependency(dependency, replacement){
    System.delete(System.normalizeSync(dependency));
    if(!replacement){
        replacement = sinon.stub();
    }
    if(typeof replacement === 'function'){
        let originalReplacement = replacement;
        replacement = {default: replacement};
    }
    System.set(System.normalizeSync(dependency), System.newModule(replacement));
}

export function loadDependencies(dependencies) {
    let imports = {};
    let promises = [];

    for (let key in dependencies) {
        let dependencyLocation = dependencies[key];
        promises.push(System.import(dependencyLocation).then((importedObject) => {
            imports[key] = importedObject[key] || importedObject.default || importedObject;
        }));
    }

    return Promise.all(promises).then(() => { return Promise.resolve(imports); });
}<|endoftext|>


<commit_before>// Copyright © 2013 Joshua Downer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the “Software”), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

var Renderer = function(canvas) {
  this.renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.RAPHAEL)
  this.ctx = this.renderer.getContext()
}

Renderer.prototype.clear = function() {
  this.ctx.clear()
}

Renderer.prototype.draw_stave = function(x, y, width, in_stave, options) {
  // Create new vexflow stave object
  var stave = new Vex.Flow.Stave(x, y, width);

  var options = options || {}
  var clef = options.clef || null
  var signature = options.signature || null
  var end_bar = options.end_bar || null

  // Add a clef if this stave has one
  if(clef) {
    stave.addClef(clef)
  }

  // Add a time signature if there is one
  if(signature) {
    stave.addTimeSignature(signature)
  }

  // A an end bar if there is one
  if(end_bar) {
    stave.setEndBarType(end_bar)
  }

  stave.setContext(this.ctx)
  stave.draw()

  // Create a voice
  var voice = new Vex.Flow.Voice({
    num_beats: 4,
      beat_value: 4,
      resolution: Vex.Flow.RESOLUTION
  });

  // Add notes to the voice
  voice.addTickables(in_stave.notes);

  // Format and justify the notes
  var formatter = new Vex.Flow.Formatter()
  formatter.joinVoices([voice])
  formatter.format([voice], width)
  formatter.formatToStave([voice], stave)

  // Draw the voice using the stave
  voice.draw(this.ctx, stave);

  // Draw any beams
  for(var i = 0; i < in_stave.beams.length; i++) {
    in_stave.beams[i].setContext(this.ctx).draw()
  }
}

Renderer.prototype.draw_score = function(score) {
  var measures_per_line = Math.floor(this.ctx.paper.width / score.measure_width)
  for(var k = 0; k < score.staves.length; k++) {
    var i = k % measures_per_line
    var j = Math.floor(k / measures_per_line)
    var x = score.measure_width * i
    var y = score.measure_height * j

    var config = {}

    // The first measure of each line should have the clef
    if(i == 0) {
      config.clef = score.clef
    }

    // The first measure of the score should have the time signature
    if(k == 0) {
      config.signature = score.signature
    }

    // the last measure should have an appropriate barline
    if(k == score.staves.length - 1) {
      config.end_bar = Vex.Flow.Barline.type.END
    }

    this.draw_stave(x, y, score.measure_width, score.staves[k], config)
  }
}

var Stave = function(notes) {
  this.notes = new Array()
  this.beams = new Array()

  // The beam stack is used to keep track of the notes that are a part of
  // each beam as we iterate through the tokens
  var beam_stack = new Array()

  // Create an alias for this object so that it can be referenced in the
  // following private functions.
  var stave = this

  // Poor-man's tokenizer
  var tokenize = function(str) {
    str = str.trim()
    str = str.replace(/8r/g, 'x')
    str = str.replace(/4r/g, 'X')
    str = str.replace(/\(/g, '( ')
    str = str.replace(/\)/g, ' )')
    str = str.replace(/  /g, ' ')
    str = str.replace(/x/g, '8r')
    str = str.replace(/X/g, '4r')
    return str.split(' ')
  }

  // Starts a new beam array and pushed it onto the stack
  var start_beam = function() {
    beam_stack.push(new Array())
  }

  // Pops the last beam off the stack and pushes the notes in the bream to the
  // stave.
  var end_beam = function() {
    var beam = beam_stack.pop()
    var notes = new Array()
    for(var j = 0; j < beam.length; j++) {
      notes.push(stave.notes[beam[j]])
    }
    stave.beams.push(new Vex.Flow.Beam(notes))
  }

  // Adds a new note to the current beam on the beam stack.
  var add_note = function(token) {
    var note = new Vex.Flow.StaveNote({ keys: ["c/5"], duration: token})
    stave.notes.push(note)
    for(var j = 0; j < beam_stack.length; j++) {
      beam_stack[j].push(stave.notes.length - 1)
    }
  }

  // Iterate through the tokens and construct the notes and beams
  var token = null
  var tokens = tokenize(notes)
  for(var i = 0; i < tokens.length; i++) {
    token = tokens[i]
    switch (token)
    {
      case '(':
        start_beam()
        break
      case ')':
        end_beam()
        break
      default:
        add_note(token)
    }
  }
}

Stave.prototype.notes = function() {
  return this.notes
}

var Score = function(canvas, notes) {
  this.clef = "percussion"
  this.signature = "4/4"
  this.measure_height = 100
  this.measure_width = 300
  this.renderer = new Renderer(canvas)

  this.staves = new Array()
  var measures = notes.split("|")
  for(var i = 0; i < measures.length; i++) {
    this.staves.push(new Stave(measures[i].trim()))
  }
}

Score.prototype.clef = function() {
  return this.clef
}

Score.prototype.signature = function() {
  return this.signature
}

Score.prototype.draw = function() {
  this.renderer.clear()
  this.renderer.draw_score(this)

  // The following code determines the bounding box around all of the rects and
  // paths in the SVG element created by Raphael and ensures that the size of
  // the SVG element is sufficient to render the entire score.
  var canvas = $(this.renderer.ctx.paper.canvas)
  var bbox = {'x':0, 'y':0, 'u':0, 'v':0}
  $.each(canvas.find('rect, path'), function(index, element){
    var child = $(element)
    var x = parseFloat(child.attr('x'))
    var y = parseFloat(child.attr('y'))
    var w = parseFloat(child.attr('width'))
    var h = parseFloat(child.attr('height'))

    bbox.x = Math.min(bbox.x, x) || bbox.x
    bbox.y = Math.min(bbox.y, y) || bbox.y
    bbox.u = Math.max(bbox.u, x + w) || bbox.u
    bbox.v = Math.max(bbox.v, y + h) || bbox.v
  })

  canvas.attr('x', bbox.x)
  canvas.attr('y', bbox.y)
  canvas.attr('width', bbox.u - bbox.x)
  canvas.attr('height', bbox.v - bbox.y)
}
<commit_msg>score: safe use of jQuery<commit_after>// Copyright © 2013 Joshua Downer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the “Software”), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

var Renderer = function(canvas) {
  this.renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.RAPHAEL)
  this.ctx = this.renderer.getContext()
}

Renderer.prototype.clear = function() {
  this.ctx.clear()
}

Renderer.prototype.draw_stave = function(x, y, width, in_stave, options) {
  // Create new vexflow stave object
  var stave = new Vex.Flow.Stave(x, y, width);

  var options = options || {}
  var clef = options.clef || null
  var signature = options.signature || null
  var end_bar = options.end_bar || null

  // Add a clef if this stave has one
  if(clef) {
    stave.addClef(clef)
  }

  // Add a time signature if there is one
  if(signature) {
    stave.addTimeSignature(signature)
  }

  // A an end bar if there is one
  if(end_bar) {
    stave.setEndBarType(end_bar)
  }

  stave.setContext(this.ctx)
  stave.draw()

  // Create a voice
  var voice = new Vex.Flow.Voice({
    num_beats: 4,
      beat_value: 4,
      resolution: Vex.Flow.RESOLUTION
  });

  // Add notes to the voice
  voice.addTickables(in_stave.notes);

  // Format and justify the notes
  var formatter = new Vex.Flow.Formatter()
  formatter.joinVoices([voice])
  formatter.format([voice], width)
  formatter.formatToStave([voice], stave)

  // Draw the voice using the stave
  voice.draw(this.ctx, stave);

  // Draw any beams
  for(var i = 0; i < in_stave.beams.length; i++) {
    in_stave.beams[i].setContext(this.ctx).draw()
  }
}

Renderer.prototype.draw_score = function(score) {
  var measures_per_line = Math.floor(this.ctx.paper.width / score.measure_width)
  for(var k = 0; k < score.staves.length; k++) {
    var i = k % measures_per_line
    var j = Math.floor(k / measures_per_line)
    var x = score.measure_width * i
    var y = score.measure_height * j

    var config = {}

    // The first measure of each line should have the clef
    if(i == 0) {
      config.clef = score.clef
    }

    // The first measure of the score should have the time signature
    if(k == 0) {
      config.signature = score.signature
    }

    // the last measure should have an appropriate barline
    if(k == score.staves.length - 1) {
      config.end_bar = Vex.Flow.Barline.type.END
    }

    this.draw_stave(x, y, score.measure_width, score.staves[k], config)
  }
}

var Stave = function(notes) {
  this.notes = new Array()
  this.beams = new Array()

  // The beam stack is used to keep track of the notes that are a part of
  // each beam as we iterate through the tokens
  var beam_stack = new Array()

  // Create an alias for this object so that it can be referenced in the
  // following private functions.
  var stave = this

  // Poor-man's tokenizer
  var tokenize = function(str) {
    str = str.trim()
    str = str.replace(/8r/g, 'x')
    str = str.replace(/4r/g, 'X')
    str = str.replace(/\(/g, '( ')
    str = str.replace(/\)/g, ' )')
    str = str.replace(/  /g, ' ')
    str = str.replace(/x/g, '8r')
    str = str.replace(/X/g, '4r')
    return str.split(' ')
  }

  // Starts a new beam array and pushed it onto the stack
  var start_beam = function() {
    beam_stack.push(new Array())
  }

  // Pops the last beam off the stack and pushes the notes in the bream to the
  // stave.
  var end_beam = function() {
    var beam = beam_stack.pop()
    var notes = new Array()
    for(var j = 0; j < beam.length; j++) {
      notes.push(stave.notes[beam[j]])
    }
    stave.beams.push(new Vex.Flow.Beam(notes))
  }

  // Adds a new note to the current beam on the beam stack.
  var add_note = function(token) {
    var note = new Vex.Flow.StaveNote({ keys: ["c/5"], duration: token})
    stave.notes.push(note)
    for(var j = 0; j < beam_stack.length; j++) {
      beam_stack[j].push(stave.notes.length - 1)
    }
  }

  // Iterate through the tokens and construct the notes and beams
  var token = null
  var tokens = tokenize(notes)
  for(var i = 0; i < tokens.length; i++) {
    token = tokens[i]
    switch (token)
    {
      case '(':
        start_beam()
        break
      case ')':
        end_beam()
        break
      default:
        add_note(token)
    }
  }
}

Stave.prototype.notes = function() {
  return this.notes
}

var Score = function(canvas, notes) {
  this.clef = "percussion"
  this.signature = "4/4"
  this.measure_height = 100
  this.measure_width = 300
  this.renderer = new Renderer(canvas)

  this.staves = new Array()
  var measures = notes.split("|")
  for(var i = 0; i < measures.length; i++) {
    this.staves.push(new Stave(measures[i].trim()))
  }
}

Score.prototype.clef = function() {
  return this.clef
}

Score.prototype.signature = function() {
  return this.signature
}

Score.prototype.draw = function() {
  this.renderer.clear()
  this.renderer.draw_score(this)

  // The following code determines the bounding box around all of the rects and
  // paths in the SVG element created by Raphael and ensures that the size of
  // the SVG element is sufficient to render the entire score.
  var canvas = jQuery(this.renderer.ctx.paper.canvas)
  var bbox = {'x':0, 'y':0, 'u':0, 'v':0}
  jQuery.each(canvas.find('rect, path'), function(index, element){
    var child = jQuery(element)
    var x = parseFloat(child.attr('x'))
    var y = parseFloat(child.attr('y'))
    var w = parseFloat(child.attr('width'))
    var h = parseFloat(child.attr('height'))

    bbox.x = Math.min(bbox.x, x) || bbox.x
    bbox.y = Math.min(bbox.y, y) || bbox.y
    bbox.u = Math.max(bbox.u, x + w) || bbox.u
    bbox.v = Math.max(bbox.v, y + h) || bbox.v
  })

  canvas.attr('x', bbox.x)
  canvas.attr('y', bbox.y)
  canvas.attr('width', bbox.u - bbox.x)
  canvas.attr('height', bbox.v - bbox.y)
}
<|endoftext|>


<commit_before>$(document).ready(function () {
   $('#chose-level').addClass('animated fadeInDown');
});

var btn = document.getElementById('btn');
$('#btn').addClass('animated pulse');
$('#team-logo').addClass('animated flash');

var levels = document.getElementById('level-menu');

var rows, cols;
var someSocket = io();

$('.level').on('click', function(){

    $('.level').removeClass('level-chosen');
    $(this).addClass('level-chosen');
    var difficult = $(this).data('level');
    someSocket.emit('difficulty', difficult);
});

someSocket.on('difficulty', function (diff) {
    switch (diff) {
        case 'e':
            rows = 8;
            cols = 8;
            break;
        case 'm':
            rows = 11;
            cols = 11;
            break;
        case 's':
            rows = 15;
            cols = 15;
            break;
    }
});

btn.addEventListener('click', function () {
    someSocket.emit('set up game', null);
});

someSocket.on('set up game', function () {
    $('#container').removeClass('hidden');
    $('#svg-container').removeClass('hidden');
    $('#chose-level').addClass('hidden');

    var paper = Raphael('svg-container', 600, 600);

    var players = [{
        color: 'red',
        points: 0
    }, {
        color: 'blue',
        points: 0
    }];

    var playersCount = players.length;
    var currentPlayerTurn = 0;
    var isPlayerAgain = false;

    var pointsContainer = document.getElementById('points-container');
    var firstPlayerContainer = document.createElement('div');
    var secondPlayerContainer = document.createElement('div');
    pointsContainer.appendChild(firstPlayerContainer);
    pointsContainer.appendChild(secondPlayerContainer);

    var showPoints = (function showPoints() {
        firstPlayerContainer.innerHTML = players[0].color + ': ' + players[0].points;
        secondPlayerContainer.innerHTML = players[1].color + ': ' + players[1].points;
        console.log(players[0].color, players[0].points);
        console.log(players[1].color, players[1].points);
    });
    showPoints();

    var squares = [];

    var socket = io();
    var currentLineId = -1;

    //emitting chat's messages
    $('form').submit(function () {
        socket.emit('chat message', $('#m').val());
        $('#m').val('');
        return false;
    });
    socket.on('chat message', function (msg) {
        $('#messages').append($('<li>').text(msg));
    });
    //--- end of emitting chat's messages

    var generateGrid = (function grid(rows, cols) {
        var pathsIDs = 0;

        for (var i = 1; i <= rows; i++) {
            for (var j = 1; j <= cols; j++) {
                var y = i * 40;
                var x = j * 40;

                if (j !== cols) {
                    createLine(x, y, 40, 'h');
                }
            }
        }

        for (var i = 1; i <= rows; i++) {
            for (var j = 1; j <= cols; j++) {
                var y = i * 40;
                var x = j * 40;

                // without last line ( they get out of the grid)
                if (i !== rows) {
                    createLine(x, y, 40, 'v');
                }

                createDot(x, y, 2);
            }
        }

        function createLine(x, y, len, type) {
            var path = 'M' + x + ' ' + y + ' ' + type + len;
            var line = paper.path(path)
            line.attr({ stroke: 'lightgray' });
            line.attr({ 'stroke-width': '4' });
            line.node.id = ++pathsIDs;
        }

        function createDot(x, y, r) {
            var dot = paper.circle();
            dot.attr({
                cx: x,
                cy: y,
                r: r
            });
        }
    });
    generateGrid(rows, cols);

    var generateIds = (function generateIds(rows, cols) {
        var lineOneStart = 1;
        var lineTwoStart = rows;
        var lineThreeStart = (rows * cols) - (cols - 1);
        var lineFourStart = lineThreeStart + 1;

        for (var i = 1; i <= (rows - 1) * (cols - 1) ; i++) {

            var squaresLines = [lineOneStart, lineTwoStart, lineThreeStart, lineFourStart];
            var square = {
                lines: squaresLines,
                topLineId: lineOneStart
            };

            lineOneStart++;
            lineTwoStart++;
            lineThreeStart++;
            lineFourStart++;

            if (i % (rows - 1) == 0) {
                lineThreeStart++;
                lineFourStart++;
            }

            squares.push(square);
        }
    });

    generateIds(rows, cols);

    (function socket(socket, currentLineID) {

        function mouseOver() {
            $(this).attr({ stroke: '#53533F' });
            $(this).attr({ 'stroke-width': '5' });
            //console.log($(this).attr('id'));
        }

        function mouseOut() {
            $(this).attr({ stroke: 'lightgray' });
            $(this).attr({ 'stroke-width': '4' });
        }

        function clicked() {

            $(this).attr({ stroke: 'black' });
            $(this).attr({ 'stroke-width': '5' });
            $(this).unbind("mouseover", mouseOver);
            $(this).unbind("mouseout", mouseOut);

            currentLineID = +($(this).attr('id'));
            //console.log(currentLineID);

            socket.emit('id', currentLineID);

            socket.on('id', function (id) {
                addLineToSquare(id);
            });

            if (!isPlayerAgain) {
                currentPlayerTurn++;
            }
            else {
                isPlayerAgain = false;
            }

            if (currentPlayerTurn === playersCount) {
                currentPlayerTurn = 0;
            }
        }

        socket.emit('id', currentLineID);

        socket.on('id', function (id) {
            addLineToSquare(id);
        });

        function addLineToSquare(id) {
            squares.forEach(function (currentSquare) {

                if (!currentSquare.lines.length) {
                    return;
                }

                var indexOfId = currentSquare.lines.indexOf(id);

                if (indexOfId >= 0) {
                    //console.log(currentSquare);
                    currentSquare.lines.splice(indexOfId, 1);
                    //console.log(currentSquare);

                    $('#' + id).unbind("mouseover", mouseOver);
                    $('#' + id).unbind("mouseout", mouseOut);
                    $('#' + id).attr({ stroke: 'black' });
                    $('#' + id).attr({ 'stroke-width': '5' });
                }

                if (!currentSquare.lines.length) {
                    // THE SQUARE HAS ALL SIDES FILLED, NEED TO CONTINUE THE LOGIC
                    var currentTopLineId = currentSquare.topLineId;

                    var $currentLine = $('#' + currentTopLineId);
                    var $position = $currentLine.position();

                    var x = $position.left;
                    var y = $position.top;

                    //alert('x: ' + x + ' y: ' + y);
                    var rectToFill = paper.rect(x, y, 40, 40);

                    var colorToUse = players[currentPlayerTurn].color;

                    socket.emit('rect color', colorToUse);
                    console.log();

                    socket.on('rect color', function (color) {
                        if (rectToFill.attr('fill') == 'none') {
                            rectToFill.attr({
                                fill: color
                            });
                        }
                    });

                    players[currentPlayerTurn].points++;

                    showPoints();

                    isPlayerAgain = true;

                    //console.log(currentSquare);
                    //console.log(id);
                }
            });
        }

        $('div svg path')
            .mouseover(mouseOver)
            .mouseout(mouseOut)
            .click(clicked);

    }(socket, currentLineId));
});
<commit_msg>Fixed visualization of points.<commit_after>$(document).ready(function () {
   $('#chose-level').addClass('animated fadeInDown');
});

var btn = document.getElementById('btn');
$('#btn').addClass('animated pulse');
$('#team-logo').addClass('animated flash');

var levels = document.getElementById('level-menu');

var rows, cols;
var someSocket = io();

$('.level').on('click', function(){

    $('.level').removeClass('level-chosen');
    $(this).addClass('level-chosen');
    var difficult = $(this).data('level');
    someSocket.emit('difficulty', difficult);
});

someSocket.on('difficulty', function (diff) {
    switch (diff) {
        case 'e':
            rows = 8;
            cols = 8;
            break;
        case 'm':
            rows = 11;
            cols = 11;
            break;
        case 's':
            rows = 15;
            cols = 15;
            break;
    }
});

btn.addEventListener('click', function () {
    someSocket.emit('set up game', null);
});

someSocket.on('set up game', function () {
    $('#container').removeClass('hidden');
    $('#svg-container').removeClass('hidden');
    $('#chose-level').addClass('hidden');

    var paper = Raphael('svg-container', 600, 600);

    var players = [{
        color: 'red',
        points: 0
    }, {
        color: 'blue',
        points: 0
    }];

    var playersCount = players.length;
    var currentPlayerTurn = 0;
    var isPlayerAgain = false;

    var pointsContainer = document.getElementById('points-container');
    var firstPlayerPointsSpan = document.createElement('span');
    var secondPlayerPointsSpan = document.createElement('span');
    firstPlayerPointsSpan.style.display = 'block';
    firstPlayerPointsSpan.style.color = 'red';
    secondPlayerPointsSpan.style.display = 'block';
    secondPlayerPointsSpan.style.color = 'blue';

    pointsContainer.appendChild(firstPlayerPointsSpan);
    pointsContainer.appendChild(secondPlayerPointsSpan);

    var showPoints = (function showPoints() {
        firstPlayerPointsSpan.innerText = players[0].color + ': ' + players[0].points;
        secondPlayerPointsSpan.innerText = players[1].color + ': ' + players[1].points;
        console.log(players[0].color, players[0].points);
        console.log(players[1].color, players[1].points);
    });
    showPoints();

    var squares = [];

    var socket = io();
    var currentLineId = -1;

    //emitting chat's messages
    $('form').submit(function () {
        socket.emit('chat message', $('#m').val());
        $('#m').val('');
        return false;
    });
    socket.on('chat message', function (msg) {
        $('#messages').append($('<li>').text(msg));
    });
    //--- end of emitting chat's messages

    var generateGrid = (function grid(rows, cols) {
        var pathsIDs = 0;

        for (var i = 1; i <= rows; i++) {
            for (var j = 1; j <= cols; j++) {
                var y = i * 40;
                var x = j * 40;

                if (j !== cols) {
                    createLine(x, y, 40, 'h');
                }
            }
        }

        for (var i = 1; i <= rows; i++) {
            for (var j = 1; j <= cols; j++) {
                var y = i * 40;
                var x = j * 40;

                // without last line ( they get out of the grid)
                if (i !== rows) {
                    createLine(x, y, 40, 'v');
                }

                createDot(x, y, 2);
            }
        }

        function createLine(x, y, len, type) {
            var path = 'M' + x + ' ' + y + ' ' + type + len;
            var line = paper.path(path)
            line.attr({ stroke: 'lightgray' });
            line.attr({ 'stroke-width': '4' });
            line.node.id = ++pathsIDs;
        }

        function createDot(x, y, r) {
            var dot = paper.circle();
            dot.attr({
                cx: x,
                cy: y,
                r: r
            });
        }
    });
    generateGrid(rows, cols);

    var generateIds = (function generateIds(rows, cols) {
        var lineOneStart = 1;
        var lineTwoStart = rows;
        var lineThreeStart = (rows * cols) - (cols - 1);
        var lineFourStart = lineThreeStart + 1;

        for (var i = 1; i <= (rows - 1) * (cols - 1) ; i++) {

            var squaresLines = [lineOneStart, lineTwoStart, lineThreeStart, lineFourStart];
            var square = {
                lines: squaresLines,
                topLineId: lineOneStart
            };

            lineOneStart++;
            lineTwoStart++;
            lineThreeStart++;
            lineFourStart++;

            if (i % (rows - 1) == 0) {
                lineThreeStart++;
                lineFourStart++;
            }

            squares.push(square);
        }
    });

    generateIds(rows, cols);

    (function socket(socket, currentLineID) {

        function mouseOver() {
            $(this).attr({ stroke: '#53533F' });
            $(this).attr({ 'stroke-width': '5' });
            //console.log($(this).attr('id'));
        }

        function mouseOut() {
            $(this).attr({ stroke: 'lightgray' });
            $(this).attr({ 'stroke-width': '4' });
        }

        function clicked() {

            $(this).attr({ stroke: 'black' });
            $(this).attr({ 'stroke-width': '5' });
            $(this).unbind("mouseover", mouseOver);
            $(this).unbind("mouseout", mouseOut);

            currentLineID = +($(this).attr('id'));
            //console.log(currentLineID);

            socket.emit('id', currentLineID);

            socket.on('id', function (id) {
                addLineToSquare(id);
            });

            if (!isPlayerAgain) {
                currentPlayerTurn++;
            }
            else {
                isPlayerAgain = false;
            }

            if (currentPlayerTurn === playersCount) {
                currentPlayerTurn = 0;
            }
        }

        socket.emit('id', currentLineID);

        socket.on('id', function (id) {
            addLineToSquare(id);
        });

        function addLineToSquare(id) {
            squares.forEach(function (currentSquare) {

                if (!currentSquare.lines.length) {
                    return;
                }

                var indexOfId = currentSquare.lines.indexOf(id);

                if (indexOfId >= 0) {
                    //console.log(currentSquare);
                    currentSquare.lines.splice(indexOfId, 1);
                    //console.log(currentSquare);

                    $('#' + id).unbind("mouseover", mouseOver);
                    $('#' + id).unbind("mouseout", mouseOut);
                    $('#' + id).attr({ stroke: 'black' });
                    $('#' + id).attr({ 'stroke-width': '5' });
                }

                if (!currentSquare.lines.length) {
                    // THE SQUARE HAS ALL SIDES FILLED, NEED TO CONTINUE THE LOGIC
                    var currentTopLineId = currentSquare.topLineId;

                    var $currentLine = $('#' + currentTopLineId);
                    var $position = $currentLine.position();

                    var x = $position.left;
                    var y = $position.top;

                    //alert('x: ' + x + ' y: ' + y);
                    var rectToFill = paper.rect(x, y, 40, 40);

                    var colorToUse = players[currentPlayerTurn].color;

                    socket.emit('rect color', colorToUse);
                    console.log();

                    socket.on('rect color', function (color) {
                        if (rectToFill.attr('fill') == 'none') {
                            rectToFill.attr({
                                fill: color
                            });
                        }
                    });

                    players[currentPlayerTurn].points++;

                    showPoints();

                    isPlayerAgain = true;

                    //console.log(currentSquare);
                    //console.log(id);
                }
            });
        }

        $('div svg path')
            .mouseover(mouseOver)
            .mouseout(mouseOut)
            .click(clicked);

    }(socket, currentLineId));
});
<|endoftext|>