undo.spec.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import expect = require('expect.js');
  4. import {
  5. JSONObject
  6. } from 'phosphor/lib/algorithm/json';
  7. import {
  8. ObservableUndoableVector, ISerializable
  9. } from '../../../../lib/notebook/common/undo';
  10. class Test implements ISerializable {
  11. constructor(value: JSONObject) {
  12. this._value = value;
  13. }
  14. toJSON(): JSONObject {
  15. return this._value;
  16. }
  17. private _value: JSONObject;
  18. }
  19. let count = 0;
  20. function factory(value: JSONObject): Test {
  21. value['count'] = count++;
  22. return new Test(value);
  23. }
  24. const value: JSONObject = { name: 'foo' };
  25. describe('notebook/common/undo', () => {
  26. describe('ObservableUndoableVector', () => {
  27. describe('#constructor', () => {
  28. it('should create a new ObservableUndoableVector', () => {
  29. let vector = new ObservableUndoableVector(factory);
  30. expect(vector).to.be.an(ObservableUndoableVector);
  31. });
  32. });
  33. describe('#canRedo', () => {
  34. it('should return false if there is no history', () => {
  35. let vector = new ObservableUndoableVector(factory);
  36. expect(vector.canRedo).to.be(false);
  37. });
  38. it('should return true if there is an undo that can be redone', () => {
  39. let vector = new ObservableUndoableVector(factory);
  40. vector.pushBack(new Test(value));
  41. vector.undo();
  42. expect(vector.canRedo).to.be(true);
  43. });
  44. });
  45. describe('#canUndo', () => {
  46. it('should return false if there is no history', () => {
  47. let vector = new ObservableUndoableVector(factory);
  48. expect(vector.canUndo).to.be(false);
  49. });
  50. it('should return true if there is a change that can be undone', () => {
  51. let vector = new ObservableUndoableVector(factory);
  52. vector.pushBack(factory(value));
  53. expect(vector.canUndo).to.be(true);
  54. });
  55. });
  56. describe('#dispose()', () => {
  57. it('should dispose of the resources used by the vector', () => {
  58. let vector = new ObservableUndoableVector(factory);
  59. vector.dispose();
  60. expect(vector.isDisposed).to.be(true);
  61. vector.dispose();
  62. expect(vector.isDisposed).to.be(true);
  63. });
  64. });
  65. describe('#beginCompoundOperation()', () => {
  66. it('should begin a compound operation', () => {
  67. let vector = new ObservableUndoableVector(factory);
  68. vector.beginCompoundOperation();
  69. vector.pushBack(factory(value));
  70. vector.pushBack(factory(value));
  71. vector.endCompoundOperation();
  72. expect(vector.canUndo).to.be(true);
  73. vector.undo();
  74. expect(vector.canUndo).to.be(false);
  75. });
  76. it('should not be undoable if isUndoAble is set to false', () => {
  77. let vector = new ObservableUndoableVector(factory);
  78. vector.beginCompoundOperation(false);
  79. vector.pushBack(factory(value));
  80. vector.pushBack(factory(value));
  81. vector.endCompoundOperation();
  82. expect(vector.canUndo).to.be(false);
  83. });
  84. });
  85. describe('#endCompoundOperation()', () => {
  86. it('should end a compound operation', () => {
  87. let vector = new ObservableUndoableVector(factory);
  88. vector.beginCompoundOperation();
  89. vector.pushBack(factory(value));
  90. vector.pushBack(factory(value));
  91. vector.endCompoundOperation();
  92. expect(vector.canUndo).to.be(true);
  93. vector.undo();
  94. expect(vector.canUndo).to.be(false);
  95. });
  96. });
  97. describe('#undo()', () => {
  98. it('should undo a pushBack', () => {
  99. let vector = new ObservableUndoableVector(factory);
  100. vector.pushBack(factory(value));
  101. vector.undo();
  102. expect(vector.length).to.be(0);
  103. });
  104. it('should undo a pushAll', () => {
  105. let vector = new ObservableUndoableVector(factory);
  106. vector.pushAll([factory(value), factory(value)]);
  107. vector.undo();
  108. expect(vector.length).to.be(0);
  109. });
  110. it('should undo a remove', () => {
  111. let vector = new ObservableUndoableVector(factory);
  112. vector.pushAll([factory(value), factory(value)]);
  113. vector.removeAt(0);
  114. vector.undo();
  115. expect(vector.length).to.be(2);
  116. });
  117. it('should undo a removeRange', () => {
  118. let vector = new ObservableUndoableVector(factory);
  119. vector.pushAll([factory(value), factory(value), factory(value),
  120. factory(value), factory(value), factory(value)]);
  121. vector.removeRange(1, 3);
  122. vector.undo();
  123. expect(vector.length).to.be(6);
  124. });
  125. it('should undo a move', () => {
  126. let items = [factory(value), factory(value), factory(value)];
  127. let vector = new ObservableUndoableVector(factory);
  128. vector.pushAll(items);
  129. vector.move(1, 2);
  130. vector.undo();
  131. expect((vector.at(1) as any)['count']).to.be((items[1] as any)['count']);
  132. });
  133. });
  134. describe('#redo()', () => {
  135. it('should redo a pushBack', () => {
  136. let vector = new ObservableUndoableVector(factory);
  137. vector.pushBack(factory(value));
  138. vector.undo();
  139. vector.redo();
  140. expect(vector.length).to.be(1);
  141. });
  142. it('should redo a pushAll', () => {
  143. let vector = new ObservableUndoableVector(factory);
  144. vector.pushAll([factory(value), factory(value)]);
  145. vector.undo();
  146. vector.redo();
  147. expect(vector.length).to.be(2);
  148. });
  149. it('should redo a remove', () => {
  150. let vector = new ObservableUndoableVector(factory);
  151. vector.pushAll([factory(value), factory(value)]);
  152. vector.removeAt(0);
  153. vector.undo();
  154. vector.redo();
  155. expect(vector.length).to.be(1);
  156. });
  157. it('should redo a removeRange', () => {
  158. let vector = new ObservableUndoableVector(factory);
  159. vector.pushAll([factory(value), factory(value), factory(value),
  160. factory(value), factory(value), factory(value)]);
  161. vector.removeRange(1, 3);
  162. vector.undo();
  163. vector.redo();
  164. expect(vector.length).to.be(4);
  165. });
  166. it('should undo a move', () => {
  167. let items = [factory(value), factory(value), factory(value)];
  168. let vector = new ObservableUndoableVector(factory);
  169. vector.pushAll(items);
  170. vector.move(1, 2);
  171. vector.undo();
  172. vector.redo();
  173. expect((vector.at(2) as any)['count']).to.be((items[1] as any)['count']);
  174. });
  175. });
  176. describe('#clearUndo()', () => {
  177. it('should clear the undo stack', () => {
  178. let vector = new ObservableUndoableVector(factory);
  179. vector.pushBack(factory(value));
  180. vector.clearUndo();
  181. expect(vector.canUndo).to.be(false);
  182. });
  183. });
  184. });
  185. });