undomanager_test.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Distributed under the BSD license:
  3. *
  4. * Copyright (c) 2010, Ajax.org B.V.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * * Neither the name of Ajax.org B.V. nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * ***** END LICENSE BLOCK ***** */
  30. if (typeof process !== "undefined") {
  31. ace_require("amd-loader");
  32. ace_require("./test/mockdom");
  33. }
  34. define(function(ace_require, exports, module) {
  35. "use strict";
  36. ace_require("./multi_select");
  37. var assert = ace_require("./test/assertions");
  38. var Range = ace_require("./range").Range;
  39. var Editor = ace_require("./editor").Editor;
  40. var EditSession = ace_require("./edit_session").EditSession;
  41. var MockRenderer = ace_require("./test/mockrenderer").MockRenderer;
  42. var UndoManager = ace_require("./undomanager").UndoManager;
  43. var editor, session, undoManager;
  44. module.exports = {
  45. name: "ACE undoManager.js",
  46. setUp: function() {
  47. editor = editor || new Editor(new MockRenderer());
  48. session = new EditSession("");
  49. undoManager = new UndoManager();
  50. undoManager.$keepRedoStack = true;
  51. session.setUndoManager(undoManager);
  52. editor.setSession(session);
  53. },
  54. "test: reabsing": function() {
  55. session.setValue("012345-012345-012345");
  56. session.insert({row: 0, column: 0}, "xx");
  57. session.markUndoGroup();
  58. session.remove(new Range(0, 10, 0, 15));
  59. session.markUndoGroup();
  60. session.insert({row: 0, column: 5}, "yy");
  61. session.markUndoGroup();
  62. editor.undo();
  63. editor.undo();
  64. var rev = undoManager.startNewGroup();
  65. session.insert({row: 0, column: 5}, "z\nz");
  66. undoManager.markIgnored(rev);
  67. // editor.undo()
  68. editor.redo();
  69. editor.redo();
  70. var val1 = editor.getValue();
  71. editor.undo();
  72. editor.undo();
  73. editor.undo();
  74. editor.redo();
  75. editor.redo();
  76. editor.redo();
  77. var val2 = editor.getValue();
  78. assert.equal(val1, val2);
  79. },
  80. "test: conflicting deletes": function() {
  81. session.setValue("012345\nabcdefg\nxyz");
  82. session.remove(new Range(0, 2, 0, 4));
  83. assert.equal(session.getLine(0), "0145");
  84. session.markUndoGroup();
  85. editor.undo();
  86. session.remove(new Range(0, 1, 0, 5));
  87. assert.equal(session.getLine(0), "05");
  88. session.markUndoGroup();
  89. editor.redo();
  90. assert.equal(session.getLine(0), "05");
  91. editor.undo();
  92. assert.equal(session.getLine(0), "012345");
  93. },
  94. "test: several deltas ignored": function() {
  95. session.setValue("012345\nabcdefg\nxyz");
  96. session.insert({row: 0, column: 5}, "zzzz");
  97. var rev = undoManager.startNewGroup();
  98. session.insert({row: 0, column: 5}, "yyyy");
  99. session.insert({row: 0, column: 5}, "aaaa");
  100. undoManager.markIgnored(rev, undoManager.getRevision() + 1);
  101. editor.undo();
  102. assert.equal(editor.getValue(), "01234aaaayyyy5\nabcdefg\nxyz");
  103. },
  104. "test: canUndo/canRedo and bookmarks": function() {
  105. session.setValue("012345\nabcdefg\nxyz");
  106. assert.ok(undoManager.isAtBookmark());
  107. editor.execCommand("removewordright");
  108. assert.ok(!undoManager.isAtBookmark());
  109. var rev = undoManager.getRevision();
  110. undoManager.bookmark();
  111. assert.ok(undoManager.isAtBookmark());
  112. editor.undo();
  113. assert.ok(!undoManager.isAtBookmark());
  114. undoManager.bookmark(rev);
  115. assert.ok(!undoManager.canUndo());
  116. assert.ok(undoManager.canRedo());
  117. editor.redo();
  118. assert.ok(undoManager.isAtBookmark());
  119. session.insert({row: 0, column: 5}, "yyyy");
  120. assert.ok(undoManager.canUndo());
  121. assert.ok(!undoManager.canRedo());
  122. },
  123. "test: getRevision": function () {
  124. session.setValue("012345\nabcdefg\nxyz");
  125. session.insert({row: 0, column: 5}, "yyyy");
  126. var rev = undoManager.getRevision();
  127. assert.equal(rev, 2);
  128. editor.undo();
  129. rev = undoManager.getRevision();
  130. assert.equal(rev, 0);
  131. },
  132. "test: swap deltas delete/insert": function () {
  133. session.setValue("012345\nabcdefg\nxyz");
  134. session.insert({row: 0, column: 5}, "zzzz");
  135. undoManager.startNewGroup();
  136. session.insert({row: 0, column: 5}, "yyyy");
  137. session.remove(new Range(0, 5, 0, 9));
  138. var rev = undoManager.startNewGroup();
  139. session.insert({row: 0, column: 5}, "aaaa");
  140. undoManager.markIgnored(rev);
  141. editor.undo();
  142. assert.equal(editor.getValue(), "01234aaaazzzz5\nabcdefg\nxyz");
  143. },
  144. "test: swap deltas insert/delete": function () {
  145. session.setValue("012345");
  146. undoManager.startNewGroup();
  147. session.insert({row: 0, column: 5}, "yyyy");
  148. var rev = undoManager.startNewGroup();
  149. session.remove(new Range(0, 5, 0, 9));
  150. undoManager.markIgnored(rev);
  151. editor.undo();
  152. assert.equal(editor.getValue(), "01234yyyy5");
  153. editor.redo();
  154. undoManager.startNewGroup();
  155. session.insert({row: 0, column: 5}, "yyyy");
  156. var rev1 = undoManager.startNewGroup();
  157. session.remove(new Range(0, 1, 0, 4));
  158. undoManager.markIgnored(rev1);
  159. editor.undo();
  160. assert.equal(editor.getValue(), "045");
  161. editor.redo();
  162. undoManager.startNewGroup();
  163. session.insert({row: 0, column: 1}, "yyyy");
  164. var rev2 = undoManager.startNewGroup();
  165. session.remove(new Range(0, 7, 0, 9));
  166. undoManager.markIgnored(rev2);
  167. editor.undo();
  168. assert.equal(editor.getValue(), "04yy5");
  169. },
  170. "test: swap deltas insert/insert": function () {
  171. session.setValue("012345");
  172. undoManager.startNewGroup();
  173. session.insert({row: 0, column: 1}, "yyyy");
  174. var rev = undoManager.startNewGroup();
  175. session.insert({row: 0, column: 2}, "xxxx");
  176. undoManager.markIgnored(rev);
  177. editor.undo();
  178. assert.equal(editor.getValue(), "0yyyy12345");
  179. },
  180. "test: swap deltas delete/delete": function () {
  181. session.setValue("012345");
  182. session.insert({row: 0, column: 5}, "zzzz");
  183. undoManager.startNewGroup();
  184. session.insert({row: 0, column: 5}, "yyyy");
  185. session.remove(new Range(0, 5, 0, 9));
  186. session.insert({row: 0, column: 5}, "aaaa");
  187. var rev = undoManager.startNewGroup();
  188. session.remove(new Range(0, 5, 0, 9));
  189. undoManager.markIgnored(rev);
  190. editor.undo();
  191. assert.equal(editor.getValue(), "01234aaaazzzz5");
  192. editor.undo();
  193. assert.equal(editor.getValue(), "01234zzzz5");
  194. editor.redo();
  195. var rev1=undoManager.startNewGroup();
  196. session.insert({row: 0, column: 1}, "yyyy");
  197. session.remove(new Range(0, 0, 0, 1));
  198. undoManager.markIgnored(rev1);
  199. editor.undo();
  200. assert.equal(editor.getValue(), "yyyy1234zzzz5");
  201. undoManager.startNewGroup();
  202. session.remove(new Range(0, 0, 0, 1));
  203. var rev2=undoManager.startNewGroup();
  204. session.remove(new Range(0, 3, 0, 5));
  205. undoManager.markIgnored(rev2);
  206. editor.undo();
  207. assert.equal(editor.getValue(), "yyyy34zzzz5");
  208. editor.redo();
  209. undoManager.startNewGroup();
  210. session.remove(new Range(0, 3, 0, 5));
  211. var rev3=undoManager.startNewGroup();
  212. session.remove(new Range(0, 1, 0, 5));
  213. undoManager.markIgnored(rev3);
  214. editor.undo();
  215. assert.equal(editor.getValue(), "yyyzzzz5");
  216. },
  217. "test: xform deltas insert/insert": function () {
  218. session.setValue("012345");
  219. session.insert({row: 0, column: 5}, "zzzz");
  220. undoManager.startNewGroup();
  221. session.insert({row: 0, column: 0}, "yyyy");
  222. editor.undo();
  223. session.insert({row: 0, column: 5}, "aaaa");
  224. editor.redo();
  225. assert.equal(editor.getValue(), "yyyy01234aaaazzzz5");
  226. },
  227. "test: xform deltas insert/delete": function () {
  228. session.setValue("012345");
  229. session.insert({row: 0, column: 5}, "zzzz");
  230. undoManager.startNewGroup();
  231. session.insert({row: 0, column: 0}, "yyyy");
  232. editor.undo();
  233. session.remove(new Range(0, 0, 0, 1));
  234. editor.redo();
  235. assert.equal(editor.getValue(), "yyyy1234zzzz5");
  236. session.setValue("012345");
  237. session.insert({row: 0, column: 5}, "zzzz");
  238. undoManager.startNewGroup();
  239. var rev=undoManager.startNewGroup();
  240. session.insert({row: 0, column: 0}, "yyyy");
  241. undoManager.markIgnored(rev);
  242. editor.undo();
  243. session.remove(new Range(0, 0, 0, 1));
  244. editor.redo();
  245. assert.equal(editor.getValue(), "yyy01234zzzz5");
  246. },
  247. "test: xform deltas delete/insert": function () {
  248. session.setValue("012345");
  249. session.insert({row: 0, column: 0}, "yyyy");
  250. undoManager.startNewGroup();
  251. session.remove(new Range(0, 0, 0, 1));
  252. editor.undo();
  253. session.insert({row: 0, column: 5}, "zzzz");
  254. editor.redo();
  255. assert.equal(editor.getValue(), "yyy0zzzz12345");
  256. },
  257. "test: xform deltas delete/delete": function () {
  258. session.setValue("012345");
  259. session.insert({row: 0, column: 0}, "yyyy");
  260. undoManager.startNewGroup();
  261. session.remove(new Range(0, 3, 0, 4));
  262. editor.undo();
  263. session.remove(new Range(0, 4, 0, 5));
  264. editor.redo();
  265. assert.equal(editor.getValue(), "yyy12345");
  266. session.setValue("012345");
  267. session.insert({row: 0, column: 0}, "yyyy");
  268. session.remove(new Range(0, 2, 0, 5));
  269. assert.equal(editor.getValue(), "yy12345");
  270. editor.undo();
  271. assert.equal(editor.getValue(), "012345");
  272. session.remove(new Range(0, 1, 0, 2));
  273. editor.redo();
  274. assert.equal(editor.getValue(), "yy2345");
  275. session.setValue("1234abcd ---");
  276. session.insert({row: 0, column: 0}, "ijkl");
  277. session.remove(new Range(0, 2, 0, 8));
  278. editor.undo();
  279. session.remove(new Range(0, 4, 0, 7));
  280. editor.redo();
  281. assert.equal(editor.getValue(), "ijd ---");
  282. assert.equal(undoManager.$prettyPrint(), '-[abc]0:4=>0:7\t(12)\n+[ijkl]0:0=>0:4\t(13)\n-[kl1234]0:2=>0:8\n---\n');
  283. },
  284. "test: clear redo stack after insert": function () {
  285. undoManager.$keepRedoStack = false;
  286. session.insert({row: 0, column: 0}, "y");
  287. editor.undo();
  288. assert.equal(session.$undoManager.$redoStack.length, 1);
  289. session.insert({row: 0, column: 0}, "y");
  290. assert.equal(session.$undoManager.$redoStack.length, 0);
  291. },
  292. "test: ignore deltas with incorrect boundaries": function () {
  293. session.setValue("012\n345\n678");
  294. undoManager.add({
  295. action: "remove",
  296. start: {row: 1, column: 0},
  297. end: {row: 3, column: 0},
  298. lines: ["hello", "world"]
  299. });
  300. editor.undo();
  301. assert.equal(editor.getValue(), "012\nhello\nworld345\n678");
  302. session.setValue("012\n345\n678");
  303. undoManager.add({
  304. action: "remove",
  305. start: {row: 3, column: 0},
  306. end: {row: 5, column: 0},
  307. lines: ["hello", "world"]
  308. });
  309. editor.undo();
  310. assert.equal(editor.getValue(), "012\n345\n678\nhello\nworld");
  311. session.setValue("012\n345\n678");
  312. undoManager.add({
  313. action: "remove",
  314. start: {row: 5, column: 0},
  315. end: {row: 7, column: 0},
  316. lines: ["hello", "world"]
  317. });
  318. editor.undo();
  319. assert.equal(editor.getValue(), "012\n345\n678");
  320. session.setValue("012\n345\n678");
  321. undoManager.add({
  322. action: "insert",
  323. start: {row: 3, column: 0},
  324. end: {row: 5, column: 0},
  325. lines: ["hello", "world"]
  326. });
  327. editor.undo();
  328. assert.equal(editor.getValue(), "012\n345\n678");
  329. session.setValue("012\n345\n678");
  330. undoManager.$redoStack.push([{
  331. action: "remove",
  332. start: {row: 2, column: 0},
  333. end: {row: 4, column: 0},
  334. lines: ["hello", "world"]
  335. }]);
  336. editor.redo();
  337. assert.equal(editor.getValue(), "012\n345\n678");
  338. },
  339. "test: do not ignore valid deltas": function () {
  340. editor.setValue("");
  341. editor.insert("\n");
  342. editor.insert("\n");
  343. editor.insert("\n");
  344. editor.insert("\n");
  345. editor.undo();
  346. assert.equal(editor.getValue(), "");
  347. editor.redo();
  348. assert.equal(editor.getValue(), "\n\n\n\n");
  349. }
  350. };
  351. });
  352. if (typeof module !== "undefined" && module === ace_require.main) {
  353. ace_require("asyncjs").test.testcase(module.exports).exec();
  354. }