mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-10 20:04:53 +02:00
814c3608db
This way doesn't depend on details of keybindings and the undo button. Also, implement this in DrawArea mode.
189 lines
6.4 KiB
JavaScript
189 lines
6.4 KiB
JavaScript
describe("iD.History", function () {
|
|
var history, spy,
|
|
action = function() { return iD.Graph(); };
|
|
|
|
beforeEach(function () {
|
|
history = iD.History();
|
|
spy = sinon.spy();
|
|
});
|
|
|
|
describe("#graph", function () {
|
|
it("returns the current graph", function () {
|
|
expect(history.graph()).to.be.an.instanceOf(iD.Graph);
|
|
});
|
|
});
|
|
|
|
describe("#perform", function () {
|
|
it("updates the graph", function () {
|
|
var graph = iD.Graph();
|
|
history.perform(d3.functor(graph));
|
|
expect(history.graph()).to.equal(graph);
|
|
});
|
|
|
|
it("pushes an undo annotation", function () {
|
|
history.perform(action, "annotation");
|
|
expect(history.undoAnnotation()).to.equal("annotation");
|
|
});
|
|
|
|
it("emits a change event", function () {
|
|
history.on('change', spy);
|
|
history.perform(action);
|
|
expect(spy).to.have.been.calledWith([]);
|
|
});
|
|
|
|
it("performs multiple actions", function () {
|
|
var action1 = sinon.stub().returns(iD.Graph()),
|
|
action2 = sinon.stub().returns(iD.Graph());
|
|
history.perform(action1, action2, "annotation");
|
|
expect(action1).to.have.been.called;
|
|
expect(action2).to.have.been.called;
|
|
expect(history.undoAnnotation()).to.equal("annotation");
|
|
});
|
|
});
|
|
|
|
describe("#replace", function () {
|
|
it("updates the graph", function () {
|
|
var graph = iD.Graph();
|
|
history.replace(d3.functor(graph));
|
|
expect(history.graph()).to.equal(graph);
|
|
});
|
|
|
|
it("replaces the undo annotation", function () {
|
|
history.perform(action, "annotation1");
|
|
history.replace(action, "annotation2");
|
|
expect(history.undoAnnotation()).to.equal("annotation2");
|
|
});
|
|
|
|
it("emits a change event", function () {
|
|
history.on('change', spy);
|
|
history.replace(action);
|
|
expect(spy).to.have.been.calledWith([]);
|
|
});
|
|
|
|
it("performs multiple actions", function () {
|
|
var action1 = sinon.stub().returns(iD.Graph()),
|
|
action2 = sinon.stub().returns(iD.Graph());
|
|
history.replace(action1, action2, "annotation");
|
|
expect(action1).to.have.been.called;
|
|
expect(action2).to.have.been.called;
|
|
expect(history.undoAnnotation()).to.equal("annotation");
|
|
});
|
|
});
|
|
|
|
describe("#undo", function () {
|
|
it("pops the undo stack", function () {
|
|
history.perform(action, "annotation");
|
|
history.undo();
|
|
expect(history.undoAnnotation()).to.be.undefined;
|
|
});
|
|
|
|
it("pushes the redo stack", function () {
|
|
history.perform(action, "annotation");
|
|
history.undo();
|
|
expect(history.redoAnnotation()).to.equal("annotation");
|
|
});
|
|
|
|
it("emits an undone event", function () {
|
|
history.perform(action);
|
|
history.on('undone', spy);
|
|
history.undo();
|
|
expect(spy).to.have.been.called;
|
|
});
|
|
|
|
it("emits a change event", function () {
|
|
history.perform(action);
|
|
history.on('change', spy);
|
|
history.undo();
|
|
expect(spy).to.have.been.calledWith([]);
|
|
});
|
|
});
|
|
|
|
describe("#redo", function () {
|
|
it("emits an redone event", function () {
|
|
history.perform(action);
|
|
history.undo();
|
|
history.on('change', spy);
|
|
history.redo();
|
|
expect(spy).to.have.been.called;
|
|
});
|
|
|
|
it("emits a change event", function () {
|
|
history.perform(action);
|
|
history.undo();
|
|
history.on('change', spy);
|
|
history.redo();
|
|
expect(spy).to.have.been.calledWith([]);
|
|
});
|
|
});
|
|
|
|
describe("#changes", function () {
|
|
it("includes created entities", function () {
|
|
var node = iD.Node();
|
|
history.perform(function (graph) { return graph.replace(node); });
|
|
expect(history.changes().created).to.eql([node]);
|
|
});
|
|
|
|
it("includes modified entities", function () {
|
|
var node1 = iD.Node({id: "n1"}),
|
|
node2 = node1.update({}),
|
|
graph = iD.Graph([node1]);
|
|
history.merge(graph);
|
|
history.perform(function (graph) { return graph.replace(node2); });
|
|
expect(history.changes().modified).to.eql([node2]);
|
|
});
|
|
|
|
it("includes deleted entities", function () {
|
|
var node = iD.Node({id: "n1"}),
|
|
graph = iD.Graph([node]);
|
|
history.merge(graph);
|
|
history.perform(function (graph) { return graph.remove(node); });
|
|
expect(history.changes().deleted).to.eql([node]);
|
|
});
|
|
});
|
|
|
|
describe("#hasChanges", function() {
|
|
it("is true when any of change's values are nonempty", function() {
|
|
var node = iD.Node();
|
|
history.perform(function (graph) { return graph.replace(node); });
|
|
expect(history.hasChanges()).to.eql(true);
|
|
});
|
|
|
|
it("is false when all of change's values are empty", function() {
|
|
expect(history.hasChanges()).to.eql(false);
|
|
});
|
|
});
|
|
|
|
describe("#numChanges", function() {
|
|
it("is 0 when there are no changes", function() {
|
|
expect(history.numChanges()).to.eql(0);
|
|
});
|
|
|
|
it("is the sum of all types of changes", function() {
|
|
var node1 = iD.Node({id: "n1"}),
|
|
node2 = iD.Node();
|
|
history.merge(iD.Graph([node1]));
|
|
history.perform(function (graph) { return graph.remove(node1); });
|
|
expect(history.numChanges()).to.eql(1);
|
|
history.perform(function (graph) { return graph.replace(node2); });
|
|
expect(history.numChanges()).to.eql(2);
|
|
});
|
|
});
|
|
|
|
describe("#reset", function () {
|
|
it("clears the version stack", function () {
|
|
history.perform(action, "annotation");
|
|
history.perform(action, "annotation");
|
|
history.undo();
|
|
history.reset();
|
|
expect(history.undoAnnotation()).to.be.undefined;
|
|
expect(history.redoAnnotation()).to.be.undefined;
|
|
});
|
|
|
|
it("emits a change event", function () {
|
|
history.on('change', spy);
|
|
history.reset();
|
|
expect(spy).to.have.been.called;
|
|
});
|
|
});
|
|
});
|