2012-02-07 00:12:31 +00:00
module ( 've/dm' ) ;
2011-11-02 21:20:48 +00:00
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.getData' , 1 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
// Test 1
2012-02-07 00:12:31 +00:00
deepEqual ( documentModel . getData ( ) , veTest . data , 'Flattening plain objects results in correct data' ) ;
2011-11-02 21:20:48 +00:00
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.getChildren' , 1 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
function equalLengths ( a , b ) {
if ( a . length !== b . length ) {
return false ;
}
for ( var i = 0 ; i < a . length ; i ++ ) {
if ( a [ i ] . getContentLength ( ) !== b [ i ] . getContentLength ( ) ) {
console . log ( 'mismatched content lengths' , a [ i ] , b [ i ] ) ;
return false ;
}
2011-11-16 23:32:57 +00:00
var aIsBranch = typeof a [ i ] . getChildren === 'function' ;
var bIsBranch = typeof b [ i ] . getChildren === 'function' ;
2011-11-03 21:48:40 +00:00
if ( aIsBranch !== bIsBranch ) {
return false ;
}
if ( aIsBranch && ! equalLengths ( a [ i ] . getChildren ( ) , b [ i ] . getChildren ( ) ) ) {
2011-11-02 21:20:48 +00:00
return false ;
}
}
return true ;
}
// Test 1
ok (
2012-02-07 00:12:31 +00:00
equalLengths ( documentModel . getChildren ( ) , veTest . tree ) ,
2011-11-02 21:20:48 +00:00
'Nodes in the model tree contain correct lengths'
) ;
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.getRelativeContentOffset' , 7 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
// Test 1
equal (
documentModel . getRelativeContentOffset ( 1 , 1 ) ,
2 ,
'getRelativeContentOffset advances forwards through the inside of elements'
) ;
// Test 2
equal (
documentModel . getRelativeContentOffset ( 2 , - 1 ) ,
1 ,
'getRelativeContentOffset advances backwards through the inside of elements'
) ;
// Test 3
equal (
documentModel . getRelativeContentOffset ( 3 , 1 ) ,
4 ,
'getRelativeContentOffset uses the offset after the last character in an element'
) ;
2011-11-23 19:37:57 +00:00
// Test 4
2011-11-02 21:20:48 +00:00
equal (
documentModel . getRelativeContentOffset ( 1 , - 1 ) ,
1 ,
2011-11-23 19:37:57 +00:00
'getRelativeContentOffset does not allow moving before the content of the first node'
2011-11-02 21:20:48 +00:00
) ;
2011-11-23 19:37:57 +00:00
// Test 5
2011-11-02 21:20:48 +00:00
equal (
2011-11-23 19:37:57 +00:00
documentModel . getRelativeContentOffset ( 33 , 1 ) ,
33 ,
'getRelativeContentOffset does not allow moving after the content of the last node'
2011-11-02 21:20:48 +00:00
) ;
2011-11-23 19:37:57 +00:00
// Test 6
2011-11-02 21:20:48 +00:00
equal (
documentModel . getRelativeContentOffset ( 4 , 1 ) ,
9 ,
'getRelativeContentOffset advances forwards between elements'
) ;
2011-11-23 19:37:57 +00:00
// Test 7
2011-11-02 21:20:48 +00:00
equal (
2011-11-09 23:39:47 +00:00
documentModel . getRelativeContentOffset ( 32 , - 1 ) ,
25 ,
2011-11-02 21:20:48 +00:00
'getRelativeContentOffset advances backwards between elements'
) ;
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.getContentData' , 6 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ,
2011-11-02 21:20:48 +00:00
childNodes = documentModel . getChildren ( ) ;
// Test 1
deepEqual (
2012-02-07 00:12:31 +00:00
childNodes [ 0 ] . getContentData ( new ve . Range ( 1 , 3 ) ) ,
2011-11-02 21:20:48 +00:00
[
2011-11-21 22:32:22 +00:00
[ 'b' , { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' } ] ,
[ 'c' , { 'type' : 'textStyle/italic' , 'hash' : '{"type":"textStyle/italic"}' } ]
2011-11-02 21:20:48 +00:00
] ,
2011-12-05 19:41:04 +00:00
'getContentData can return an ending portion of the content'
2011-11-02 21:20:48 +00:00
) ;
// Test 2
deepEqual (
2012-02-07 00:12:31 +00:00
childNodes [ 0 ] . getContentData ( new ve . Range ( 0 , 2 ) ) ,
2011-11-21 22:32:22 +00:00
[ 'a' , [ 'b' , { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' } ] ] ,
2011-12-05 19:41:04 +00:00
'getContentData can return a beginning portion of the content'
2011-11-02 21:20:48 +00:00
) ;
// Test 3
deepEqual (
2012-02-07 00:12:31 +00:00
childNodes [ 0 ] . getContentData ( new ve . Range ( 1 , 2 ) ) ,
2011-11-21 22:32:22 +00:00
[ [ 'b' , { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' } ] ] ,
2011-12-05 19:41:04 +00:00
'getContentData can return a middle portion of the content'
2011-11-02 21:20:48 +00:00
) ;
// Test 4
try {
2012-02-07 00:12:31 +00:00
childNodes [ 0 ] . getContentData ( new ve . Range ( - 1 , 3 ) ) ;
2011-11-02 21:20:48 +00:00
} catch ( negativeIndexError ) {
2011-12-05 19:41:04 +00:00
ok ( true , 'getContentData throws exceptions when given a range with start < 0' ) ;
2011-11-02 21:20:48 +00:00
}
// Test 5
try {
2012-02-07 00:12:31 +00:00
childNodes [ 0 ] . getContentData ( new ve . Range ( 0 , 4 ) ) ;
2011-11-02 21:20:48 +00:00
} catch ( outOfRangeError ) {
2011-12-05 19:41:04 +00:00
ok ( true , 'getContentData throws exceptions when given a range with end > length' ) ;
2011-11-02 21:20:48 +00:00
}
// Test 6
2011-12-05 19:41:04 +00:00
deepEqual ( childNodes [ 2 ] . getContentData ( ) , [ 'h' ] , 'Content can be extracted from nodes' ) ;
2011-11-02 21:20:48 +00:00
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.getIndexOfAnnotation' , 3 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
2011-11-21 22:32:22 +00:00
var bold = { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' } ,
italic = { 'type' : 'textStyle/italic' , 'hash' : '{"type":"textStyle/italic"}' } ,
nothing = { 'type' : 'nothing' , 'hash' : '{"type":"nothing"}' } ,
2011-11-02 21:20:48 +00:00
character = [ 'a' , bold , italic ] ;
// Test 1
equal (
2012-02-07 00:12:31 +00:00
ve . dm . DocumentNode . getIndexOfAnnotation ( character , bold ) ,
2011-11-02 21:20:48 +00:00
1 ,
'getIndexOfAnnotation get the correct index'
) ;
// Test 2
equal (
2012-02-07 00:12:31 +00:00
ve . dm . DocumentNode . getIndexOfAnnotation ( character , italic ) ,
2011-11-02 21:20:48 +00:00
2 ,
'getIndexOfAnnotation get the correct index'
) ;
// Test 3
equal (
2012-02-07 00:12:31 +00:00
ve . dm . DocumentNode . getIndexOfAnnotation ( character , nothing ) ,
2011-11-02 21:20:48 +00:00
- 1 ,
'getIndexOfAnnotation returns -1 if the annotation was not found'
) ;
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.getWordBoundaries' , 2 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
deepEqual (
documentModel . getWordBoundaries ( 2 ) ,
2012-02-07 00:12:31 +00:00
new ve . Range ( 1 , 4 ) ,
2011-11-02 21:20:48 +00:00
'getWordBoundaries returns range around nearest whole word'
) ;
strictEqual (
documentModel . getWordBoundaries ( 5 ) ,
null ,
'getWordBoundaries returns null when given non-content offset'
) ;
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.getAnnotationBoundaries' , 2 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
deepEqual (
2011-11-03 18:15:24 +00:00
documentModel . getAnnotationBoundaries ( 2 , { 'type' : 'textStyle/bold' } ) ,
2012-02-07 00:12:31 +00:00
new ve . Range ( 2 , 3 ) ,
2011-11-02 21:20:48 +00:00
'getWordBoundaries returns range around content covered by annotation'
) ;
strictEqual (
2011-11-03 18:15:24 +00:00
documentModel . getAnnotationBoundaries ( 1 , { 'type' : 'textStyle/bold' } ) ,
2011-11-02 21:20:48 +00:00
null ,
'getWordBoundaries returns null if offset is not covered by annotation'
) ;
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.getAnnotationsFromOffset' , 4 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
deepEqual (
documentModel . getAnnotationsFromOffset ( 1 ) ,
[ ] ,
'getAnnotationsFromOffset returns empty array for non-annotated content'
) ;
deepEqual (
documentModel . getAnnotationsFromOffset ( 2 ) ,
2011-11-21 22:32:22 +00:00
[ { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' } ] ,
2011-11-02 21:20:48 +00:00
'getAnnotationsFromOffset returns annotations of annotated content correctly'
) ;
deepEqual (
documentModel . getAnnotationsFromOffset ( 3 ) ,
2011-11-21 22:32:22 +00:00
[ { 'type' : 'textStyle/italic' , 'hash' : '{"type":"textStyle/italic"}' } ] ,
2011-11-02 21:20:48 +00:00
'getAnnotationsFromOffset returns annotations of annotated content correctly'
) ;
deepEqual (
documentModel . getAnnotationsFromOffset ( 0 ) ,
[ ] ,
'getAnnotationsFromOffset returns empty array when given a non-content offset'
) ;
} ) ;
2012-03-12 00:07:33 +00:00
function compareOffsets ( documentModel , expectedOffsets , descPrefix , start , end ) {
start = start || 0 ;
end = end || expectedOffsets . length ;
equal ( documentModel . offsetMap . length , expectedOffsets . length , descPrefix + ' (offset map has the correct length)' ) ;
// We use a loop instead of equal( documentModel.offsetMap, expectedOffsets ); because
// the latter will descend into the elements and their children
for ( var i = start ; i < end ; i ++ ) {
ok ( documentModel . offsetMap [ i ] == expectedOffsets [ i ] , descPrefix + ' (offset map elements point to the correct nodes (element ' + i + '))' ) ;
}
}
function repeatArray ( element , n ) {
var a = [ ] ;
for ( var i = 0 ; i < n ; i ++ ) {
a [ i ] = element ;
}
return a ;
}
test ( 've.dm.DocumentNode.offsetMap' , function ( ) {
var documentModel = new ve . dm . DocumentNode ( veTest . data ) ;
var expectedOffsets = veTest . getOffsets ( documentModel ) ;
compareOffsets ( documentModel , expectedOffsets , 'Constructor creates offset map correctly' ) ;
} ) ;
test ( 've.dm.DocumentNode.rebuildNodes' , function ( ) {
var documentModel = new ve . dm . DocumentNode ( veTest . data . slice ( 0 ) ) ;
var originalLength = veTest . data . length ;
var expectedOffsets = veTest . getOffsets ( documentModel ) ;
// Make the first paragraph longer
documentModel . data . splice ( 3 , 0 , 'F' , 'O' , 'O' ) ;
documentModel . rebuildNodes ( documentModel , 0 , 1 , 0 , documentModel . data . slice ( 0 , 8 ) ) ;
ve . batchedSplice ( expectedOffsets , 1 , 4 , repeatArray ( documentModel . children [ 0 ] , 7 ) ) ;
equal ( documentModel . children [ 0 ] . getElementType ( ) , 'paragraph' , 'rebuildNodes() makes a paragraph longer (first child is a paragraph)' ) ;
equal ( documentModel . children [ 0 ] . getContentLength ( ) , 6 , 'rebuildNodes() rmakes a paragraph longer (content length is updated)' ) ;
equal ( documentModel . children . length , 3 , 'rebuildNodes() makes a paragraph longer (document still has 3 children)' ) ;
equal ( documentModel . getContentLength ( ) , originalLength + 3 , 'rebuildNodes() makes a paragraph longer (document content length is updated)' ) ;
compareOffsets ( documentModel , expectedOffsets , 'rebuildNodes() makes a paragraph longer' , 0 , 9 ) ;
// Now make it shorter
documentModel . data . splice ( 2 , 4 ) ;
documentModel . rebuildNodes ( documentModel , 0 , 1 , 0 , documentModel . data . slice ( 0 , 4 ) ) ;
ve . batchedSplice ( expectedOffsets , 1 , 7 , repeatArray ( documentModel . children [ 0 ] , 3 ) ) ;
equal ( documentModel . children [ 0 ] . getElementType ( ) , 'paragraph' , 'rebuildNodes() makes a paragraph shorter (first child is a paragraph)' ) ;
equal ( documentModel . children [ 0 ] . getContentLength ( ) , 2 , 'rebuildNodes() makes a paragraph shorter (content length is updated)' ) ;
equal ( documentModel . children . length , 3 , 'rebuildNodes() makes a paragraph shorter (document still has 3 children)' ) ;
equal ( documentModel . getContentLength ( ) , originalLength - 1 , 'rebuildNodes() makes a paragraph shorter (document content length is updated)' ) ;
compareOffsets ( documentModel , expectedOffsets , 'rebuildNodes() makes a paragraph shorter' , 0 , 5 ) ;
// Split the first paragraph up
documentModel . data . splice ( 2 , 0 , { 'type' : '/paragraph' } , { 'type' : 'paragraph' } ) ;
documentModel . rebuildNodes ( documentModel , 0 , 1 , 0 , documentModel . data . slice ( 0 , 6 ) ) ;
expectedOffsets . splice ( 1 , 3 , documentModel . children [ 0 ] , documentModel . children [ 0 ] , documentModel , documentModel . children [ 1 ] , documentModel . children [ 1 ] ) ;
equal ( documentModel . children [ 0 ] . getElementType ( ) , 'paragraph' , 'rebuildNodes() splits a paragraph (first child is a paragraph)' ) ;
equal ( documentModel . children [ 1 ] . getElementType ( ) , 'paragraph' , 'rebuildNodes() splits a paragraph (second child is a paragraph)' ) ;
equal ( documentModel . children [ 0 ] . getContentLength ( ) , 1 , 'rebuildNodes() splits a paragraph (content length of first paragraph is updated)' ) ;
equal ( documentModel . children [ 1 ] . getContentLength ( ) , 1 , 'rebuildNodes() splits a paragraph (content length of second paragraph is updated)' ) ;
equal ( documentModel . children . length , 4 , 'rebuildNodes() splits a paragraph (document now has 4 children)' ) ;
equal ( documentModel . getContentLength ( ) , originalLength + 1 , 'rebuildNodes() splits a paragraph (document content length is updated)' ) ;
compareOffsets ( documentModel , expectedOffsets , 'rebuildNodes() splits a paragraph' , 0 , 7 ) ;
// Join it back together
documentModel . data . splice ( 2 , 2 ) ;
documentModel . rebuildNodes ( documentModel , 0 , 2 , 0 , documentModel . data . slice ( 0 , 4 ) ) ;
ve . batchedSplice ( expectedOffsets , 1 , 5 , repeatArray ( documentModel . children [ 0 ] , 3 ) ) ;
equal ( documentModel . children [ 0 ] . getElementType ( ) , 'paragraph' , 'rebuildNodes() joins two paragraphs (first child is a paragraph)' ) ;
equal ( documentModel . children [ 0 ] . getContentLength ( ) , 2 , 'rebuildNodes() joins two paragraphs (content length is updated)' ) ;
equal ( documentModel . children . length , 3 , 'rebuildNodes() joins two paragraphsr (document still has 3 children)' ) ;
equal ( documentModel . getContentLength ( ) , originalLength - 1 , 'rebuildNodes() joins two paragraphs (document content length is updated)' ) ;
compareOffsets ( documentModel , expectedOffsets , 'rebuildNodes() joins two paragraphs' , 0 , 5 ) ;
// Add a paragraph to the first listItem by rebuilding the listItem
documentModel . data . splice ( 12 , 0 , { 'type' : 'paragraph' } , 'B' , 'A' , 'R' , { 'type' : '/paragraph' } ) ;
var list = documentModel . children [ 1 ] . children [ 0 ] . children [ 0 ] . children [ 1 ] ;
documentModel . rebuildNodes ( list , 0 , 1 , 11 , documentModel . data . slice ( 11 , 21 ) ) ;
var newListItem = documentModel . children [ 1 ] . children [ 0 ] . children [ 0 ] . children [ 1 ] . children [ 0 ] ;
ve . batchedSplice ( expectedOffsets , 11 , 5 ,
[ list , newListItem ] . concat (
repeatArray ( newListItem . children [ 0 ] , 4 ) ) . concat (
[ newListItem , newListItem . children [ 1 ] , newListItem . children [ 1 ] , newListItem ] )
) ;
equal ( newListItem . getElementType ( ) , 'listItem' , 'rebuildNodes() adds a paragraph to a listItem (listItem is still a listItem)' ) ;
equal ( newListItem . children . length , 2 , 'rebuildNodes() adds a paragraph to a listItem (listItem now has 2 children)' ) ;
equal ( newListItem . children [ 0 ] . getElementType ( ) , 'paragraph' , 'rebuildNodes() adds a paragraph to a listItem (first child is a paragraph)' ) ;
equal ( newListItem . children [ 1 ] . getElementType ( ) , 'paragraph' , 'rebuildNodes() adds a paragraph to a listItem (second child is a paragraph)' ) ;
equal ( newListItem . children [ 0 ] . getContentLength ( ) , 3 , 'rebuildNodes() adds a paragraph to a listItem (first paragraph has correct content length)' ) ;
equal ( newListItem . children [ 1 ] . getContentLength ( ) , 1 , 'rebuildNodes() adds a paragraph to a listItem (second paragraph has correct content length)' ) ;
equal ( newListItem . getContentLength ( ) , 8 , 'rebuildNodes() adds a paragraph to a listItem (content length of listItem is updated)' ) ;
equal ( documentModel . getContentLength ( ) , originalLength + 4 , 'rebuildNodes() adds a paragraph to a listItem (document content length is updated)' ) ;
compareOffsets ( documentModel , expectedOffsets , 'rebuildNodes() adds a paragraph to a listItem' , 10 , 22 ) ;
// Add another paragraph to the first listItem using a zero rebuild
documentModel . data . splice ( 20 , 0 , { 'type' : 'paragraph' } , 'B' , 'A' , 'Z' , { 'type' : '/paragraph' } ) ;
documentModel . rebuildNodes ( newListItem , 2 , 0 , 20 , documentModel . data . slice ( 20 , 25 ) ) ;
ve . batchedSplice ( expectedOffsets , 20 , 0 ,
[ newListItem ] . concat ( repeatArray ( newListItem . children [ 2 ] , 4 ) )
) ;
equal ( newListItem . getElementType ( ) , 'listItem' , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild (listItem is still a listItem) ' ) ;
equal ( newListItem . children . length , 3 , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild (listItem now has 3 children)' ) ;
equal ( newListItem . children [ 0 ] . getElementType ( ) , 'paragraph' , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild (first child is a paragraph)' ) ;
equal ( newListItem . children [ 1 ] . getElementType ( ) , 'paragraph' , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild (second child is a paragraph)' ) ;
equal ( newListItem . children [ 2 ] . getElementType ( ) , 'paragraph' , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild (third child is a paragraph)' ) ;
equal ( newListItem . children [ 0 ] . getContentLength ( ) , 3 , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild (first paragraph has correct content length)' ) ;
equal ( newListItem . children [ 1 ] . getContentLength ( ) , 1 , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild (second paragraph has correct content length)' ) ;
equal ( newListItem . children [ 2 ] . getContentLength ( ) , 3 , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild (third paragraph has correct content length)' ) ;
equal ( newListItem . getContentLength ( ) , 13 , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild (content length of listItem is updated)' ) ;
equal ( documentModel . getContentLength ( ) , originalLength + 9 , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild (document content length is updated)' ) ;
compareOffsets ( documentModel , expectedOffsets , 'rebuildNodes() adds a paragraph to a listItem with zero rebuild' , 10 , 28 ) ;
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.prepareElementAttributeChange' , 4 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
// Test 1
deepEqual (
2012-03-02 23:12:38 +00:00
documentModel . prepareElementAttributeChange ( 0 , 'test' , 1234 ) . getOperations ( ) ,
2011-11-02 21:20:48 +00:00
[
2012-03-02 23:12:38 +00:00
{ 'type' : 'attribute' , 'key' : 'test' , 'from' : undefined , 'to' : 1234 } ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 34 }
2011-11-02 21:20:48 +00:00
] ,
'prepareElementAttributeChange retains data after attribute change for first element'
) ;
// Test 2
deepEqual (
2012-03-02 23:12:38 +00:00
documentModel . prepareElementAttributeChange ( 5 , 'test' , 1234 ) . getOperations ( ) ,
2011-11-02 21:20:48 +00:00
[
{ 'type' : 'retain' , 'length' : 5 } ,
2012-03-02 23:12:38 +00:00
{ 'type' : 'attribute' , 'key' : 'test' , 'from' : undefined , 'to' : 1234 } ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 29 }
2011-11-02 21:20:48 +00:00
] ,
'prepareElementAttributeChange retains data before and after attribute change'
) ;
// Test 3
try {
documentModel . prepareElementAttributeChange ( 1 , 'set' , 'test' , 1234 ) ;
} catch ( invalidOffsetError ) {
ok (
true ,
'prepareElementAttributeChange throws an exception when offset is not an element'
) ;
}
// Test 4
try {
documentModel . prepareElementAttributeChange ( 4 , 'set' , 'test' , 1234 ) ;
} catch ( closingElementError ) {
ok (
true ,
'prepareElementAttributeChange throws an exception when offset is a closing element'
) ;
}
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.prepareContentAnnotation' , 3 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
// Test 1
deepEqual (
documentModel . prepareContentAnnotation (
2012-02-07 00:12:31 +00:00
new ve . Range ( 1 , 4 ) , 'set' , { 'type' : 'textStyle/bold' }
2011-11-02 21:20:48 +00:00
) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 1 } ,
{
'type' : 'annotate' ,
'method' : 'set' ,
'bias' : 'start' ,
2011-11-21 22:32:22 +00:00
'annotation' : { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' }
2011-11-02 21:20:48 +00:00
} ,
{ 'type' : 'retain' , 'length' : 1 } ,
{
'type' : 'annotate' ,
'method' : 'set' ,
'bias' : 'stop' ,
2011-11-21 22:32:22 +00:00
'annotation' : { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' }
2011-11-02 21:20:48 +00:00
} ,
{ 'type' : 'retain' , 'length' : 1 } ,
{
'type' : 'annotate' ,
'method' : 'set' ,
'bias' : 'start' ,
2011-11-21 22:32:22 +00:00
'annotation' : { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' }
2011-11-02 21:20:48 +00:00
} ,
{ 'type' : 'retain' , 'length' : 1 } ,
{
'type' : 'annotate' ,
'method' : 'set' ,
'bias' : 'stop' ,
2011-11-21 22:32:22 +00:00
'annotation' : { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' }
2011-11-02 21:20:48 +00:00
} ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 30 }
2011-11-02 21:20:48 +00:00
] ,
'prepareContentAnnotation skips over content that is already set or cleared'
) ;
2011-11-23 23:24:05 +00:00
// Test 2
deepEqual (
documentModel . prepareContentAnnotation (
2012-02-07 00:12:31 +00:00
new ve . Range ( 3 , 10 ) , 'set' , { 'type' : 'textStyle/bold' }
2011-11-23 23:24:05 +00:00
) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 3 } ,
{
'type' : 'annotate' ,
'method' : 'set' ,
'bias' : 'start' ,
'annotation' : { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' }
} ,
{ 'type' : 'retain' , 'length' : 1 } ,
{
'type' : 'annotate' ,
'method' : 'set' ,
'bias' : 'stop' ,
'annotation' : { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' }
} ,
{ 'type' : 'retain' , 'length' : 5 } ,
{
'type' : 'annotate' ,
'method' : 'set' ,
'bias' : 'start' ,
'annotation' : { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' }
} ,
{ 'type' : 'retain' , 'length' : 1 } ,
{
'type' : 'annotate' ,
'method' : 'set' ,
'bias' : 'stop' ,
'annotation' : { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' }
} ,
{ 'type' : 'retain' , 'length' : 24 }
] ,
'prepareContentAnnotation works across element boundaries'
) ;
2011-11-24 16:27:40 +00:00
// Test 3
deepEqual (
documentModel . prepareContentAnnotation (
2012-02-07 00:12:31 +00:00
new ve . Range ( 4 , 11 ) , 'set' , { 'type' : 'textStyle/bold' }
2011-11-24 16:27:40 +00:00
) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 9 } ,
{
'type' : 'annotate' ,
'method' : 'set' ,
'bias' : 'start' ,
'annotation' : { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' }
} ,
{ 'type' : 'retain' , 'length' : 1 } ,
{
'type' : 'annotate' ,
'method' : 'set' ,
'bias' : 'stop' ,
'annotation' : { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' }
} ,
{ 'type' : 'retain' , 'length' : 24 }
] ,
'prepareContentAnnotation works when given structural offsets'
) ;
2011-11-02 21:20:48 +00:00
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.prepareRemoval' , 11 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
// Test 1
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 1 , 4 ) ) . getOperations ( ) ,
2011-11-02 21:20:48 +00:00
[
{ 'type' : 'retain' , 'length' : 1 } ,
{
'type' : 'remove' ,
'data' : [
'a' ,
2011-11-21 22:32:22 +00:00
[ 'b' , { 'type' : 'textStyle/bold' , 'hash' : '{"type":"textStyle/bold"}' } ] ,
[ 'c' , { 'type' : 'textStyle/italic' , 'hash' : '{"type":"textStyle/italic"}' } ]
2011-11-02 21:20:48 +00:00
]
} ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 30 }
2011-11-02 21:20:48 +00:00
] ,
'prepareRemoval includes the content being removed'
) ;
// Test 2
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 17 , 22 ) ) . getOperations ( ) ,
2011-11-02 21:20:48 +00:00
[
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 17 } ,
2011-11-02 21:20:48 +00:00
{
'type' : 'remove' ,
'data' : [
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' , 'bullet' ] } } ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'paragraph' } ,
2011-11-04 18:31:22 +00:00
'f' ,
2011-11-09 23:39:47 +00:00
{ 'type' : '/paragraph' } ,
2011-11-02 21:20:48 +00:00
{ 'type' : '/listItem' }
]
} ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 12 }
2011-11-02 21:20:48 +00:00
] ,
'prepareRemoval removes entire elements'
) ;
2011-11-04 20:38:47 +00:00
2011-11-17 19:23:15 +00:00
// Test 3
2011-11-04 20:38:47 +00:00
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 3 , 9 ) ) . getOperations ( ) ,
2011-11-04 20:38:47 +00:00
[
{ 'type' : 'retain' , 'length' : 3 } ,
{
'type' : 'remove' ,
'data' : [
2011-11-21 22:32:22 +00:00
[ 'c' , { 'type' : 'textStyle/italic' , 'hash' : '{"type":"textStyle/italic"}' } ]
2011-11-04 20:38:47 +00:00
]
} ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 30 }
2011-11-04 20:38:47 +00:00
] ,
'prepareRemoval works across structural nodes'
) ;
2011-11-15 01:04:37 +00:00
2011-11-17 19:23:15 +00:00
// Test 4
2011-11-15 01:04:37 +00:00
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 3 , 24 ) ) . getOperations ( ) ,
2011-11-15 01:04:37 +00:00
[
{ 'type' : 'retain' , 'length' : 3 } ,
{
'type' : 'remove' ,
2011-11-21 22:32:22 +00:00
'data' : [ [ 'c' , { 'type' : 'textStyle/italic' , 'hash' : '{"type":"textStyle/italic"}' } ] ]
2011-11-15 01:04:37 +00:00
} ,
{ 'type' : 'retain' , 'length' : 4 } ,
{
'type' : 'remove' ,
'data' : [ { 'type' : 'paragraph' } , 'd' , { 'type' : '/paragraph' } ]
} ,
{ 'type' : 'retain' , 'length' : 1 } ,
{
'type' : 'remove' ,
'data' : [
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' ] } } ,
{ 'type' : 'paragraph' } ,
'e' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' , 'bullet' ] } } ,
{ 'type' : 'paragraph' } ,
'f' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' }
]
} ,
2011-11-16 00:03:17 +00:00
{ 'type' : 'retain' , 'length' : 12 }
2011-11-15 01:04:37 +00:00
] ,
2011-11-15 10:15:52 +00:00
'prepareRemoval strips and drops correctly when working across structural nodes'
2011-11-15 01:04:37 +00:00
) ;
2011-11-16 19:07:17 +00:00
2011-11-17 19:23:15 +00:00
// Test 5
2011-11-16 19:07:17 +00:00
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 3 , 25 ) ) . getOperations ( ) ,
2011-11-16 19:07:17 +00:00
[
{ 'type' : 'retain' , 'length' : 3 } ,
{
'type' : 'remove' ,
2011-11-21 22:32:22 +00:00
'data' : [ [ 'c' , { 'type' : 'textStyle/italic' , 'hash' : '{"type":"textStyle/italic"}' } ] ]
2011-11-16 19:07:17 +00:00
} ,
{ 'type' : 'retain' , 'length' : 4 } ,
{
'type' : 'remove' ,
'data' : [ { 'type' : 'paragraph' } , 'd' , { 'type' : '/paragraph' } ]
} ,
{ 'type' : 'retain' , 'length' : 1 } ,
{
'type' : 'remove' ,
'data' : [
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' ] } } ,
{ 'type' : 'paragraph' } ,
'e' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' , 'bullet' ] } } ,
{ 'type' : 'paragraph' } ,
'f' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' }
]
} ,
{ 'type' : 'retain' , 'length' : 2 } ,
{
'type' : 'remove' ,
'data' : [ 'g' ]
} ,
{ 'type' : 'retain' , 'length' : 9 }
] ,
'prepareRemoval strips and drops correctly when working across structural nodes (2)'
) ;
2011-11-17 19:23:15 +00:00
// Test 6
2011-11-16 19:07:17 +00:00
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 9 , 17 ) ) . getOperations ( ) ,
2011-11-16 19:07:17 +00:00
[
{ 'type' : 'retain' , 'length' : 9 } ,
{
'type' : 'remove' ,
'data' : [ 'd' ]
} ,
{ 'type' : 'retain' , 'length' : 2 } ,
{
'type' : 'remove' ,
'data' : [
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' ] } } ,
{ 'type' : 'paragraph' } ,
'e' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' }
]
} ,
{ 'type' : 'retain' , 'length' : 17 }
] ,
'prepareRemoval will not merge items of unequal types'
) ;
2011-11-17 19:23:15 +00:00
// Test 7
2011-11-16 19:07:17 +00:00
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 9 , 27 ) ) . getOperations ( ) ,
2011-11-16 19:07:17 +00:00
[
{ 'type' : 'retain' , 'length' : 9 } ,
{
'type' : 'remove' ,
'data' : [ 'd' ]
} ,
{ 'type' : 'retain' , 'length' : 2 } ,
{
'type' : 'remove' ,
'data' : [
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' ] } } ,
{ 'type' : 'paragraph' } ,
'e' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' , 'bullet' ] } } ,
{ 'type' : 'paragraph' } ,
'f' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'number' ] } } ,
{ 'type' : 'paragraph' } ,
'g' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' }
]
} ,
{ 'type' : 'retain' , 'length' : 7 }
] ,
'prepareRemoval blanks a paragraph and a list'
) ;
2011-11-17 19:23:15 +00:00
// Test 8
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 21 , 23 ) ) . getOperations ( ) ,
2011-11-17 19:23:15 +00:00
[
{ 'type' : 'retain' , 'length' : 21 } ,
{
'type' : 'remove' ,
'data' : [
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'number' ] } }
]
} ,
{ 'type' : 'retain' , 'length' : 11 }
] ,
'prepareRemoval merges two list items'
) ;
// Test 9
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 20 , 24 ) ) . getOperations ( ) ,
2011-11-17 19:23:15 +00:00
[
{ 'type' : 'retain' , 'length' : 20 } ,
{
'type' : 'remove' ,
'data' : [
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'number' ] } } ,
{ 'type' : 'paragraph' }
]
} ,
{ 'type' : 'retain' , 'length' : 10 }
] ,
'prepareRemoval merges two list items and the paragraphs inside them'
) ;
// Test 10
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 20 , 23 ) ) . getOperations ( ) ,
2011-11-17 19:23:15 +00:00
[
{ 'type' : 'retain' , 'length' : 34 }
] ,
'prepareRemoval returns a null transaction when attempting an unbalanced merge'
) ;
// Test 11
deepEqual (
2012-02-07 00:12:31 +00:00
documentModel . prepareRemoval ( new ve . Range ( 15 , 24 ) ) . getOperations ( ) ,
2011-11-17 19:23:15 +00:00
[
{ 'type' : 'retain' , 'length' : 15 } ,
{
'type' : 'remove' ,
'data' : [
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' , 'bullet' ] } } ,
{ 'type' : 'paragraph' } ,
'f' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'number' ] } } ,
{ 'type' : 'paragraph' }
]
} ,
{ 'type' : 'retain' , 'length' : 10 }
] ,
'prepareRemoval merges two list items and the paragraphs inside them'
) ;
2011-11-02 21:20:48 +00:00
} ) ;
2012-02-07 00:12:31 +00:00
test ( 've.dm.DocumentNode.prepareInsertion' , 11 , function ( ) {
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
2011-11-02 21:20:48 +00:00
// Test 1
deepEqual (
documentModel . prepareInsertion ( 1 , [ 'd' , 'e' , 'f' ] ) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 1 } ,
{ 'type' : 'insert' , 'data' : [ 'd' , 'e' , 'f' ] } ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 33 }
2011-11-02 21:20:48 +00:00
] ,
'prepareInsertion retains data up to the offset and includes the content being inserted'
) ;
// Test 2
deepEqual (
documentModel . prepareInsertion (
5 , [ { 'type' : 'paragraph' } , 'd' , 'e' , 'f' , { 'type' : '/paragraph' } ]
) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 5 } ,
{
'type' : 'insert' ,
'data' : [ { 'type' : 'paragraph' } , 'd' , 'e' , 'f' , { 'type' : '/paragraph' } ]
} ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 29 }
2011-11-02 21:20:48 +00:00
] ,
'prepareInsertion inserts a paragraph between two structural elements'
) ;
// Test 3
deepEqual (
documentModel . prepareInsertion ( 5 , [ 'd' , 'e' , 'f' ] ) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 5 } ,
{
'type' : 'insert' ,
'data' : [ { 'type' : 'paragraph' } , 'd' , 'e' , 'f' , { 'type' : '/paragraph' } ]
} ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 29 }
2011-11-02 21:20:48 +00:00
] ,
'prepareInsertion wraps unstructured content inserted between elements in a paragraph'
) ;
// Test 4
deepEqual (
documentModel . prepareInsertion (
5 , [ { 'type' : 'paragraph' } , 'd' , 'e' , 'f' ]
) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 5 } ,
{
'type' : 'insert' ,
'data' : [ { 'type' : 'paragraph' } , 'd' , 'e' , 'f' , { 'type' : '/paragraph' } ]
} ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 29 }
2011-11-02 21:20:48 +00:00
] ,
'prepareInsertion completes opening elements in inserted content'
) ;
// Test 5
deepEqual (
documentModel . prepareInsertion (
2 , [ { 'type' : 'table' } , { 'type' : '/table' } ]
) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 2 } ,
{
'type' : 'insert' ,
2011-11-03 18:15:24 +00:00
'data' : [
{ 'type' : '/paragraph' } ,
{ 'type' : 'table' } ,
{ 'type' : '/table' } ,
{ 'type' : 'paragraph' }
]
2011-11-02 21:20:48 +00:00
} ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 32 }
2011-11-02 21:20:48 +00:00
] ,
'prepareInsertion splits up paragraph when inserting a table in the middle'
) ;
// Test 6
deepEqual (
documentModel . prepareInsertion (
2 , [ 'f' , 'o' , 'o' , { 'type' : '/paragraph' } , { 'type' : 'paragraph' } , 'b' , 'a' , 'r' ]
) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 2 } ,
{
'type' : 'insert' ,
2011-11-03 18:15:24 +00:00
'data' : [
'f' ,
'o' ,
'o' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'paragraph' } ,
'b' ,
'a' ,
'r'
]
2011-11-02 21:20:48 +00:00
} ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 32 }
2011-11-02 21:20:48 +00:00
] ,
2011-11-04 17:54:02 +00:00
'prepareInsertion splits paragraph when inserting a paragraph closing and opening inside it'
2011-11-02 21:20:48 +00:00
) ;
// Test 7
deepEqual (
documentModel . prepareInsertion (
0 , [ { 'type' : 'paragraph' } , 'f' , 'o' , 'o' , { 'type' : '/paragraph' } ]
) . getOperations ( ) ,
[
{
'type' : 'insert' ,
'data' : [ { 'type' : 'paragraph' } , 'f' , 'o' , 'o' , { 'type' : '/paragraph' } ]
} ,
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 34 }
2011-11-02 21:20:48 +00:00
] ,
'prepareInsertion inserts at the beginning, then retains up to the end'
) ;
// Test 8
deepEqual (
documentModel . prepareInsertion (
2011-11-09 23:39:47 +00:00
34 , [ { 'type' : 'paragraph' } , 'f' , 'o' , 'o' , { 'type' : '/paragraph' } ]
2011-11-02 21:20:48 +00:00
) . getOperations ( ) ,
[
2011-11-09 23:39:47 +00:00
{ 'type' : 'retain' , 'length' : 34 } ,
2011-11-02 21:20:48 +00:00
{
'type' : 'insert' ,
'data' : [ { 'type' : 'paragraph' } , 'f' , 'o' , 'o' , { 'type' : '/paragraph' } ]
}
] ,
'prepareInsertion inserts at the end'
) ;
// Test 9
raises (
function ( ) {
documentModel . prepareInsertion (
- 1 ,
[ { 'type' : 'paragraph' } , 'f' , 'o' , 'o' , { 'type' : '/paragraph' } ]
) ;
} ,
/^Offset -1 out of bounds/ ,
'prepareInsertion throws exception for negative offset'
) ;
// Test 10
raises (
function ( ) {
documentModel . prepareInsertion (
2011-11-09 23:39:47 +00:00
35 ,
2011-11-02 21:20:48 +00:00
[ { 'type' : 'paragraph' } , 'f' , 'o' , 'o' , { 'type' : '/paragraph' } ]
) ;
} ,
2011-11-09 23:39:47 +00:00
/^Offset 35 out of bounds/ ,
2011-11-02 21:20:48 +00:00
'prepareInsertion throws exception for offset past the end'
) ;
// Test 11
raises (
function ( ) {
documentModel . prepareInsertion (
5 ,
[ { 'type' : 'paragraph' } , 'a' , { 'type' : 'listItem' } , { 'type' : '/paragraph' } ]
) ;
} ,
/^Input is malformed: expected \/listItem but got \/paragraph at index 3$/ ,
'prepareInsertion throws exception for malformed input'
) ;
} ) ;
2012-03-08 23:21:26 +00:00
2012-03-09 02:19:50 +00:00
test ( 've.dm.DocumentNode.prepareWrap' , 6 , function ( ) {
2012-03-08 23:21:26 +00:00
var documentModel = ve . dm . DocumentNode . newFromPlainObject ( veTest . obj ) ;
// Test 1
deepEqual (
documentModel . prepareWrap ( new ve . Range ( 1 , 4 ) , [ { 'type' : 'paragraph' } ] , [ { 'type' : 'heading' , 'level' : 2 } ] , [ ] , [ ] ) . getOperations ( ) ,
[
{ 'type' : 'replace' , 'remove' : [ { 'type' : 'paragraph' } ] , 'replacement' : [ { 'type' : 'heading' , 'level' : 2 } ] } ,
{ 'type' : 'retain' , 'length' : 3 } ,
{ 'type' : 'replace' , 'remove' : [ { 'type' : '/paragraph' } ] , 'replacement' : [ { 'type' : '/heading' } ] } ,
{ 'type' : 'retain' , 'length' : 29 }
] ,
'prepareWrap changes a paragraph to a heading'
) ;
2012-03-09 00:38:35 +00:00
// Test 2
deepEqual (
documentModel . prepareWrap ( new ve . Range ( 12 , 27 ) , [ { 'type' : 'list' } ] , [ ] , [ { 'type' : 'listItem' } ] , [ ] ) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 11 } ,
{ 'type' : 'replace' , 'remove' : [ { 'type' : 'list' } ] , 'replacement' : [ ] } ,
2012-03-09 01:14:41 +00:00
{ 'type' : 'replace' , 'remove' : [ { 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' ] } } ] , 'replacement' : [ ] } ,
2012-03-09 00:38:35 +00:00
{ 'type' : 'retain' , 'length' : 3 } ,
{ 'type' : 'replace' , 'remove' : [ { 'type' : '/listItem' } ] , 'replacement' : [ ] } ,
2012-03-09 01:14:41 +00:00
{ 'type' : 'replace' , 'remove' : [ { 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'bullet' , 'bullet' ] } } ] , 'replacement' : [ ] } ,
2012-03-09 00:38:35 +00:00
{ 'type' : 'retain' , 'length' : 3 } ,
{ 'type' : 'replace' , 'remove' : [ { 'type' : '/listItem' } ] , 'replacement' : [ ] } ,
2012-03-09 01:14:41 +00:00
{ 'type' : 'replace' , 'remove' : [ { 'type' : 'listItem' , 'attributes' : { 'styles' : [ 'number' ] } } ] , 'replacement' : [ ] } ,
2012-03-09 00:38:35 +00:00
{ 'type' : 'retain' , 'length' : 3 } ,
{ 'type' : 'replace' , 'remove' : [ { 'type' : '/listItem' } ] , 'replacement' : [ ] } ,
{ 'type' : 'replace' , 'remove' : [ { 'type' : '/list' } ] , 'replacement' : [ ] } ,
{ 'type' : 'retain' , 'length' : 6 }
] ,
'prepareWrap unwraps a list'
) ;
2012-03-09 01:44:31 +00:00
// Test 3
2012-03-09 02:19:50 +00:00
deepEqual (
documentModel . prepareWrap ( new ve . Range ( 8 , 28 ) , [ { 'type' : 'table' } , { 'type' : 'tableRow' } , { 'type' : 'tableCell' } ] , [ { 'type' : 'list' } , { 'type' : 'listItem' } ] , [ ] , [ ] ) . getOperations ( ) ,
[
{ 'type' : 'retain' , 'length' : 5 } ,
{ 'type' : 'replace' , 'remove' : [ { 'type' : 'table' } , { 'type' : 'tableRow' } , { 'type' : 'tableCell' } ] , 'replacement' : [ { 'type' : 'list' } , { 'type' : 'listItem' } ] } ,
{ 'type' : 'retain' , 'length' : 20 } ,
{ 'type' : 'replace' , 'remove' : [ { 'type' : '/tableCell' } , { 'type' : '/tableRow' } , { 'type' : '/table' } ] , 'replacement' : [ { 'type' : '/listItem' } , { 'type' : '/list' } ] } ,
{ 'type' : 'retain' , 'length' : 3 }
] ,
'prepareWrap replaces a table with a list'
) ;
// Test 4
2012-03-09 01:44:31 +00:00
raises (
function ( ) {
documentModel . prepareWrap ( new ve . Range ( 12 , 27 ) , [ { 'type' : 'table' } ] , [ ] , [ ] , [ ] ) ;
} ,
/^Element in unwrapOuter does not match: expected table but found list$/ ,
'prepareWrap checks integrity of unwrapOuter parameter'
) ;
2012-03-09 02:19:50 +00:00
// Test 5
2012-03-09 01:44:31 +00:00
raises (
function ( ) {
documentModel . prepareWrap ( new ve . Range ( 12 , 27 ) , [ { 'type' : 'list' } ] , [ ] , [ { 'type' : 'paragraph' } ] , [ ] ) ;
} ,
/^Element in unwrapEach does not match: expected paragraph but found listItem$/ ,
'prepareWrap checks integrity of unwrapEach parameter'
) ;
2012-03-09 02:19:50 +00:00
// Test 6
2012-03-09 01:44:31 +00:00
raises (
function ( ) {
documentModel . prepareWrap ( new ve . Range ( 1 , 4 ) , [ { 'type' : 'listItem' } , { 'type' : 'paragraph' } ] , [ ] , [ ] , [ ] ) ;
} ,
/^unwrapOuter is longer than the data preceding the range$/ ,
'prepareWrap checks that unwrapOuter fits before the range'
) ;
2012-03-08 23:21:26 +00:00
} ) ;