import { context, describe, it } from '@ephox/bedrock-client'; import { LegacyUnit, TinyAssertions, TinySelections, TinyHooks } from '@ephox/wrap-mcagar'; import { assert } from 'chai'; import Editor from 'tinymce/core/api/Editor'; import Plugin from 'tinymce/plugins/lists/Plugin'; describe('browser.tinymce.plugins.lists.ApplyTest', () => { const hook = TinyHooks.bddSetupLight({ plugins: 'lists', add_unload_trigger: false, disable_nodechange: true, indent: false, entities: 'raw', extended_valid_elements: 'li[style|class|data-custom|data-custom1|data-custom2],ol[style|class|data-custom|data-custom1|data-custom2],' + 'ul[style|class|data-custom|data-custom1|data-custom2],dl,dt,dd,em,strong,span,#p,div,br', valid_styles: { '*': 'color,font-size,font-family,background-color,font-weight,' + 'font-style,text-decoration,float,margin,margin-top,margin-right,' + 'margin-bottom,margin-left,display,position,top,left,list-style-type' }, base_url: '/project/tinymce/js/tinymce' }, [ Plugin ]); it('TBA: Apply UL list to single P', () => { const editor = hook.editor(); editor.setContent('

a

'); LegacyUnit.setSelection(editor, 'p', 0); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertContent(editor, ''); assert.equal(editor.selection.getNode().nodeName, 'LI'); }); it('TBA: Apply UL list to single empty P', () => { const editor = hook.editor(); editor.setContent(LegacyUnit.trimBrs('


'), { format: 'raw' }); LegacyUnit.setSelection(editor, 'p', 0); editor.execCommand('InsertUnorderedList'); assert.equal(LegacyUnit.trimBrs(editor.getContent({ format: 'raw' })), ''); assert.equal(editor.selection.getNode().nodeName, 'LI'); }); it('TBA: Apply UL list to multiple Ps', () => { const editor = hook.editor(); editor.setContent( '

a

' + '

b

' + '

c

' ); LegacyUnit.setSelection(editor, 'p', 0, 'p:last-of-type', 0); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertContent(editor, '' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('TBA: Apply OL list to single P', () => { const editor = hook.editor(); editor.setContent('

a

'); LegacyUnit.setSelection(editor, 'p', 0); editor.execCommand('InsertOrderedList'); TinyAssertions.assertContent(editor, '
  1. a
'); LegacyUnit.equal(editor.selection.getNode().nodeName, 'LI'); }); it('TBA: Apply OL list to single empty P', () => { const editor = hook.editor(); editor.setContent(LegacyUnit.trimBrs('


'), { format: 'raw' }); LegacyUnit.setSelection(editor, 'p', 0); editor.execCommand('InsertOrderedList'); TinyAssertions.assertContent(editor, '
'); assert.equal(editor.selection.getNode().nodeName, 'LI'); }); it('TBA: Apply OL list to multiple Ps', () => { const editor = hook.editor(); editor.setContent( '

a

' + '

b

' + '

c

' ); LegacyUnit.setSelection(editor, 'p', 0, 'p:last-of-type', 0); editor.execCommand('InsertOrderedList'); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
  3. b
  4. ' + '
  5. c
  6. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('TBA: Apply OL to UL list', () => { const editor = hook.editor(); editor.setContent( '' ); LegacyUnit.setSelection(editor, 'li', 0, 'li:last-of-type', 0); editor.execCommand('InsertOrderedList'); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
  3. b
  4. ' + '
  5. c
  6. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('Apply OL to UL list with collapsed selection', () => { const editor = hook.editor(); editor.setContent( '' ); LegacyUnit.setSelection(editor, 'li:nth-child(2)', 0); editor.execCommand('InsertOrderedList'); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
  3. b
  4. ' + '
  5. c
  6. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('TBA: Apply UL to OL list', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
  3. b
  4. ' + '
  5. c
  6. ' + '
' ); LegacyUnit.setSelection(editor, 'li', 0, 'li:last-of-type', 0); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertContent( editor, '' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('TBA: Apply UL to OL list collapsed selection', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
  3. b
  4. ' + '
  5. c
  6. ' + '
' ); LegacyUnit.setSelection(editor, 'li:nth-child(2)', 0); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertContent( editor, '' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('TBA: Apply UL to P and merge with adjacent lists', () => { const editor = hook.editor(); editor.setContent( '' + '

b

' + '' ); LegacyUnit.setSelection(editor, 'p', 1); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertContent( editor, '' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('TBA: Apply UL to OL and merge with adjacent lists', () => { const editor = hook.editor(); editor.setContent( '' + '
  1. b
' + '' ); LegacyUnit.setSelection(editor, 'ol li', 1); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertContent( editor, '' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('TBA: Apply OL to P and merge with adjacent lists', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
' + '

b

' + '
    ' + '
  1. c
  2. ' + '
' ); LegacyUnit.setSelection(editor, 'p', 1); editor.execCommand('InsertOrderedList'); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
  3. b
  4. ' + '
  5. c
  6. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('TBA: Apply OL to UL and merge with adjacent lists', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. 1a
  2. ' + '
  3. 1b
  4. ' + '
' + '' + '
    ' + '
  1. 3a
  2. ' + '
  3. 3b
  4. ' + '
' ); LegacyUnit.setSelection(editor, 'ul li', 1); editor.execCommand('InsertOrderedList'); TinyAssertions.assertContent( editor, '
    ' + '
  1. 1a
  2. ' + '
  3. 1b
  4. ' + '
  5. 2a
  6. ' + '
  7. 2b
  8. ' + '
  9. 3a
  10. ' + '
  11. 3b
  12. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('Apply OL to UL and DO not merge with adjacent lists because styles are different (exec has style)', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
' + '' + '
    ' + '
  1. c
  2. ' + '
' ); LegacyUnit.setSelection(editor, 'ul li', 1); editor.execCommand('InsertOrderedList', false, { 'list-style-type': 'lower-alpha' }); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
' + '
  1. b
' + '
    ' + '
  1. c
  2. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('Apply OL to P and DO not merge with adjacent lists because styles are different (exec has style)', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
' + '

b

' + '
    ' + '
  1. c
  2. ' + '
' ); LegacyUnit.setSelection(editor, 'p', 1); editor.execCommand('InsertOrderedList', false, { 'list-style-type': 'lower-alpha' }); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
' + '
  1. b
' + '
    ' + '
  1. c
  2. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('Apply OL to UL and DO not merge with adjacent lists because styles are different (original has style)', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
' + '' + '
    ' + '
  1. c
  2. ' + '
' ); LegacyUnit.setSelection(editor, 'ul li', 1); editor.execCommand('InsertOrderedList'); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
' + '
  1. b
' + '
    ' + '
  1. c
  2. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('Apply OL to UL should merge with adjacent lists because styles are the same (both have roman)', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
' + '' + '
    ' + '
  1. c
  2. ' + '
' ); LegacyUnit.setSelection(editor, 'ul li', 1); editor.execCommand('InsertOrderedList', false, { 'list-style-type': 'upper-roman' }); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
  3. b
  4. ' + '
  5. c
  6. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('Apply OL to UL should merge with above list because styles are the same (both have lower-roman), but not below list', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
' + '' + '
    ' + '
  1. c
  2. ' + '
' ); LegacyUnit.setSelection(editor, 'ul li', 1); editor.execCommand('InsertOrderedList', false, { 'list-style-type': 'lower-roman' }); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
  3. b
  4. ' + '
' + '
    ' + '
  1. c
  2. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('Apply OL to UL should merge with below lists because styles are the same (both have roman), but not above list', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
' + '' + '
    ' + '
  1. c
  2. ' + '
' ); LegacyUnit.setSelection(editor, 'ul li', 1); editor.execCommand('InsertOrderedList', false, { 'list-style-type': 'lower-roman' }); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
' + '
    ' + '
  1. b
  2. ' + '
  3. c
  4. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('Apply OL to UL and DO not merge with adjacent lists because classes are different', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
' + '' + '
    ' + '
  1. c
  2. ' + '
' ); LegacyUnit.setSelection(editor, 'ul li', 1); editor.execCommand('InsertOrderedList'); TinyAssertions.assertContent( editor, '
    ' + '
  1. a
  2. ' + '
' + '
  1. b
' + '
    ' + '
  1. c
  2. ' + '
' ); assert.equal(editor.selection.getStart().nodeName, 'LI'); }); it('TBA: Apply UL list to all P lines (SelectAll)', () => { const editor = hook.editor(); editor.setContent( '

a

' + '

b

' + '

c

' ); editor.execCommand('SelectAll'); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertContent( editor, '' ); }); it('TBA: Apply UL list to more than two paragraphs', () => { const editor = hook.editor(); editor.setContent( '

a

' + '

b

' + '

c

' ); LegacyUnit.setSelection(editor, 'p:nth-child(1)', 0, 'p:nth-child(3)', 1); editor.execCommand('InsertUnorderedList', false, { 'list-style-type': null }); TinyAssertions.assertContent(editor, ''); }); it('TBA: Apply UL with custom attributes', () => { const editor = hook.editor(); editor.setContent('

a

'); LegacyUnit.setSelection(editor, 'p', 0); editor.execCommand('InsertUnorderedList', false, { 'list-attributes': { 'class': 'a', 'data-custom': 'c1' } }); TinyAssertions.assertContent(editor, ''); }); it('TBA: Apply UL and LI with custom attributes', () => { const editor = hook.editor(); editor.setContent('

a

'); LegacyUnit.setSelection(editor, 'p', 0); editor.execCommand('InsertUnorderedList', false, { 'list-attributes': { 'class': 'a', 'data-custom': 'c1' }, 'list-item-attributes': { 'class': 'b', 'data-custom1': 'c2', 'data-custom2': '' } }); TinyAssertions.assertContent( editor, '' ); }); it('TBA: Handle one empty unordered list items without error', () => { const editor = hook.editor(); editor.setContent( '' ); editor.execCommand('SelectAll'); LegacyUnit.setSelection(editor, 'li:first-of-type', 0, 'li:last-of-type', 0); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertRawContent( editor, '

a

' + '

b

' + '


' ); }); it('TBA: Handle several empty unordered list items without error', () => { const editor = hook.editor(); editor.setContent( '' ); LegacyUnit.setSelection(editor, 'li:first-of-type', 0, 'li:last-of-type', 0); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertRawContent( editor, '

a

' + '

b

' + '


' + '

c

' + '


' + '

d

' + '


' + '

e

' ); }); it('TBA: Handle one empty ordered list items without error', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
  3. b
  4. ' + '
  5. ' + '
' ); editor.execCommand('SelectAll'); LegacyUnit.setSelection(editor, 'li:first-of-type', 0, 'li:last-of-type', 0); editor.execCommand('InsertOrderedList'); TinyAssertions.assertRawContent( editor, '

a

' + '

b

' + '


' ); }); it('TBA: Handle several empty ordered list items without error', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
  3. b
  4. ' + '
  5. ' + '
  6. c
  7. ' + '
  8. ' + '
  9. d
  10. ' + '
  11. ' + '
  12. e
  13. ' + '
' ); LegacyUnit.setSelection(editor, 'li:first-of-type', 0, 'li:last-of-type', 0); editor.execCommand('InsertOrderedList'); TinyAssertions.assertRawContent( editor, '

a

' + '

b

' + '


' + '

c

' + '


' + '

d

' + '


' + '

e

' ); }); it('TBA: Apply list on paragraphs with list between', () => { const editor = hook.editor(); editor.setContent( '

a

' + '
    ' + '
  1. b
  2. ' + '
' + '

c

' ); editor.execCommand('SelectAll'); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertRawContent(editor, ''); }); it('TBA: Apply unordered list on children on a fully selected ordered list', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a' + '
      ' + '
    1. b
    2. ' + '
    ' + '
  2. ' + '
  3. c
  4. ' + '
' ); editor.execCommand('SelectAll'); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertRawContent(editor, ''); }); it('TBA: Apply unordered list on empty table cell', () => { const editor = hook.editor(); editor.setContent( '' + '' + '' + '' + '' + '' + '
' + '
' + '
', { format: 'raw' } ); const rng = editor.dom.createRng(); rng.setStart(editor.dom.select('td')[0], 0); rng.setEnd(editor.dom.select('td')[0], 1); editor.selection.setRng(rng); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertRawContent(editor, '

'); }); it('TBA: Apply unordered list on table cell with two lines br', () => { const editor = hook.editor(); editor.setContent( '' + '' + '' + '' + '' + '' + '
' + 'a
b' + '
', { format: 'raw' } ); const rng = editor.dom.createRng(); rng.setStart(editor.dom.select('td')[0].firstChild as Text, 0); rng.setEnd(editor.dom.select('td')[0].firstChild as Text, 0); editor.selection.setRng(rng); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertRawContent( editor, '
  • a
b
' ); }); it('TBA: Apply UL list to single P with forced_root_block_attrs', () => { const editor = hook.editor(); editor.options.set('forced_root_block', 'p'); editor.options.set('forced_root_block_attrs', { 'data-editor': '1' }); editor.setContent( '

a

', { format: 'raw' } ); LegacyUnit.setSelection(editor, 'p', 0); editor.execCommand('InsertUnorderedList'); TinyAssertions.assertRawContent(editor, ''); assert.equal(editor.selection.getNode().nodeName, 'LI'); editor.options.unset('forced_root_block'); editor.options.unset('forced_root_block_attrs'); }); it('TINY-3755: Lists: Apply list on mix of existing lists and other text blocks', () => { const editor = hook.editor(); editor.setContent( '
    ' + '
  1. a
  2. ' + '
  3. b' + '
      ' + '
    1. c
    2. ' + '
    3. d
    4. ' + '
    5. e
    6. ' + '
    ' + '
  4. ' + '
  5. f
  6. ' + '
  7. g
  8. ' + '
' + '

text1
text2
text3

' + '

text4
text5
text6

' + '' ); editor.execCommand('SelectAll'); editor.execCommand('InsertUnorderedList'); const expected = ( '' + '' ); TinyAssertions.assertRawContent(editor, expected); }); it('TINY-3755: Lists: Apply lists with selection start and end on text blocks', () => { const editor = hook.editor(); editor.setContent( '

 

' + '' + '
    ' + '
  1. four
  2. ' + '
  3. five
  4. ' + '
  5. six
  6. ' + '
' + '

After

', { format: 'raw' } ); editor.execCommand('SelectAll'); editor.execCommand('InsertUnorderedList'); const expected = ( '' + '' + '' ); TinyAssertions.assertRawContent(editor, expected); }); context('Parent context', () => { const testApplyOLAtTextPath = (inputHtml: string, path: number[], expectedHtml: string) => () => { const editor = hook.editor(); editor.setContent(inputHtml); TinySelections.setCursor(editor, path, 0); editor.execCommand('InsertOrderedList'); TinyAssertions.assertContent(editor, expectedHtml); }; it('TINY-8068: apply OL to UL inside DIV should not alter the DIV', testApplyOLAtTextPath( '
', [ 0, 0, 0, 0 ], '
  1. a
' )); it('TINY-8068: apply OL to UL on LI with a paragraph should not alter the paragraph', testApplyOLAtTextPath( '', [ 0, 0, 0, 0 ], '
  1. a

' )); it('TINY-8068: apply OL in a table should not alter elements outside the table', testApplyOLAtTextPath( '
a
', [ 0, 0, 0, 0, 0, 0 ], '
  1. a
' )); it('TINY-8068: apply OL to UL in table should not alter elements outside the table', testApplyOLAtTextPath( '
  • a
', [ 0, 0, 0, 0, 0, 0, 0, 0 ], '
  1. a
' )); }); });