changeoperation.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* bender-tags: document */
  6. 'use strict';
  7. var modules = bender.amd.require(
  8. 'document/document',
  9. 'document/changeoperation',
  10. 'document/position',
  11. 'document/range',
  12. 'document/character',
  13. 'document/attribute' );
  14. describe( 'ChangeOperation', function() {
  15. it( 'should insert attribute to the set of nodes', function() {
  16. var Document = modules[ 'document/document' ];
  17. var ChangeOperation = modules[ 'document/changeoperation' ];
  18. var Position = modules[ 'document/position' ];
  19. var Range = modules[ 'document/range' ];
  20. var Character = modules[ 'document/character' ];
  21. var Attribute = modules[ 'document/attribute' ];
  22. var doc = new Document();
  23. var newAttr = new Attribute( 'isNew', true );
  24. doc.root.children.push( new Character( doc.root, 'b' ) );
  25. doc.root.children.push( new Character( doc.root, 'a' ) );
  26. doc.root.children.push( new Character( doc.root, 'r' ) );
  27. doc.applyOperation( new ChangeOperation(
  28. new Range( new Position( [ 0 ], doc ), new Position( [ 2 ], doc ) ),
  29. null,
  30. newAttr,
  31. doc.version ) );
  32. expect( doc.version ).to.be.equal( 1 );
  33. expect( doc.root.children.length ).to.be.equal( 3 );
  34. expect( doc.root.children[ 0 ].hasAttr( newAttr ) ).to.be.true;
  35. expect( doc.root.children[ 1 ].hasAttr( newAttr ) ).to.be.true;
  36. expect( doc.root.children[ 2 ].attrs.length ).to.be.equal( 0 );
  37. } );
  38. it( 'should add attribute to the existing attributes', function() {
  39. var Document = modules[ 'document/document' ];
  40. var ChangeOperation = modules[ 'document/changeoperation' ];
  41. var Position = modules[ 'document/position' ];
  42. var Range = modules[ 'document/range' ];
  43. var Character = modules[ 'document/character' ];
  44. var Attribute = modules[ 'document/attribute' ];
  45. var doc = new Document();
  46. var newAttr = new Attribute( 'isNew', true );
  47. var fooAttr = new Attribute( 'foo', true );
  48. var barAttr = new Attribute( 'bar', true );
  49. doc.root.children.push( new Character( doc.root, 'x', [ fooAttr, barAttr ] ) );
  50. doc.applyOperation( new ChangeOperation(
  51. new Range( new Position( [ 0 ], doc ), new Position( [ 1 ], doc ) ),
  52. null,
  53. newAttr,
  54. doc.version ) );
  55. expect( doc.version ).to.be.equal( 1 );
  56. expect( doc.root.children.length ).to.be.equal( 1 );
  57. expect( doc.root.children[ 0 ].attrs.length ).to.be.equal( 3 );
  58. expect( doc.root.children[ 0 ].hasAttr( newAttr ) ).to.be.true;
  59. expect( doc.root.children[ 0 ].hasAttr( fooAttr ) ).to.be.true;
  60. expect( doc.root.children[ 0 ].hasAttr( barAttr ) ).to.be.true;
  61. } );
  62. it( 'should change attribute to the set of nodes', function() {
  63. var Document = modules[ 'document/document' ];
  64. var ChangeOperation = modules[ 'document/changeoperation' ];
  65. var Position = modules[ 'document/position' ];
  66. var Range = modules[ 'document/range' ];
  67. var Character = modules[ 'document/character' ];
  68. var Attribute = modules[ 'document/attribute' ];
  69. var doc = new Document();
  70. var oldAttr = new Attribute( 'isNew', false );
  71. var newAttr = new Attribute( 'isNew', true );
  72. doc.root.children.push( new Character( doc.root, 'b', [ oldAttr ] ) );
  73. doc.root.children.push( new Character( doc.root, 'a', [ oldAttr ] ) );
  74. doc.root.children.push( new Character( doc.root, 'r', [ oldAttr ] ) );
  75. doc.applyOperation( new ChangeOperation(
  76. new Range( new Position( [ 0 ], doc ), new Position( [ 2 ], doc ) ),
  77. oldAttr,
  78. newAttr,
  79. doc.version ) );
  80. expect( doc.version ).to.be.equal( 1 );
  81. expect( doc.root.children.length ).to.be.equal( 3 );
  82. expect( doc.root.children[ 0 ].attrs.length ).to.be.equal( 1 );
  83. expect( doc.root.children[ 0 ].hasAttr( newAttr ) ).to.be.true;
  84. expect( doc.root.children[ 1 ].attrs.length ).to.be.equal( 1 );
  85. expect( doc.root.children[ 1 ].hasAttr( newAttr ) ).to.be.true;
  86. expect( doc.root.children[ 2 ].attrs.length ).to.be.equal( 1 );
  87. expect( doc.root.children[ 2 ].hasAttr( oldAttr ) ).to.be.true;
  88. } );
  89. it( 'should change attribute in the middle of existing attributes', function() {
  90. var Document = modules[ 'document/document' ];
  91. var ChangeOperation = modules[ 'document/changeoperation' ];
  92. var Position = modules[ 'document/position' ];
  93. var Range = modules[ 'document/range' ];
  94. var Character = modules[ 'document/character' ];
  95. var Attribute = modules[ 'document/attribute' ];
  96. var doc = new Document();
  97. var fooAttr = new Attribute( 'foo', true );
  98. var x1Attr = new Attribute( 'x', 1 );
  99. var x2Attr = new Attribute( 'x', 2 );
  100. var barAttr = new Attribute( 'bar', true );
  101. doc.root.children.push( new Character( doc.root, 'x', [ fooAttr, x1Attr, barAttr ] ) );
  102. doc.applyOperation( new ChangeOperation(
  103. new Range( new Position( [ 0 ], doc ), new Position( [ 1 ], doc ) ),
  104. x1Attr,
  105. x2Attr,
  106. doc.version ) );
  107. expect( doc.version ).to.be.equal( 1 );
  108. expect( doc.root.children.length ).to.be.equal( 1 );
  109. expect( doc.root.children[ 0 ].attrs.length ).to.be.equal( 3 );
  110. expect( doc.root.children[ 0 ].hasAttr( fooAttr ) ).to.be.true;
  111. expect( doc.root.children[ 0 ].hasAttr( x2Attr ) ).to.be.true;
  112. expect( doc.root.children[ 0 ].hasAttr( barAttr ) ).to.be.true;
  113. } );
  114. it( 'should remove attribute', function() {
  115. var Document = modules[ 'document/document' ];
  116. var ChangeOperation = modules[ 'document/changeoperation' ];
  117. var Position = modules[ 'document/position' ];
  118. var Range = modules[ 'document/range' ];
  119. var Character = modules[ 'document/character' ];
  120. var Attribute = modules[ 'document/attribute' ];
  121. var doc = new Document();
  122. var fooAttr = new Attribute( 'foo', true );
  123. var xAttr = new Attribute( 'x', true );
  124. var barAttr = new Attribute( 'bar', true );
  125. doc.root.children.push( new Character( doc.root, 'x', [ fooAttr, xAttr, barAttr ] ) );
  126. doc.applyOperation( new ChangeOperation(
  127. new Range( new Position( [ 0 ], doc ), new Position( [ 1 ], doc ) ),
  128. xAttr,
  129. null,
  130. doc.version ) );
  131. expect( doc.version ).to.be.equal( 1 );
  132. expect( doc.root.children.length ).to.be.equal( 1 );
  133. expect( doc.root.children[ 0 ].attrs.length ).to.be.equal( 2 );
  134. expect( doc.root.children[ 0 ].hasAttr( fooAttr ) ).to.be.true;
  135. expect( doc.root.children[ 0 ].hasAttr( barAttr ) ).to.be.true;
  136. } );
  137. it( 'should create a change operation as a reverse', function() {
  138. var Document = modules[ 'document/document' ];
  139. var ChangeOperation = modules[ 'document/changeoperation' ];
  140. var Position = modules[ 'document/position' ];
  141. var Range = modules[ 'document/range' ];
  142. var Attribute = modules[ 'document/attribute' ];
  143. var doc = new Document();
  144. var oldAttr = new Attribute( 'x', 'old' );
  145. var newAttr = new Attribute( 'x', 'new' );
  146. var range = new Range( new Position( [ 0 ], doc ), new Position( [ 3 ], doc ) );
  147. var oppertaion = new ChangeOperation( range, oldAttr, newAttr, doc.version );
  148. var reverse = oppertaion.reverseOperation();
  149. expect( reverse ).to.be.an.instanceof( ChangeOperation );
  150. expect( reverse.baseVersion ).to.be.equals( 1 );
  151. expect( reverse.range ).to.be.equals( range );
  152. expect( reverse.oldAttr ).to.be.equals( newAttr );
  153. expect( reverse.newAttr ).to.be.equals( oldAttr );
  154. } );
  155. it( 'should undo insert attribute by applying reverse operation', function() {
  156. var Document = modules[ 'document/document' ];
  157. var ChangeOperation = modules[ 'document/changeoperation' ];
  158. var Position = modules[ 'document/position' ];
  159. var Range = modules[ 'document/range' ];
  160. var Character = modules[ 'document/character' ];
  161. var Attribute = modules[ 'document/attribute' ];
  162. var doc = new Document();
  163. var newAttr = new Attribute( 'isNew', true );
  164. doc.root.children.push( new Character( doc.root, 'b' ) );
  165. doc.root.children.push( new Character( doc.root, 'a' ) );
  166. doc.root.children.push( new Character( doc.root, 'r' ) );
  167. var oppertaion = new ChangeOperation(
  168. new Range( new Position( [ 0 ], doc ), new Position( [ 3 ], doc ) ),
  169. null,
  170. newAttr,
  171. doc.version );
  172. var reverse = oppertaion.reverseOperation();
  173. doc.applyOperation( oppertaion );
  174. doc.applyOperation( reverse );
  175. expect( doc.version ).to.be.equal( 2 );
  176. expect( doc.root.children.length ).to.be.equal( 3 );
  177. expect( doc.root.children[ 0 ].attrs.length ).to.be.equal( 0 );
  178. expect( doc.root.children[ 1 ].attrs.length ).to.be.equal( 0 );
  179. expect( doc.root.children[ 2 ].attrs.length ).to.be.equal( 0 );
  180. } );
  181. it( 'should undo change attribute by applying reverse operation', function() {
  182. var Document = modules[ 'document/document' ];
  183. var ChangeOperation = modules[ 'document/changeoperation' ];
  184. var Position = modules[ 'document/position' ];
  185. var Range = modules[ 'document/range' ];
  186. var Character = modules[ 'document/character' ];
  187. var Attribute = modules[ 'document/attribute' ];
  188. var doc = new Document();
  189. var oldAttr = new Attribute( 'isNew', false );
  190. var newAttr = new Attribute( 'isNew', true );
  191. doc.root.children.push( new Character( doc.root, 'b', [ oldAttr ] ) );
  192. doc.root.children.push( new Character( doc.root, 'a', [ oldAttr ] ) );
  193. doc.root.children.push( new Character( doc.root, 'r', [ oldAttr ] ) );
  194. var oppertaion = new ChangeOperation(
  195. new Range( new Position( [ 0 ], doc ), new Position( [ 3 ], doc ) ),
  196. oldAttr,
  197. newAttr,
  198. doc.version );
  199. var reverse = oppertaion.reverseOperation();
  200. doc.applyOperation( oppertaion );
  201. doc.applyOperation( reverse );
  202. expect( doc.version ).to.be.equal( 2 );
  203. expect( doc.root.children.length ).to.be.equal( 3 );
  204. expect( doc.root.children[ 0 ].attrs.length ).to.be.equal( 1 );
  205. expect( doc.root.children[ 0 ].hasAttr( oldAttr ) ).to.be.true;
  206. expect( doc.root.children[ 1 ].attrs.length ).to.be.equal( 1 );
  207. expect( doc.root.children[ 1 ].hasAttr( oldAttr ) ).to.be.true;
  208. expect( doc.root.children[ 2 ].attrs.length ).to.be.equal( 1 );
  209. expect( doc.root.children[ 2 ].hasAttr( oldAttr ) ).to.be.true;
  210. } );
  211. it( 'should undo remove attribute by applying reverse operation', function() {
  212. var Document = modules[ 'document/document' ];
  213. var ChangeOperation = modules[ 'document/changeoperation' ];
  214. var Position = modules[ 'document/position' ];
  215. var Range = modules[ 'document/range' ];
  216. var Character = modules[ 'document/character' ];
  217. var Attribute = modules[ 'document/attribute' ];
  218. var doc = new Document();
  219. var fooAttr = new Attribute( 'foo', false );
  220. doc.root.children.push( new Character( doc.root, 'b', [ fooAttr ] ) );
  221. doc.root.children.push( new Character( doc.root, 'a', [ fooAttr ] ) );
  222. doc.root.children.push( new Character( doc.root, 'r', [ fooAttr ] ) );
  223. var oppertaion = new ChangeOperation(
  224. new Range( new Position( [ 0 ], doc ), new Position( [ 3 ], doc ) ),
  225. fooAttr,
  226. null,
  227. doc.version );
  228. var reverse = oppertaion.reverseOperation();
  229. doc.applyOperation( oppertaion );
  230. doc.applyOperation( reverse );
  231. expect( doc.version ).to.be.equal( 2 );
  232. expect( doc.root.children.length ).to.be.equal( 3 );
  233. expect( doc.root.children[ 0 ].attrs.length ).to.be.equal( 1 );
  234. expect( doc.root.children[ 0 ].hasAttr( fooAttr ) ).to.be.true;
  235. expect( doc.root.children[ 1 ].attrs.length ).to.be.equal( 1 );
  236. expect( doc.root.children[ 1 ].hasAttr( fooAttr ) ).to.be.true;
  237. expect( doc.root.children[ 2 ].attrs.length ).to.be.equal( 1 );
  238. expect( doc.root.children[ 2 ].hasAttr( fooAttr ) ).to.be.true;
  239. } );
  240. it( 'should throw an error when one try to remove and the attribute does not exists', function() {
  241. var Document = modules[ 'document/document' ];
  242. var ChangeOperation = modules[ 'document/changeoperation' ];
  243. var Position = modules[ 'document/position' ];
  244. var Range = modules[ 'document/range' ];
  245. var Character = modules[ 'document/character' ];
  246. var Attribute = modules[ 'document/attribute' ];
  247. var doc = new Document();
  248. var fooAttr = new Attribute( 'foo', true );
  249. doc.root.children.push( new Character( doc.root, 'x' ) );
  250. expect( function() {
  251. doc.applyOperation( new ChangeOperation(
  252. new Range( new Position( [ 0 ], doc ), new Position( [ 1 ], doc ) ),
  253. fooAttr,
  254. null,
  255. doc.version ) );
  256. } ).to.throw( 'The attribute which should be removed does not exists.' );
  257. } );
  258. it( 'should throw an error when one try to insert and the attribute already exists', function() {
  259. var Document = modules[ 'document/document' ];
  260. var ChangeOperation = modules[ 'document/changeoperation' ];
  261. var Position = modules[ 'document/position' ];
  262. var Range = modules[ 'document/range' ];
  263. var Character = modules[ 'document/character' ];
  264. var Attribute = modules[ 'document/attribute' ];
  265. var doc = new Document();
  266. var x1Attr = new Attribute( 'x', 1 );
  267. var x2Attr = new Attribute( 'x', 2 );
  268. doc.root.children.push( new Character( doc.root, 'x', [ x1Attr ] ) );
  269. expect( function() {
  270. doc.applyOperation( new ChangeOperation(
  271. new Range( new Position( [ 0 ], doc ), new Position( [ 1 ], doc ) ),
  272. null,
  273. x2Attr,
  274. doc.version ) );
  275. } ).to.throw( 'The attribute with given key already exists.' );
  276. } );
  277. it( 'should throw an error when one try to change and the new and old attributes have different keys', function() {
  278. var Document = modules[ 'document/document' ];
  279. var ChangeOperation = modules[ 'document/changeoperation' ];
  280. var Position = modules[ 'document/position' ];
  281. var Range = modules[ 'document/range' ];
  282. var Character = modules[ 'document/character' ];
  283. var Attribute = modules[ 'document/attribute' ];
  284. var doc = new Document();
  285. var fooAttr = new Attribute( 'foo', true );
  286. var barAttr = new Attribute( 'bar', true );
  287. doc.root.children.push( new Character( doc.root, 'x' ) );
  288. expect( function() {
  289. doc.applyOperation( new ChangeOperation(
  290. new Range( new Position( [ 0 ], doc ), new Position( [ 1 ], doc ) ),
  291. fooAttr,
  292. barAttr,
  293. doc.version ) );
  294. } ).to.throw( 'Old and new attributes should have the same keys.' );
  295. } );
  296. it( 'should throw an error when one try to change and the old attribute does not exists', function() {
  297. var Document = modules[ 'document/document' ];
  298. var ChangeOperation = modules[ 'document/changeoperation' ];
  299. var Position = modules[ 'document/position' ];
  300. var Range = modules[ 'document/range' ];
  301. var Character = modules[ 'document/character' ];
  302. var Attribute = modules[ 'document/attribute' ];
  303. var doc = new Document();
  304. var x1Attr = new Attribute( 'x', 1 );
  305. var x2Attr = new Attribute( 'x', 2 );
  306. doc.root.children.push( new Character( doc.root, 'x' ) );
  307. expect( function() {
  308. doc.applyOperation( new ChangeOperation(
  309. new Range( new Position( [ 0 ], doc ), new Position( [ 1 ], doc ) ),
  310. x1Attr,
  311. x2Attr,
  312. doc.version ) );
  313. } ).to.throw( 'The attribute which should be changed does not exists.' );
  314. } );
  315. } );