<commit_before>describe('iD.Graph', function() {
    describe("constructor", function () {
        it("accepts an entities Object", function () {
            var entity = iD.Entity(),
                graph = iD.Graph({'n-1': entity});
            expect(graph.entity('n-1')).to.equal(entity);
        });

        it("accepts an entities Array", function () {
            var entity = iD.Entity(),
                graph = iD.Graph([entity]);
            expect(graph.entity(entity.id)).to.equal(entity);
        });

        it("accepts a Graph", function () {
            var entity = iD.Entity(),
                graph = iD.Graph(iD.Graph([entity]));
            expect(graph.entity(entity.id)).to.equal(entity);
        });

        it("copies other's entities", function () {
            var entity = iD.Entity(),
                base   = iD.Graph([entity]),
                graph  = iD.Graph(base);
            expect(graph.entities).not.to.equal(base.entities);
        });

        it("rebases on other's base", function () {
            var base   = iD.Graph(),
                graph  = iD.Graph(base);
            expect(graph.base().entities).to.equal(base.base().entities);
        });

        it("freezes by default", function () {
            expect(iD.Graph().frozen).to.be.true;
        });

        it("remains mutable if passed true as second argument", function () {
            expect(iD.Graph([], true).frozen).not.to.be.true;
        });
    });

    describe("#freeze", function () {
        it("sets the frozen flag", function () {
            expect(iD.Graph([], true).freeze().frozen).to.be.true;
        });

        if (iD.debug) {
            it("freezes entities", function () {
                expect(Object.isFrozen(iD.Graph().entities)).to.be.true;
            });
        }
    });

    describe("#rebase", function () {
        it("preserves existing entities", function () {
            var node = iD.Node({id: 'n'}),
                graph = iD.Graph([node]);
            graph.rebase({});
            expect(graph.entity('n')).to.equal(node);
        });

        it("includes new entities", function () {
            var node = iD.Node({id: 'n'}),
                graph = iD.Graph();
            graph.rebase({'n': node});
            expect(graph.entity('n')).to.equal(node);
        });

        it("gives precedence to existing entities", function () {
            var a = iD.Node({id: 'n'}),
                b = iD.Node({id: 'n'}),
                graph = iD.Graph([a]);
            graph.rebase({'n': b});
            expect(graph.entity('n')).to.equal(a);
        });

        it("inherits entities from base prototypally", function () {
            var graph = iD.Graph();
            graph.rebase({'n': iD.Node()});
            expect(graph.entities).not.to.have.ownProperty('n');
        });

        it("updates parentWays", function () {
            var n = iD.Node({id: 'n'}),
                w1 = iD.Way({id: 'w1', nodes: ['n']}),
                w2 = iD.Way({id: 'w2', nodes: ['n']}),
                graph = iD.Graph([n, w1]);

            graph.rebase({ 'w2': w2 });
            expect(graph.parentWays(n)).to.eql([w1, w2]);
            expect(graph._parentWays.hasOwnProperty('n')).to.be.false;
        });

        it("updates parentWays for nodes with modified parentWays", function () {
            var n = iD.Node({id: 'n'}),
                w1 = iD.Way({id: 'w1', nodes: ['n']}),
                w2 = iD.Way({id: 'w2', nodes: ['n']}),
                w3 = iD.Way({id: 'w3', nodes: ['n']}),
                graph = iD.Graph([n, w1]),
                graph2 = graph.replace(w2);
            graph.rebase({ 'w3': w3 });
            graph2.rebase({ 'w3': w3 });

            expect(graph2.parentWays(n)).to.eql([w1, w2, w3]);
        });

        it("avoids re-adding removed parentWays", function() {
            var n = iD.Node({id: 'n'}),
                w1 = iD.Way({id: 'w1', nodes: ['n']}),
                graph = iD.Graph([n, w1]),
                graph2 = graph.remove(w1);
            graph.rebase({ 'w1': w1 });
            graph2.rebase({ 'w1': w1 });
            expect(graph2.parentWays(n)).to.eql([]);
        });

        it("updates parentRelations", function () {
            var n = iD.Node({id: 'n'}),
                r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}),
                r2 = iD.Relation({id: 'r2', members: [{id: 'n'}]}),
                graph = iD.Graph([n, r1]);

            graph.rebase({'r2': r2});

            expect(graph.parentRelations(n)).to.eql([r1, r2]);
            expect(graph._parentRels.hasOwnProperty('n')).to.be.false;
        });

        it("avoids re-adding removed parentRels", function() {
            var n = iD.Node({id: 'n'}),
                r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}),
                graph = iD.Graph([n, r1]),
                graph2 = graph.remove(r1);
            graph.rebase({ 'w1': r1 });
            graph2.rebase({ 'w1': r1 });
            expect(graph2.parentWays(n)).to.eql([]);
        });

        it("updates parentRels for nodes with modified parentWays", function () {
            var n = iD.Node({id: 'n'}),
                r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}),
                r2 = iD.Relation({id: 'r2', members: [{id: 'n'}]}),
                r3 = iD.Relation({id: 'r3', members: [{id: 'n'}]}),
                graph = iD.Graph([n, r1]),
                graph2 = graph.replace(r2);

            graph.rebase({'r3': r3});
            graph2.rebase({'r3': r3});
            expect(graph2.parentRelations(n)).to.eql([r1, r2, r3]);
        });

    });

    describe("#remove", function () {
        it("returns a new graph", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);
            expect(graph.remove(node)).not.to.equal(graph);
        });

        it("doesn't modify the receiver", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);
            graph.remove(node);
            expect(graph.entity(node.id)).to.equal(node);
        });

        it("removes the entity from the result", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);
            expect(graph.remove(node).entity(node.id)).to.be.undefined;
        });
    });

    describe("#replace", function () {
        it("returns a new graph", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);
            expect(graph.replace(node)).not.to.equal(graph);
        });

        it("doesn't modify the receiver", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);
            graph.replace(node);
            expect(graph.entity(node.id)).to.equal(node);
        });

        it("replaces the entity in the result", function () {
            var node1 = iD.Node(),
                node2 = node1.update({}),
                graph = iD.Graph([node1]);
            expect(graph.replace(node2).entity(node2.id)).to.equal(node2);
        });
    });

    describe("#update", function () {
        it("returns a new graph if self is frozen", function () {
            var graph = iD.Graph();
            expect(graph.update()).not.to.equal(graph);
        });

        it("returns self if self is not frozen", function () {
            var graph = iD.Graph({}, true);
            expect(graph.update()).to.equal(graph);
        });

        it("doesn't modify self is self is frozen", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);

            graph.update(function (graph) { graph.remove(node); });

            expect(graph.entity(node.id)).to.equal(node);
        });

        it("modifies self is self is not frozen", function () {
            var node = iD.Node(),<commit_msg>Add tests for #replace #remove #rebase<commit_after>describe('iD.Graph', function() {
    describe("constructor", function () {
        it("accepts an entities Object", function () {
            var entity = iD.Entity(),
                graph = iD.Graph({'n-1': entity});
            expect(graph.entity('n-1')).to.equal(entity);
        });

        it("accepts an entities Array", function () {
            var entity = iD.Entity(),
                graph = iD.Graph([entity]);
            expect(graph.entity(entity.id)).to.equal(entity);
        });

        it("accepts a Graph", function () {
            var entity = iD.Entity(),
                graph = iD.Graph(iD.Graph([entity]));
            expect(graph.entity(entity.id)).to.equal(entity);
        });

        it("copies other's entities", function () {
            var entity = iD.Entity(),
                base   = iD.Graph([entity]),
                graph  = iD.Graph(base);
            expect(graph.entities).not.to.equal(base.entities);
        });

        it("rebases on other's base", function () {
            var base   = iD.Graph(),
                graph  = iD.Graph(base);
            expect(graph.base().entities).to.equal(base.base().entities);
        });

        it("freezes by default", function () {
            expect(iD.Graph().frozen).to.be.true;
        });

        it("remains mutable if passed true as second argument", function () {
            expect(iD.Graph([], true).frozen).not.to.be.true;
        });
    });

    describe("#freeze", function () {
        it("sets the frozen flag", function () {
            expect(iD.Graph([], true).freeze().frozen).to.be.true;
        });

        if (iD.debug) {
            it("freezes entities", function () {
                expect(Object.isFrozen(iD.Graph().entities)).to.be.true;
            });
        }
    });

    describe("#rebase", function () {
        it("preserves existing entities", function () {
            var node = iD.Node({id: 'n'}),
                graph = iD.Graph([node]);
            graph.rebase({});
            expect(graph.entity('n')).to.equal(node);
        });

        it("includes new entities", function () {
            var node = iD.Node({id: 'n'}),
                graph = iD.Graph();
            graph.rebase({'n': node});
            expect(graph.entity('n')).to.equal(node);
        });

        it("gives precedence to existing entities", function () {
            var a = iD.Node({id: 'n'}),
                b = iD.Node({id: 'n'}),
                graph = iD.Graph([a]);
            graph.rebase({'n': b});
            expect(graph.entity('n')).to.equal(a);
        });

        it("inherits entities from base prototypally", function () {
            var graph = iD.Graph();
            graph.rebase({'n': iD.Node()});
            expect(graph.entities).not.to.have.ownProperty('n');
        });

        it("updates parentWays", function () {
            var n = iD.Node({id: 'n'}),
                w1 = iD.Way({id: 'w1', nodes: ['n']}),
                w2 = iD.Way({id: 'w2', nodes: ['n']}),
                graph = iD.Graph([n, w1]);

            graph.rebase({ 'w2': w2 });
            expect(graph.parentWays(n)).to.eql([w1, w2]);
            expect(graph._parentWays.hasOwnProperty('n')).to.be.false;
        });

        it("avoids adding duplicate parentWays", function () {
            var n = iD.Node({id: 'n'}),
                w1 = iD.Way({id: 'w1', nodes: ['n']}),
                graph = iD.Graph([n, w1]);
            graph.rebase({ 'w1': w1 });
            expect(graph.parentWays(n)).to.eql([w1]);
        });

        it("updates parentWays for nodes with modified parentWays", function () {
            var n = iD.Node({id: 'n'}),
                w1 = iD.Way({id: 'w1', nodes: ['n']}),
                w2 = iD.Way({id: 'w2', nodes: ['n']}),
                w3 = iD.Way({id: 'w3', nodes: ['n']}),
                graph = iD.Graph([n, w1]),
                graph2 = graph.replace(w2);
            graph.rebase({ 'w3': w3 });
            graph2.rebase({ 'w3': w3 });

            expect(graph2.parentWays(n)).to.eql([w1, w2, w3]);
        });

        it("avoids re-adding removed parentWays", function() {
            var n = iD.Node({id: 'n'}),
                w1 = iD.Way({id: 'w1', nodes: ['n']}),
                graph = iD.Graph([n, w1]),
                graph2 = graph.remove(w1);
            graph.rebase({ 'w1': w1 });
            graph2.rebase({ 'w1': w1 });
            expect(graph2.parentWays(n)).to.eql([]);
        });

        it("updates parentRelations", function () {
            var n = iD.Node({id: 'n'}),
                r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}),
                r2 = iD.Relation({id: 'r2', members: [{id: 'n'}]}),
                graph = iD.Graph([n, r1]);

            graph.rebase({'r2': r2});

            expect(graph.parentRelations(n)).to.eql([r1, r2]);
            expect(graph._parentRels.hasOwnProperty('n')).to.be.false;
        });

        it("avoids re-adding removed parentRels", function() {
            var n = iD.Node({id: 'n'}),
                r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}),
                graph = iD.Graph([n, r1]),
                graph2 = graph.remove(r1);
            graph.rebase({ 'w1': r1 });
            graph2.rebase({ 'w1': r1 });
            expect(graph2.parentWays(n)).to.eql([]);
        });

        it("updates parentRels for nodes with modified parentWays", function () {
            var n = iD.Node({id: 'n'}),
                r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}),
                r2 = iD.Relation({id: 'r2', members: [{id: 'n'}]}),
                r3 = iD.Relation({id: 'r3', members: [{id: 'n'}]}),
                graph = iD.Graph([n, r1]),
                graph2 = graph.replace(r2);

            graph.rebase({'r3': r3});
            graph2.rebase({'r3': r3});
            expect(graph2.parentRelations(n)).to.eql([r1, r2, r3]);
        });

    });

    describe("#remove", function () {
        it("returns a new graph", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);
            expect(graph.remove(node)).not.to.equal(graph);
        });

        it("doesn't modify the receiver", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);
            graph.remove(node);
            expect(graph.entity(node.id)).to.equal(node);
        });

        it("removes the entity from the result", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);
            expect(graph.remove(node).entity(node.id)).to.be.undefined;
        });

        it("removes the entity as a parentWay", function () {
            var node = iD.Node({id: 'n' }),
                w1 = iD.Way({id: 'w', nodes: ['n']}),
                graph = iD.Graph([node, w1]);
            expect(graph.remove(w1).parentWays(node)).to.eql([]);
        });

        it("removes the entity as a parentRelation", function () {
            var node = iD.Node({id: 'n' }),
                r1 = iD.Relation({id: 'w', members: [{id: 'n' }]}),
                graph = iD.Graph([node, r1]);
            expect(graph.remove(r1).parentRelations(node)).to.eql([]);
        });
    });

    describe("#replace", function () {
        it("returns a new graph", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);
            expect(graph.replace(node)).not.to.equal(graph);
        });

        it("doesn't modify the receiver", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);
            graph.replace(node);
            expect(graph.entity(node.id)).to.equal(node);
        });

        it("replaces the entity in the result", function () {
            var node1 = iD.Node(),
                node2 = node1.update({}),
                graph = iD.Graph([node1]);
            expect(graph.replace(node2).entity(node2.id)).to.equal(node2);
        });

        it("adds parentWays",  function () {
            var node = iD.Node({id: 'n' }),
                w1 = iD.Way({id: 'w', nodes: ['n']}),
                graph = iD.Graph([node]);
            expect(graph.replace(w1).parentWays(node)).to.eql([w1]);
        });

        it("removes parentWays",  function () {
            var node = iD.Node({id: 'n' }),
                w1 = iD.Way({id: 'w', nodes: ['n']}),
                graph = iD.Graph([node, w1]);
            expect(graph.remove(w1).parentWays(node)).to.eql([]);
        });

        it("doesn't add duplicate parentWays",  function () {
            var node = iD.Node({id: 'n' }),
                w1 = iD.Way({id: 'w', nodes: ['n']}),
                graph = iD.Graph([node, w1]);
            expect(graph.replace(w1).parentWays(node)).to.eql([w1]);
        });

        it("adds parentRels",  function () {
            var node = iD.Node({id: 'n' }),
            r1 = iD.Relation({id: 'w', members: [{id: 'n'}]}),
            graph = iD.Graph([node]);
            expect(graph.replace(r1).parentRelations(node)).to.eql([r1]);
        });

        it("removes parentRelations",  function () {
            var node = iD.Node({id: 'n' }),
            r1 = iD.Relation({id: 'w', members: [{id: 'n'}]}),
            graph = iD.Graph([node, r1]);
            expect(graph.remove(r1).parentRelations(node)).to.eql([]);
        });

        it("doesn't add duplicate parentRelations",  function () {
            var node = iD.Node({id: 'n' }),
            r1 = iD.Relation({id: 'w', members: [{id: 'n'}]}),
            graph = iD.Graph([node, r1]);
            expect(graph.replace(r1).parentRelations(node)).to.eql([r1]);
        });

    });

    describe("#update", function () {
        it("returns a new graph if self is frozen", function () {
            var graph = iD.Graph();
            expect(graph.update()).not.to.equal(graph);
        });

        it("returns self if self is not frozen", function () {
            var graph = iD.Graph({}, true);
            expect(graph.update()).to.equal(graph);
        });

        it("doesn't modify self is self is frozen", function () {
            var node = iD.Node(),
                graph = iD.Graph([node]);

            graph.update(function (graph) { graph.remove(node); });

            expect(graph.entity(node.id)).to.equal(node);
        });

        it("modifies self is self is not frozen", function () {
            var node = iD.Node(),
{'fraction_non_alphanumeric': 0.189961811238407, 'fraction_numerical': 0.011020185488270594, 'mean_word_length': 1.6862543962485346, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, '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': '5362467', 'n_tokens_mistral': 5842, 'n_tokens_neox': 5637, 'n_words': 1109}