/* global describe:false, it:false, beforeEach:false, expect:false, elementResizeDetectorMaker:false, _:false, $:false, jasmine:false */ "use strict"; function ensureMapEqual(before, after, ignore) { var beforeKeys = _.keys(before); var afterKeys = _.keys(after); var unionKeys = _.union(beforeKeys, afterKeys); var diffValueKeys = _.filter(unionKeys, function (key) { var beforeValue = before[key]; var afterValue = after[key]; return !ignore(key, beforeValue, afterValue) && beforeValue !== afterValue; }); if (diffValueKeys.length) { var beforeDiffObject = {}; var afterDiffObject = {}; _.forEach(diffValueKeys, function (key) { beforeDiffObject[key] = before[key]; afterDiffObject[key] = after[key]; }); expect(afterDiffObject).toEqual(beforeDiffObject); } } function getStyle(element) { function clone(styleObject) { var clonedTarget = {}; _.forEach(styleObject.cssText.split(";").slice(0, -1), function (declaration) { var colonPos = declaration.indexOf(":"); var attr = declaration.slice(0, colonPos).trim(); if (attr.indexOf("-") === -1) { // Remove attributes like "background-image", leaving "backgroundImage" clonedTarget[attr] = declaration.slice(colonPos + 2); } }); return clonedTarget; } var style = getComputedStyle(element); return clone(style); } function getAttributes(element) { var attrs = {}; _.forEach(element.attributes, function (attr) { attrs[attr.nodeName] = attr.value; }); return attrs; } var ensureAttributes = ensureMapEqual; var reporter = { log: function () { throw new Error("Reporter.log should not be called"); }, warn: function () { throw new Error("Reporter.warn should not be called"); }, error: function () { throw new Error("Reporter.error should not be called"); } }; $("body").prepend("<div id=fixtures></div>"); function listenToTest(strategy) { describe("[" + strategy + "] listenTo", function () { it("should be able to attach a listener to an element", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener = jasmine.createSpy("listener"); erd.listenTo($("#test")[0], listener); setTimeout(function () { $("#test").width(300); }, 200); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); done(); }, 400); }); it("should throw on invalid parameters", function () { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); expect(erd.listenTo).toThrow(); expect(_.partial(erd.listenTo, $("#test")[0])).toThrow(); }); describe("option.onReady", function () { it("should be called when installing a listener to an element", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener = jasmine.createSpy("listener"); erd.listenTo({ onReady: function () { $("#test").width(200); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); done(); }, 200); } }, $("#test")[0], listener); }); it("should be called when all elements are ready", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener = jasmine.createSpy("listener"); erd.listenTo({ onReady: function () { $("#test").width(200); $("#test2").width(300); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); expect(listener).toHaveBeenCalledWith($("#test2")[0]); done(); }, 200); } }, $("#test, #test2"), listener); }); it("should be able to handle listeners for the same element but different calls", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var onReady1 = jasmine.createSpy("listener"); var onReady2 = jasmine.createSpy("listener"); erd.listenTo({ onReady: onReady1 }, $("#test"), function noop() { }); erd.listenTo({ onReady: onReady2 }, $("#test"), function noop() { }); setTimeout(function () { expect(onReady1.calls.count()).toBe(1); expect(onReady2.calls.count()).toBe(1); done(); }, 300); }); it("should be able to handle when elements occur multiple times in the same call (and other calls)", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var onReady1 = jasmine.createSpy("listener"); var onReady2 = jasmine.createSpy("listener"); erd.listenTo({ onReady: onReady1 }, [$("#test")[0], $("#test")[0]], function noop() { }); erd.listenTo({ onReady: onReady2 }, $("#test"), function noop() { }); setTimeout(function () { expect(onReady1.calls.count()).toBe(1); expect(onReady2.calls.count()).toBe(1); done(); }, 300); }); }); it("should be able to attach multiple listeners to an element", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener1 = jasmine.createSpy("listener1"); var listener2 = jasmine.createSpy("listener2"); erd.listenTo($("#test")[0], listener1); erd.listenTo($("#test")[0], listener2); setTimeout(function () { $("#test").width(300); }, 200); setTimeout(function () { expect(listener1).toHaveBeenCalledWith($("#test")[0]); expect(listener2).toHaveBeenCalledWith($("#test")[0]); done(); }, 400); }); it("should be able to attach a listener to an element multiple times within the same call", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener1 = jasmine.createSpy("listener1"); erd.listenTo([$("#test")[0], $("#test")[0]], listener1); setTimeout(function () { $("#test").width(300); }, 200); setTimeout(function () { expect(listener1).toHaveBeenCalledWith($("#test")[0]); expect(listener1.calls.count()).toBe(2); done(); }, 400); }); it("should be able to attach listeners to multiple elements", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener1 = jasmine.createSpy("listener1"); erd.listenTo($("#test, #test2"), listener1); setTimeout(function () { $("#test").width(200); }, 200); setTimeout(function () { expect(listener1).toHaveBeenCalledWith($("#test")[0]); }, 400); setTimeout(function () { $("#test2").width(500); }, 600); setTimeout(function () { expect(listener1).toHaveBeenCalledWith($("#test2")[0]); done(); }, 800); }); //Only run this test if the browser actually is able to get the computed style of an element. //Only IE8 is lacking the getComputedStyle method. if (window.getComputedStyle) { it("should keep the style of the element intact", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); function ignoreStyleChange(key, before, after) { return (key === "position" && before === "static" && after === "relative") || (/^(top|right|bottom|left)$/.test(key) && before === "auto" && after === "0px"); } var beforeComputedStyle = getStyle($("#test")[0]); erd.listenTo($("#test")[0], _.noop); var afterComputedStyle = getStyle($("#test")[0]); ensureMapEqual(beforeComputedStyle, afterComputedStyle, ignoreStyleChange); //Test styles async since making an element listenable is async. setTimeout(function () { var afterComputedStyleAsync = getStyle($("#test")[0]); ensureMapEqual(beforeComputedStyle, afterComputedStyleAsync, ignoreStyleChange); expect(true).toEqual(true); // Needed so that jasmine does not warn about no expects in the test (the actual expects are in the ensureMapEqual). done(); }, 200); }); } describe("options.callOnAdd", function () { it("should be true default and call all functions when listenTo succeeds", function (done) { var erd = elementResizeDetectorMaker({ reporter: reporter, strategy: strategy }); var listener = jasmine.createSpy("listener"); var listener2 = jasmine.createSpy("listener2"); erd.listenTo($("#test")[0], listener); erd.listenTo($("#test")[0], listener2); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); expect(listener2).toHaveBeenCalledWith($("#test")[0]); listener.calls.reset(); listener2.calls.reset(); $("#test").width(300); }, 200); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); expect(listener2).toHaveBeenCalledWith($("#test")[0]); done(); }, 400); }); it("should call listener multiple times when listening to multiple elements", function (done) { var erd = elementResizeDetectorMaker({ reporter: reporter, strategy: strategy }); var listener1 = jasmine.createSpy("listener1"); erd.listenTo($("#test, #test2"), listener1); setTimeout(function () { expect(listener1).toHaveBeenCalledWith($("#test")[0]); expect(listener1).toHaveBeenCalledWith($("#test2")[0]); done(); }, 200); }); }); it("should call listener if the element is changed synchronously after listenTo", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener1 = jasmine.createSpy("listener1"); erd.listenTo($("#test"), listener1); $("#test").width(200); setTimeout(function () { expect(listener1).toHaveBeenCalledWith($("#test")[0]); done(); }, 200); }); it("should not emit resize when listenTo is called", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener1 = jasmine.createSpy("listener1"); erd.listenTo($("#test"), listener1); setTimeout(function () { expect(listener1).not.toHaveBeenCalledWith($("#test")[0]); done(); }, 200); }); it("should not emit resize event even though the element is back to its start size", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener = jasmine.createSpy("listener1"); $("#test").width(200); erd.listenTo($("#test"), listener); setTimeout(function () { expect(listener).not.toHaveBeenCalledWith($("#test")[0]); listener.calls.reset(); $("#test").width(100); }, 200); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); listener.calls.reset(); $("#test").width(200); }, 400); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); done(); }, 600); }); it("should use the option.idHandler if present", function (done) { var ID_ATTR = "some-fancy-id-attr"; var idHandler = { get: function (element, readonly) { if (element[ID_ATTR] === undefined) { if (readonly) { return null; } this.set(element); } return $(element).attr(ID_ATTR); }, set: function (element) { var id; if ($(element).attr("id") === "test") { id = "test+1"; } else if ($(element).attr("id") === "test2") { id = "test2+2"; } $(element).attr(ID_ATTR, id); return id; } }; var erd = elementResizeDetectorMaker({ idHandler: idHandler, callOnAdd: false, reporter: reporter, strategy: strategy }); var listener1 = jasmine.createSpy("listener1"); var listener2 = jasmine.createSpy("listener1"); var attrsBeforeTest = getAttributes($("#test")[0]); var attrsBeforeTest2 = getAttributes($("#test2")[0]); erd.listenTo($("#test"), listener1); erd.listenTo($("#test, #test2"), listener2); var attrsAfterTest = getAttributes($("#test")[0]); var attrsAfterTest2 = getAttributes($("#test2")[0]); var ignoreValidIdAttrAndStyle = function (key) { return key === ID_ATTR || key === "style"; }; ensureAttributes(attrsBeforeTest, attrsAfterTest, ignoreValidIdAttrAndStyle); ensureAttributes(attrsBeforeTest2, attrsAfterTest2, ignoreValidIdAttrAndStyle); expect($("#test").attr(ID_ATTR)).toEqual("test+1"); expect($("#test2").attr(ID_ATTR)).toEqual("test2+2"); setTimeout(function () { $("#test").width(300); $("#test2").width(500); }, 200); setTimeout(function () { expect(listener1).toHaveBeenCalledWith($("#test")[0]); expect(listener2).toHaveBeenCalledWith($("#test")[0]); expect(listener2).toHaveBeenCalledWith($("#test2")[0]); done(); }, 600); }); it("should be able to install into elements that are detached from the DOM", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener1 = jasmine.createSpy("listener1"); var div = document.createElement("div"); div.style.width = "100%"; div.style.height = "100%"; erd.listenTo(div, listener1); setTimeout(function () { $("#test")[0].appendChild(div); }, 200); setTimeout(function () { $("#test").width(200); }, 400); setTimeout(function () { expect(listener1).toHaveBeenCalledWith(div); done(); }, 600); }); it("should handle iframes, by using initDocument", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, strategy: strategy, reporter: reporter }); var listener1 = jasmine.createSpy("listener1"); var iframe = document.createElement("iframe"); $("#test")[0].appendChild(iframe); erd.initDocument(iframe.contentDocument); var div = iframe.contentDocument.createElement("div"); div.style.width = "100%"; div.style.height = "100%"; div.id = "target"; erd.listenTo(div, listener1); setTimeout(function () { // FireFox triggers the onload state of the iframe and wipes its content. iframe.contentDocument.body.appendChild(div); erd.initDocument(iframe.contentDocument); }, 10); setTimeout(function () { div.style.width = "100px"; }, 200); setTimeout(function () { expect(listener1).toHaveBeenCalledWith(div); done(); }, 400); }); it("should detect resizes caused by padding and font-size changes", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener = jasmine.createSpy("listener"); $("#test").html("test"); $("#test").css("padding", "0px"); $("#test").css("font-size", "16px"); erd.listenTo($("#test"), listener); $("#test").css("padding", "10px"); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); listener.calls.reset(); $("#test").css("font-size", "20px"); }, 200); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); done(); }, 400); }); describe("should handle unrendered elements correctly", function () { it("when installing", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); $("#test").html("<div id=\"inner\"></div>"); $("#test").css("display", "none"); var listener = jasmine.createSpy("listener"); erd.listenTo($("#inner"), listener); setTimeout(function () { expect(listener).not.toHaveBeenCalled(); $("#test").css("display", ""); }, 200); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#inner")[0]); listener.calls.reset(); $("#inner").width("300px"); }, 400); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#inner")[0]); listener.calls.reset(); done(); }, 600); }); it("when element gets unrendered after installation", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); // The div is rendered to begin with. $("#test").html("<div id=\"inner\"></div>"); var listener = jasmine.createSpy("listener"); erd.listenTo($("#inner"), listener); // The it gets unrendered, and it changes width. setTimeout(function () { expect(listener).not.toHaveBeenCalled(); $("#test").css("display", "none"); $("#inner").width("300px"); }, 100); // Render the element again. setTimeout(function () { expect(listener).not.toHaveBeenCalled(); $("#test").css("display", ""); }, 200); // ERD should detect that the element has changed size as soon as it gets rendered again. setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#inner")[0]); done(); }, 300); }); }); describe("inline elements", function () { it("should be listenable", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); $("#test").html("<span id=\"inner\">test</span>"); var listener = jasmine.createSpy("listener"); erd.listenTo($("#inner"), listener); setTimeout(function () { expect(listener).not.toHaveBeenCalled(); $("#inner").append("testing testing"); }, 100); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#inner")[0]); done(); }, 200); }); it("should not get altered dimensions", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); $("#test").html("<span id=\"inner\"></span>"); var widthBefore = $("#inner").width(); var heightBefore = $("#inner").height(); var listener = jasmine.createSpy("listener"); erd.listenTo($("#inner"), listener); setTimeout(function () { expect($("#inner").width()).toEqual(widthBefore); expect($("#inner").height()).toEqual(heightBefore); done(); }, 100); }); }); it("should handle dir=rtl correctly", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, reporter: reporter, strategy: strategy }); var listener = jasmine.createSpy("listener"); $("#test")[0].dir = "rtl"; erd.listenTo($("#test")[0], listener); setTimeout(function () { $("#test").width(300); }, 200); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); done(); }, 400); }); it("should handle fast consecutive resizes", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, strategy: strategy, reporter: reporter }); var listener = jasmine.createSpy("listener"); $("#test").width(100); erd.listenTo($("#test")[0], listener); setTimeout(function () { $("#test").width(300); }, 50); setTimeout(function () { expect(listener.calls.count()).toEqual(1); $("#test").width(500); setTimeout(function () { $("#test").width(300); }, 0); }, 100); // Some browsers skip the 300 -> 500 -> 300 resize, and some actually processes it. // So the resize events may be 1 or 3 at this point. setTimeout(function () { var count = listener.calls.count(); expect(count === 1 || count === 3).toEqual(true); }, 150); setTimeout(function () { var count = listener.calls.count(); expect(count === 1 || count === 3).toEqual(true); $("#test").width(800); }, 200); setTimeout(function () { var count = listener.calls.count(); expect(count === 2 || count === 4).toEqual(true); done(); }, 250); }); }); } function removalTest(strategy) { describe("[" + strategy + "] resizeDetector.removeListener", function () { it("should remove listener from element", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, strategy: strategy }); var $testElem = $("#test"); var listenerCall = jasmine.createSpy("listener"); var listenerNotCall = jasmine.createSpy("listener"); erd.listenTo($testElem[0], listenerCall); erd.listenTo($testElem[0], listenerNotCall); setTimeout(function () { erd.removeListener($testElem[0], listenerNotCall); $testElem.width(300); }, 200); setTimeout(function () { expect(listenerCall).toHaveBeenCalled(); expect(listenerNotCall).not.toHaveBeenCalled(); done(); }, 400); }); }); describe("[" + strategy + "] resizeDetector.removeAllListeners", function () { it("should remove all listeners from element", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, strategy: strategy }); var $testElem = $("#test"); var listener1 = jasmine.createSpy("listener"); var listener2 = jasmine.createSpy("listener"); erd.listenTo($testElem[0], listener1); erd.listenTo($testElem[0], listener2); setTimeout(function () { erd.removeAllListeners($testElem[0]); $testElem.width(300); }, 200); setTimeout(function () { expect(listener1).not.toHaveBeenCalled(); expect(listener2).not.toHaveBeenCalled(); done(); }, 400); }); it("should work for elements that don't have the detector installed", function () { var erd = elementResizeDetectorMaker({ strategy: strategy }); var $testElem = $("#test"); expect(erd.removeAllListeners.bind(erd, $testElem[0])).not.toThrow(); }); }); describe("[scroll] Specific scenarios", function () { it("should be able to call uninstall in the middle of a resize", function (done) { var erd = elementResizeDetectorMaker({ strategy: "scroll" }); var $testElem = $("#test"); var testElem = $testElem[0]; var listener = jasmine.createSpy("listener"); erd.listenTo(testElem, listener); setTimeout(function () { // We want the uninstall to happen exactly when a scroll event occured before the delayed batched is going to be processed. // So we intercept the erd shrink/expand functions in the state so that we may call uninstall after the handling of the event. var uninstalled = false; function wrapOnScrollEvent(oldFn) { return function () { oldFn(); if (!uninstalled) { expect(erd.uninstall.bind(erd, testElem)).not.toThrow(); uninstalled = true; done(); } }; } var state = testElem._erd; state.onExpand = wrapOnScrollEvent(state.onExpand); state.onShrink = wrapOnScrollEvent(state.onShrink); $("#test").width(300); }, 50); }); it("should be able to call uninstall and then install in the middle of a resize (issue #61)", function (done) { var erd = elementResizeDetectorMaker({ strategy: "scroll", reporter: reporter }); var $testElem = $("#test"); var testElem = $testElem[0]; var listener = jasmine.createSpy("listener"); erd.listenTo(testElem, listener); setTimeout(function () { // We want the uninstall to happen exactly when a scroll event occured before the delayed batched is going to be processed. // So we intercept the erd shrink/expand functions in the state so that we may call uninstall after the handling of the event. var uninstalled = false; function wrapOnScrollEvent(oldFn) { return function () { oldFn(); if (!uninstalled) { expect(erd.uninstall.bind(erd, testElem)).not.toThrow(); uninstalled = true; var listener2 = jasmine.createSpy("listener"); expect(erd.listenTo.bind(erd, testElem, listener2)).not.toThrow(); setTimeout(function () { done(); }, 0); } }; } var state = testElem._erd; state.onExpand = wrapOnScrollEvent(state.onExpand); state.onShrink = wrapOnScrollEvent(state.onShrink); $("#test").width(300); }, 50); }); }); describe("[" + strategy + "] resizeDetector.uninstall", function () { it("should completely remove detector from element", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, strategy: strategy }); var $testElem = $("#test"); var listener = jasmine.createSpy("listener"); erd.listenTo($testElem[0], listener); setTimeout(function () { erd.uninstall($testElem[0]); // detector element should be removed expect($testElem[0].childNodes.length).toBe(0); $testElem.width(300); }, 200); setTimeout(function () { expect(listener).not.toHaveBeenCalled(); done(); }, 400); }); it("should completely remove detector from multiple elements", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, strategy: strategy }); var listener = jasmine.createSpy("listener"); erd.listenTo($("#test, #test2"), listener); setTimeout(function () { erd.uninstall($("#test, #test2")); // detector element should be removed expect($("#test")[0].childNodes.length).toBe(0); expect($("#test2")[0].childNodes.length).toBe(0); $("#test, #test2").width(300); }, 200); setTimeout(function () { expect(listener).not.toHaveBeenCalled(); done(); }, 400); }); it("should be able to call uninstall directly after listenTo", function () { var erd = elementResizeDetectorMaker({ strategy: strategy }); var $testElem = $("#test"); var listener = jasmine.createSpy("listener"); erd.listenTo($testElem[0], listener); expect(erd.uninstall.bind(erd, $testElem[0])).not.toThrow(); }); it("should be able to call uninstall directly async after listenTo", function (done) { var erd = elementResizeDetectorMaker({ strategy: strategy }); var $testElem = $("#test"); var listener = jasmine.createSpy("listener"); erd.listenTo($testElem[0], listener); setTimeout(function () { expect(erd.uninstall.bind(erd, $testElem[0])).not.toThrow(); done(); }, 0); }); it("should be able to call uninstall in callOnAdd callback", function (done) { var error = false; // Ugly hack to catch async errors. window.onerror = function () { error = true; }; var erd = elementResizeDetectorMaker({ strategy: strategy, callOnAdd: true }); erd.listenTo($("#test"), function () { expect(erd.uninstall.bind(null, ($("#test")))).not.toThrow(); }); setTimeout(function () { expect(error).toBe(false); done(); window.error = null; }, 50); }); it("should be able to call uninstall in callOnAdd callback with multiple elements", function (done) { var error = false; // Ugly hack to catch async errors. window.onerror = function () { error = true; }; var erd = elementResizeDetectorMaker({ strategy: strategy, callOnAdd: true }); var listener = jasmine.createSpy("listener"); erd.listenTo($("#test, #test2"), function () { expect(erd.uninstall.bind(null, ($("#test, #test2")))).not.toThrow(); listener(); }); setTimeout(function () { expect(listener.calls.count()).toBe(1); expect(error).toBe(false); done(); window.error = null; }, 50); }); it("should be able to call uninstall on non-erd elements", function () { var erd = elementResizeDetectorMaker({ strategy: strategy }); var $testElem = $("#test"); expect(erd.uninstall.bind(erd, $testElem[0])).not.toThrow(); var listener = jasmine.createSpy("listener"); erd.listenTo($testElem[0], listener); expect(erd.uninstall.bind(erd, $testElem[0])).not.toThrow(); expect(erd.uninstall.bind(erd, $testElem[0])).not.toThrow(); }); }); } function importantRuleTest(strategy) { describe("[" + strategy + "] resizeDetector.important", function () { it("should add all rules with important", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: true, strategy: strategy, important: true }); var testElem = $("#test"); var listenerCall = jasmine.createSpy("listener"); erd.listenTo(testElem[0], listenerCall); setTimeout(function () { if (strategy === "scroll") { expect(testElem[0].style.cssText).toMatch(/!important;$/); } testElem.find("*").toArray().forEach(function (element) { var rules = element.style.cssText.split(";").filter(function (rule) { return !!rule; }); rules.forEach(function (rule) { expect(rule).toMatch(/!important$/); }); }); done(); }, 50); }); it("Overrides important CSS", function (done) { var erd = elementResizeDetectorMaker({ callOnAdd: false, strategy: strategy, important: true }); var listener = jasmine.createSpy("listener"); var testElem = $("#test"); var style = document.createElement("style"); style.appendChild(document.createTextNode("#test { position: static !important; }")); document.head.appendChild(style); erd.listenTo(testElem[0], listener); setTimeout(function () { $("#test").width(300); }, 100); setTimeout(function () { expect(listener).toHaveBeenCalledWith($("#test")[0]); done(); }, 200); }); }); } describe("element-resize-detector", function () { beforeEach(function () { //This messed with tests in IE8. //TODO: Investigate why, because it would be nice to have instead of the current solution. //loadFixtures("element-resize-detector_fixture.html"); $("#fixtures").html("<div id=test></div><div id=test2></div>"); }); describe("elementResizeDetectorMaker", function () { it("should be globally defined", function () { expect(elementResizeDetectorMaker).toBeDefined(); }); it("should create an element-resize-detector instance", function () { var erd = elementResizeDetectorMaker(); expect(erd).toBeDefined(); expect(erd.listenTo).toBeDefined(); }); }); // listenToTest("object"); // removalTest("object"); // importantRuleTest("object"); listenToTest("scroll"); removalTest("scroll"); importantRuleTest("scroll"); });