<commit_before>
describe('DOM node disposal', function() {
    beforeEach(jasmine.prepareTestNode);

    it('Should run registered disposal callbacks when a node is cleaned', function () {
        var didRun = false;
        ko.utils.domNodeDisposal.addDisposeCallback(testNode, function() { didRun = true });

        expect(didRun).toEqual(false);
        ko.cleanNode(testNode);
        expect(didRun).toEqual(true);
    });

    it('Should run registered disposal callbacks on descendants when a node is cleaned', function () {
        var didRun = false;
        var childNode = document.createElement("DIV");
        var grandChildNode = document.createElement("DIV");
        testNode.appendChild(childNode);
        childNode.appendChild(grandChildNode);
        ko.utils.domNodeDisposal.addDisposeCallback(grandChildNode, function() { didRun = true });

        expect(didRun).toEqual(false);
        ko.cleanNode(testNode);
        expect(didRun).toEqual(true);
    });

    it('Should run registered disposal callbacks and detach from DOM when a node is removed', function () {
        var didRun = false;
        var childNode = document.createElement("DIV");
        testNode.appendChild(childNode);
        ko.utils.domNodeDisposal.addDisposeCallback(childNode, function() { didRun = true });

        expect(didRun).toEqual(false);
        expect(testNode.childNodes.length).toEqual(1);
        ko.removeNode(childNode);
        expect(didRun).toEqual(true);
        expect(testNode.childNodes.length).toEqual(0);
    });

    it('Should be able to remove previously-registered disposal callbacks', function() {
        var didRun = false;
        var callback = function() { didRun = true };
        ko.utils.domNodeDisposal.addDisposeCallback(testNode, callback);

        expect(didRun).toEqual(false);
        ko.utils.domNodeDisposal.removeDisposeCallback(testNode, callback);
        ko.cleanNode(testNode);
        expect(didRun).toEqual(false); // Didn't run only because we removed it
    });

    it('Should be able to attach disposal callback to a node that has been cloned', function() {
        // This represents bug https://github.com/SteveSanderson/knockout/issues/324
        // IE < 9 copies expando properties when cloning nodes, so if the node already has some DOM data associated with it,
        // the DOM data key will be copied too. This causes a problem for disposal, because if the original node gets disposed,
        // the shared DOM data is disposed, and then it becomes an error to try to set new DOM data on the clone.
        // The solution is to make the DOM-data-setting logic able to recover from the scenario by detecting that the original
        // DOM data is gone, and therefore recreating a new DOM data store for the clone.

        // Create an element with DOM data
        var originalNode = document.createElement("DIV");
        ko.utils.domNodeDisposal.addDisposeCallback(originalNode, function() { });

        // Clone it, then dispose it. Then check it's still safe to associate DOM data with the clone.
        var cloneNode = originalNode.cloneNode(true);
        ko.cleanNode(originalNode);
        ko.utils.domNodeDisposal.addDisposeCallback(cloneNode, function() { });
    });

    it('Should be able to clean any user data by overwriting "cleanExternalData"', function() {
        this.restoreAfter(ko.utils.domNodeDisposal, 'cleanExternalData'); // restore original function when done

        ko.utils.domNodeDisposal.cleanExternalData = function (node) {
            if (node['ko_test'])
                node['ko_test'] = undefined;
        };

        testNode['ko_test'] = "mydata";
        expect(testNode['ko_test']).toEqual("mydata");

        ko.cleanNode(testNode);
        expect(testNode['ko_test']).toBeUndefined();
    });

    if (typeof jQuery !== 'undefined') {
        it('Should clear jQuery data when a node is cleaned', function() {
            var obj = {};
            jQuery.data(testNode, 'ko_test', obj);
            expect(jQuery.data(testNode, 'ko_test')).toBe(obj);

            ko.cleanNode(testNode);
            expect(jQuery.data(testNode, 'ko_test')).toBeUndefined();
        });

        it('Should be able to prevent jQuery data from being cleared by overwriting "cleanExternalData"', function() {
            this.restoreAfter(ko.utils.domNodeDisposal, 'cleanExternalData'); // restore original function when done

            ko.utils.domNodeDisposal.cleanExternalData = function () {};

            var obj = {};
            jQuery.data(testNode, 'ko_test', obj);
            expect(jQuery.data(testNode, 'ko_test')).toBe(obj);

            ko.cleanNode(testNode);
            expect(jQuery.data(testNode, 'ko_test')).toBe(obj);
        });
    }
});<commit_msg>Ensure constant spec count with or without jQuery<commit_after>
describe('DOM node disposal', function() {
    beforeEach(jasmine.prepareTestNode);

    it('Should run registered disposal callbacks when a node is cleaned', function () {
        var didRun = false;
        ko.utils.domNodeDisposal.addDisposeCallback(testNode, function() { didRun = true });

        expect(didRun).toEqual(false);
        ko.cleanNode(testNode);
        expect(didRun).toEqual(true);
    });

    it('Should run registered disposal callbacks on descendants when a node is cleaned', function () {
        var didRun = false;
        var childNode = document.createElement("DIV");
        var grandChildNode = document.createElement("DIV");
        testNode.appendChild(childNode);
        childNode.appendChild(grandChildNode);
        ko.utils.domNodeDisposal.addDisposeCallback(grandChildNode, function() { didRun = true });

        expect(didRun).toEqual(false);
        ko.cleanNode(testNode);
        expect(didRun).toEqual(true);
    });

    it('Should run registered disposal callbacks and detach from DOM when a node is removed', function () {
        var didRun = false;
        var childNode = document.createElement("DIV");
        testNode.appendChild(childNode);
        ko.utils.domNodeDisposal.addDisposeCallback(childNode, function() { didRun = true });

        expect(didRun).toEqual(false);
        expect(testNode.childNodes.length).toEqual(1);
        ko.removeNode(childNode);
        expect(didRun).toEqual(true);
        expect(testNode.childNodes.length).toEqual(0);
    });

    it('Should be able to remove previously-registered disposal callbacks', function() {
        var didRun = false;
        var callback = function() { didRun = true };
        ko.utils.domNodeDisposal.addDisposeCallback(testNode, callback);

        expect(didRun).toEqual(false);
        ko.utils.domNodeDisposal.removeDisposeCallback(testNode, callback);
        ko.cleanNode(testNode);
        expect(didRun).toEqual(false); // Didn't run only because we removed it
    });

    it('Should be able to attach disposal callback to a node that has been cloned', function() {
        // This represents bug https://github.com/SteveSanderson/knockout/issues/324
        // IE < 9 copies expando properties when cloning nodes, so if the node already has some DOM data associated with it,
        // the DOM data key will be copied too. This causes a problem for disposal, because if the original node gets disposed,
        // the shared DOM data is disposed, and then it becomes an error to try to set new DOM data on the clone.
        // The solution is to make the DOM-data-setting logic able to recover from the scenario by detecting that the original
        // DOM data is gone, and therefore recreating a new DOM data store for the clone.

        // Create an element with DOM data
        var originalNode = document.createElement("DIV");
        ko.utils.domNodeDisposal.addDisposeCallback(originalNode, function() { });

        // Clone it, then dispose it. Then check it's still safe to associate DOM data with the clone.
        var cloneNode = originalNode.cloneNode(true);
        ko.cleanNode(originalNode);
        ko.utils.domNodeDisposal.addDisposeCallback(cloneNode, function() { });
    });

    it('Should be able to clean any user data by overwriting "cleanExternalData"', function() {
        this.restoreAfter(ko.utils.domNodeDisposal, 'cleanExternalData'); // restore original function when done

        ko.utils.domNodeDisposal.cleanExternalData = function (node) {
            if (node['ko_test'])
                node['ko_test'] = undefined;
        };

        testNode['ko_test'] = "mydata";
        expect(testNode['ko_test']).toEqual("mydata");

        ko.cleanNode(testNode);
        expect(testNode['ko_test']).toBeUndefined();
    });

    it('If jQuery is referenced, should clear jQuery data when a node is cleaned', function() {
        if (typeof jQuery === 'undefined') {
            return; // Nothing to test. Run the specs with jQuery referenced for this to do anything.
        }

        var obj = {};
        jQuery.data(testNode, 'ko_test', obj);
        expect(jQuery.data(testNode, 'ko_test')).toBe(obj);

        ko.cleanNode(testNode);
        expect(jQuery.data(testNode, 'ko_test')).toBeUndefined();
    });

    it('If jQuery is referenced, should be able to prevent jQuery data from being cleared by overwriting "cleanExternalData"', function() {
        if (typeof jQuery === 'undefined') {
            return; // Nothing to test. Run the specs with jQuery referenced for this to do anything.
        }

        this.restoreAfter(ko.utils.domNodeDisposal, 'cleanExternalData'); // restore original function when done

        ko.utils.domNodeDisposal.cleanExternalData = function () {};

        var obj = {};
        jQuery.data(testNode, 'ko_test', obj);
        expect(jQuery.data(testNode, 'ko_test')).toBe(obj);

        ko.cleanNode(testNode);
        expect(jQuery.data(testNode, 'ko_test')).toBe(obj);
    });
});
{'fraction_non_alphanumeric': 0.11104338108300314, 'fraction_numerical': 0.0012191405059433099, 'mean_word_length': 2.926605504587156, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2341793', 'n_tokens_mistral': 2649, 'n_tokens_neox': 2567, 'n_words': 765}