test(`ctrl-k clears selected text`, (assert) => {
  let initialText = 'something';
  const mobiledoc = Helpers.mobiledoc.build(
    ({post, markupSection, marker}) => post([
      markupSection('p', [marker(initialText)])
    ]));

  editor = new Editor({mobiledoc});
  editor.render(editorElement);

  let textElement = editor.post.sections.head.markers.head.renderNode.element;
  Helpers.dom.moveCursorTo(editor, textElement, 4, textElement, 8);
  Helpers.dom.triggerKeyCommand(editor, 'K', MODIFIERS.CTRL);

  let changedMobiledoc = editor.serialize();
  let expectedMobiledoc = Helpers.mobiledoc.build(
    ({post, markupSection, marker}) => {
      return post([
        markupSection('p', [
          marker('someg')
        ])
      ]);
  });
  assert.deepEqual(changedMobiledoc, expectedMobiledoc,
                   'mobiledoc updated appropriately');
});
  test('right arrow at start of card moves the cursor across the card', assert => {
    let mobiledoc = Helpers.mobiledoc.build(({post, cardSection}) => {
      return post([
        cardSection('my-card')
      ]);
    });
    editor = new Editor({mobiledoc, cards});
    editor.render(editorElement);

    let cardHead = editor.post.sections.head.headPosition();
    let cardTail = editor.post.sections.head.tailPosition();

    // Before zwnj
    Helpers.dom.moveCursorTo(editor, editorElement.firstChild.firstChild, 0);
    Helpers.dom.triggerRightArrowKey(editor, MODIFIERS.SHIFT);
    let { range } = editor;

    assert.positionIsEqual(range.head, cardHead);
    assert.positionIsEqual(range.tail, cardTail);

    // After zwnj
    Helpers.dom.moveCursorTo(editor, editorElement.firstChild.firstChild, 1);
    Helpers.dom.triggerRightArrowKey(editor, MODIFIERS.SHIFT);
    range = editor.range;

    assert.positionIsEqual(range.head, cardHead);
    assert.positionIsEqual(range.tail, cardTail);
  });
test('left arrow when at the start of a card moves the cursor to the previous section', assert => {
  let mobiledoc = Helpers.mobiledoc.build(({post, markupSection, cardSection}) => {
    return post([
      markupSection('p'),
      cardSection('my-card')
    ]);
  });
  editor = new Editor({mobiledoc, cards});
  editor.render(editorElement);
  let sectionTail = editor.post.sections.head.tailPosition();

  // Before zwnj
  let sectionElement = editor.post.sections.tail.renderNode.element;
  Helpers.dom.moveCursorTo(editor, sectionElement.firstChild, 0);
  Helpers.dom.triggerLeftArrowKey(editor);
  let { range } = editor;

  assert.positionIsEqual(range.head, sectionTail);
  assert.positionIsEqual(range.tail, sectionTail);

  // After zwnj
  Helpers.dom.moveCursorTo(editor, sectionElement.firstChild, 1);
  Helpers.dom.triggerLeftArrowKey(editor);
  range = editor.range;

  assert.positionIsEqual(range.head, sectionTail);
  assert.positionIsEqual(range.tail, sectionTail);
});
test('pasting when replacing a list item works', (assert) => {
  let mobiledoc = Helpers.mobiledoc.build(
    ({post, listSection, listItem, markupSection, marker}) => {
    return post([
      markupSection('p', [marker('X')]),
      listSection('ul', [
        listItem([marker('Y')])
      ])
    ]);
  });

  editor = new Editor({mobiledoc, cards});
  editor.render(editorElement);

  assert.hasElement('#editor li:contains(Y)', 'precond: has li with Y');

  Helpers.dom.selectText(editor, 'X', editorElement);
  Helpers.dom.triggerCopyEvent(editor);

  Helpers.dom.selectText(editor, 'Y', editorElement);
  Helpers.dom.triggerPasteEvent(editor);

  assert.hasElement('#editor li:contains(X)', 'replaces Y with X in li');
  assert.hasNoElement('#editor li:contains(Y)', 'li with Y is gone');
});
test('left arrow when at the end of a card moves the cursor across the card', assert => {
  let mobiledoc = Helpers.mobiledoc.build(({post, cardSection}) => {
    return post([
      cardSection('my-card')
    ]);
  });
  editor = new Editor({mobiledoc, cards});
  editor.render(editorElement);
  let cardHead = editor.post.sections.head.headPosition();

  // Before zwnj
  Helpers.dom.moveCursorTo(editor, editorElement.firstChild.lastChild, 0);
  Helpers.dom.triggerLeftArrowKey(editor);
  let { range } = editor;

  assert.positionIsEqual(range.head, cardHead);
  assert.positionIsEqual(range.tail, cardHead);

  // After zwnj
  Helpers.dom.moveCursorTo(editor, editorElement.firstChild.lastChild, 1);
  Helpers.dom.triggerLeftArrowKey(editor);
  range = editor.range;

  assert.positionIsEqual(range.head, cardHead);
  assert.positionIsEqual(range.tail, cardHead);

  // On wrapper
  Helpers.dom.moveCursorTo(editor, editorElement.firstChild, 2);
  Helpers.dom.triggerLeftArrowKey(editor);
  range = editor.range;

  assert.positionIsEqual(range.head, cardHead);
  assert.positionIsEqual(range.tail, cardHead);
});
test('typing tab enters a tab character', (assert) => {
  let done = assert.async();
  assert.expect(3);

  let mobiledoc = Helpers.mobiledoc.build(({post}) => post());
  editor = new Editor({mobiledoc});
  editor.render(editorElement);

  assert.hasElement('#editor');
  assert.hasNoElement('#editor p');

  Helpers.dom.moveCursorTo(editor, $('#editor')[0]);
  Helpers.dom.insertText(editor, TAB);
  Helpers.dom.insertText(editor, 'Y');
  window.setTimeout(() => {
    let expectedPost = Helpers.postAbstract.build(({post, markupSection, marker}) => {
      return post([
        markupSection('p', [
          marker(`${TAB}Y`)
        ])
      ]);
    });
    assert.postIsSimilar(editor.post, expectedPost);
    done();
  });
});
test('copy-paste can copy list sections', (assert) => {
  const mobiledoc = Helpers.mobiledoc.build(
    ({post, markupSection, marker, listSection, listItem}) => {
    return post([
      markupSection('p', [marker('abc')]),
      listSection('ul', [
        listItem([marker('list')])
      ]),
      markupSection('p', [marker('123')])
    ]);
  });
  editor = new Editor({mobiledoc});
  editor.render(editorElement);

  Helpers.dom.selectText(editor, 'c', editor.element, '1', editor.element);

  Helpers.dom.triggerCopyEvent(editor);

  let textNode = $('#editor p')[1].childNodes[0];
  assert.equal(textNode.textContent, '123', 'precond - correct textNode');

  Helpers.dom.moveCursorTo(editor, textNode, 3); // end of node
  Helpers.dom.triggerPasteEvent(editor);

  assert.equal($('#editor ul').length, 2, 'pastes the list');
  assert.hasElement($('#editor ul:eq(0) li:contains(list)'));
});
test('when editing is disabled, the selection detection code is disabled', (assert) => {
  let done = assert.async();
  $('#qunit-fixture').append('<p>outside section 1</p>');
  $('#qunit-fixture').append('<p>outside section 2</p>');

  editor = new Editor({mobiledoc: mobileDocWithSection});
  editor.render(editorElement);
  editor.disableEditing();

  const outside1 = $('p:contains(outside section 1)')[0];
  const outside2 = $('p:contains(outside section 2)')[0];

  Helpers.wait(() => {
    Helpers.dom.selectText(editor ,'outside', outside1, 'section 2', outside2);

    Helpers.wait(() => {
      assert.equal(editor.activeSections.length, 0, 'no selection inside the editor');
      const selectedText = Helpers.dom.getSelectedText();
      assert.ok(selectedText.indexOf('outside section 1') !== -1 &&
                selectedText.indexOf('outside section 2') !== -1, 'selects the text');

      done();
    });
  });
});
test('selecting text across markers and deleting joins markers', (assert) => {

  editor = new Editor({mobiledoc: mobileDocWith2Sections});
  editor.render(editorElement);

  Helpers.dom.selectText('rst sect', editorElement);
  editor.run(postEditor => postEditor.toggleMarkup('strong'));

  let firstTextNode = editorElement
                         .childNodes[0] // p
                         .childNodes[1] // b
                         .childNodes[0]; // textNode containing "rst sect"
  let secondTextNode = editorElement
                           .childNodes[0] // p
                           .childNodes[2]; // textNode containing "ion"

  assert.equal(firstTextNode.textContent, 'rst sect', 'correct first text node');
  assert.equal(secondTextNode.textContent, 'ion', 'correct second text node');
  Helpers.dom.selectText('t sect', firstTextNode,
                         'ion',    secondTextNode);
  Helpers.dom.triggerDelete(editor);

  assert.hasElement('p:contains(firs)', 'deletes across markers');
  assert.hasElement('strong:contains(rs)', 'maintains bold text');

  firstTextNode = editorElement
                    .childNodes[0] // p
                    .childNodes[1] // b
                    .childNodes[0]; // textNode now containing "rs"

  assert.deepEqual(Helpers.dom.getCursorPosition(),
                   {node: firstTextNode, offset: 2});
});
test('returning false from key command still runs built-in functionality', (assert) => {
  const mobiledoc = Helpers.mobiledoc.build(
    ({post, markupSection, marker}) => post([
      markupSection('p', [marker('something')])
    ]));

  editor = new Editor({mobiledoc});

  let passedEditor;
  editor.registerKeyCommand({
    str: 'enter',
    run(editor) {
      passedEditor = editor;
      return false;
    }
  });

  editor.render(editorElement);
  assert.equal($('#editor p').length, 1, 'has 1 paragraph to start');

  Helpers.dom.moveCursorTo(editor, editorElement.childNodes[0].childNodes[0], 5);
  Helpers.dom.triggerEnter(editor);

  assert.ok(!!passedEditor && passedEditor === editor, 'run method is called');

  assert.equal($('#editor p').length, 2, 'has added a new paragraph');
});
test('selecting all text across sections and hitting enter deletes and moves cursor to empty section', (assert) => {
  editor = new Editor({mobiledoc: mobileDocWith2Sections});
  editor.render(editorElement);

  let firstSection = $('#editor p:eq(0)')[0],
      secondSection = $('#editor p:eq(1)')[0];

  Helpers.dom.selectText(editor ,'first section', firstSection,
                         'second section', secondSection);

  Helpers.dom.triggerEnter(editor);

  assert.equal($('#editor p').length, 1, 'single section');
  assert.equal($('#editor p:eq(0)').text(), '', 'blank text');

  // Firefox reports that the cursor is on the "<br>", but Safari and Chrome do not.
  // Grab the selection here, then set it to the expected value, and compare again
  // the window's selection
  let selection = window.getSelection();
  let cursorElement = $('#editor p br')[0];
  assert.ok(cursorElement, 'has cursor element');
  Helpers.dom.selectRange(cursorElement, 0, cursorElement, 0);
  let newSelection = window.getSelection();
  assert.equal(selection.anchorNode, newSelection.anchorNode, 'correct anchorNode');
  assert.equal(selection.focusNode, newSelection.focusNode, 'correct focusNode');
  assert.equal(selection.anchorOffset, newSelection.anchorOffset, 'correct anchorOffset');
  assert.equal(selection.focusOffset, newSelection.focusOffset, 'correct focusOffset');
});
test('returning false from key command causes next match to run', (assert) => {
  const mobiledoc = Helpers.mobiledoc.build(
    ({post, markupSection, marker}) => post([
      markupSection('p', [marker('something')])
    ]));

  let firstCommandRan, secondCommandRan;
  editor = new Editor({mobiledoc});
  editor.registerKeyCommand({
    str: 'ctrl+x',
    run() { firstCommandRan = true; }
  });
  editor.registerKeyCommand({
    str: 'ctrl+x',
    run() {
      secondCommandRan = true;
      return false;
    }
  });
  editor.render(editorElement);

  Helpers.dom.triggerKeyCommand(editor, 'X', MODIFIERS.CTRL);

  assert.ok(!!secondCommandRan, 'last registered method is called');
  assert.ok(!!firstCommandRan, 'first registered method is called');
});
test('new key commands can be registered without modifiers', (assert) => {
  const mobiledoc = Helpers.mobiledoc.build(
    ({post, markupSection, marker}) => post([
      markupSection('p', [marker('something')])
    ]));

  let passedEditor;
  editor = new Editor({mobiledoc});
  editor.registerKeyCommand({
    str: 'X',
    run(editor) { passedEditor = editor; }
  });
  editor.render(editorElement);

  Helpers.dom.triggerKeyCommand(editor, 'Y', MODIFIERS.CTRL);

  assert.ok(!passedEditor, 'incorrect key combo does not trigger key command');

  Helpers.dom.triggerKeyCommand(editor, 'X', MODIFIERS.CTRL);

  assert.ok(!passedEditor, 'key with modifier combo does not trigger key command');

  Helpers.dom.triggerKeyCommand(editor, 'X');

  assert.ok(!!passedEditor && passedEditor === editor, 'run method is called');
});
  test(`${command} applies markup ${markupName} to highlighted text`, (assert) => {
    assert.expect(2);
    let done = assert.async();

    let modifier = MODIFIERS[modifierName];
    let modifierKeyCode = Keycodes[modifierName];
    let initialText = 'something';
    const mobiledoc = Helpers.mobiledoc.build(
      ({post, markupSection, marker}) => post([
        markupSection('p', [marker(initialText)])
      ]));

    editor = new Editor({mobiledoc});
    editor.render(editorElement);

    assert.hasNoElement(`#editor ${markupName}`, `precond - no ${markupName} text`);
    Helpers.dom.selectText(editor ,initialText, editorElement);
    Helpers.dom.triggerKeyCommand(editor, key, modifier);
    Helpers.dom.triggerKeyEvent(editor, 'keyup', {charCode: 0, keyCode: modifierKeyCode});

    setTimeout(() => {
      assert.hasElement(`#editor ${markupName}:contains(${initialText})`,
                        `text wrapped in ${markupName}`);
      done();
    });
  });
test('deleting when after deletion there is a trailing space positions cursor at end of selection', (assert) => {
  const done = assert.async();

  editor = new Editor({mobiledoc: mobileDocWith2Sections});
  editor.render(editorElement);

  let firstSectionTextNode = editor.element.childNodes[0].firstChild;
  Helpers.dom.moveCursorTo(editor, firstSectionTextNode, 'first section'.length);

  let count = 'ection'.length;
  while (count--) {
    Helpers.dom.triggerDelete(editor);
  }

  assert.equal($('#editor p:eq(0)').text(), 'first s', 'precond - correct section text after initial deletions');

  Helpers.dom.triggerDelete(editor);

  assert.equal($('#editor p:eq(0)').text(), `first${NO_BREAK_SPACE}`, 'precond - correct text after deleting last char before space');

  let text = 'e';
  Helpers.dom.insertText(editor, text);

  Helpers.wait(() => {
    assert.equal(editor.post.sections.head.text, `first ${text}`, 'character is placed after space');

    done();
  });
});
test('selecting text across markers deletes intermediary markers', (assert) => {
  let mobiledoc = Helpers.mobiledoc.build(
    ({post, markupSection, marker, markup}) => {
    return post([
      markupSection('p', [
        marker('abc'),
        marker('123', [markup('strong')]),
        marker('def')
      ])
    ]);
  });
  editor = new Editor({mobiledoc});
  editor.render(editorElement);


  const textNode1 = editorElement.childNodes[0].childNodes[0],
        textNode2 = editorElement.childNodes[0].childNodes[2];

  assert.equal(textNode1.textContent, 'abc', 'precond - text node 1');
  assert.equal(textNode2.textContent, 'def', 'precond - text node 2');
  Helpers.dom.selectText('b', textNode1,
                         'e', textNode2);

  Helpers.dom.triggerDelete(editor);

  assert.hasElement('p:contains(af)', 'has remaining first section');

  Helpers.dom.insertText(editor, 'X');
  assert.hasElement('p:contains(aXf)', 'inserts text at correct place');
});
test('left arrow when at the start of a card moves to previous list item', assert => {
  let mobiledoc = Helpers.mobiledoc.build(
    ({post, listSection, listItem, marker, cardSection}) => {
    return post([
      listSection('ul', [listItem([marker('abc')])]),
      cardSection('my-card')
    ]);
  });
  editor = new Editor({mobiledoc, cards});
  editor.render(editorElement);
  let itemTail = editor.post.sections.head.items.head.tailPosition();

  // Before zwnj
  let sectionElement = editor.post.sections.tail.renderNode.element;
  Helpers.dom.moveCursorTo(sectionElement.firstChild, 0);
  Helpers.dom.triggerLeftArrowKey(editor);
  let { range } = editor;

  assert.positionIsEqual(range.head, itemTail);
  assert.positionIsEqual(range.tail, itemTail);

  // After zwnj
  sectionElement = editor.post.sections.tail.renderNode.element;
  Helpers.dom.moveCursorTo(sectionElement.firstChild, 1);
  Helpers.dom.triggerLeftArrowKey(editor);
  range = editor.range;

  assert.positionIsEqual(range.head, itemTail);
  assert.positionIsEqual(range.tail, itemTail);
});
test('deleting text across markers preserves node after', (assert) => {
  let mobiledoc = Helpers.mobiledoc.build(
    ({post, markupSection, marker, markup}) => {
    return post([
      markupSection('p', [
        marker('abc'),
        marker('123', [markup('strong')]),
        marker('def')
      ])
    ]);
  });
  editor = new Editor({mobiledoc});
  editor.render(editorElement);


  const textNode1 = editorElement.childNodes[0].childNodes[0],
        textNode2 = editorElement.childNodes[0].childNodes[1];
  assert.equal(textNode1.textContent, 'abc', 'precond -text node 1');
  assert.equal(textNode2.textContent, '123', 'precond -text node 2');

  Helpers.dom.selectText('b', editorElement,
                         '2', editorElement);

  Helpers.dom.triggerDelete(editor);

  assert.equal(
    editorElement.childNodes[0].textContent, 'a3def',
    'has remaining first section'
  );
  Helpers.dom.insertText(editor, 'X');
  assert.equal(
    editorElement.childNodes[0].textContent, 'aX3def',
    'inserts text at correct spot');
});
test('typing enter splits lines, sets cursor', (assert) => {
  let done = assert.async();
  let mobiledoc = Helpers.mobiledoc.build(({post, markupSection, marker}) => {
    return post([
      markupSection('p', [ marker('hihey') ])
    ]);
  });
  editor = new Editor({mobiledoc});
  editor.render(editorElement);

  assert.hasElement('#editor p');

  Helpers.dom.moveCursorTo(editor, $('#editor p')[0].firstChild, 2);
  Helpers.dom.insertText(editor, ENTER);
  window.setTimeout(() => {
    let expectedPost = Helpers.postAbstract.build(({post, markupSection, marker}) => {
      return post([
        markupSection('p', [
          marker(`hi`)
        ]),
        markupSection('p', [
          marker(`hey`)
        ])
      ]);
    });
    assert.postIsSimilar(editor.post, expectedPost, 'correctly encoded');
    let expectedRange = new Range(new Position(editor.post.sections.tail, 0));
    assert.ok(expectedRange.isEqual(editor.range), 'range is at start of new section');
    done();
  }, 0);
});
test('keystroke of printable character while text is selected deletes the text', (assert) => {
  editor = new Editor({mobiledoc: mobileDocWith2Sections});
  editor.render(editorElement);

  Helpers.dom.selectText('first section', editorElement);

  editor.run(postEditor => {
    editor.activeSections.forEach(section => {
      postEditor.changeSectionTagName(section, 'h2');
    });
  });

  assert.ok($('#editor h2:contains(first section)').length,
            'first section is a heading');

  const firstSectionTextNode = editorElement.childNodes[0].childNodes[0];
  const secondSectionTextNode = editorElement.childNodes[1].childNodes[0];
  Helpers.dom.selectText('section', firstSectionTextNode,
                        'secon', secondSectionTextNode);

  Helpers.dom.insertText(editor, 'X');

  assert.ok($(`#editor h2:contains(first Xd section)`).length,
            'updates the section');
});
test('copy sets html & text for pasting externally', (assert) => {
  const mobiledoc = Helpers.mobiledoc.build(
    ({post, markupSection, marker}) => {
      return post([
        markupSection('h1', [marker('h1 heading')]),
        markupSection('h2', [marker('h2 subheader')]),
        markupSection('p', [marker('The text')])
      ]);
  });
  editor = new Editor({mobiledoc});
  editor.render(editorElement);

  Helpers.dom.selectText(editor, 'heading', editor.element,
                         'The text', editor.element);

  Helpers.dom.triggerCopyEvent(editor);

  let html = Helpers.dom.getCopyData(MIME_TEXT_HTML);
  let text = Helpers.dom.getCopyData(MIME_TEXT_PLAIN);
  assert.equal(text, ["heading", "h2 subheader", "The text" ].join('\n'),
               'gets plain text');

  assert.ok(html.indexOf("<h1>heading") !== -1, 'html has h1');
  assert.ok(html.indexOf("<h2>h2 subheader") !== -1, 'html has h2');
  assert.ok(html.indexOf("<p>The text") !== -1, 'html has p');
});
test('selecting text across markup and list sections', (assert) => {
  const build = Helpers.mobiledoc.build;
  const mobiledoc = build(({post, markupSection, listSection, listItem, marker}) =>
    post([
      markupSection('p', [marker('abc')]),
      listSection('ul', [
        listItem([marker('123')]),
        listItem([marker('456')])
      ])
    ])
  );
  editor = new Editor({mobiledoc});
  editor.render(editorElement);

  Helpers.dom.selectText('bc', editorElement, '12', editorElement);

  Helpers.dom.triggerDelete(editor);

  assert.hasElement('#editor p:contains(a3)',
                    'combines partially-selected list item onto markup section');

  assert.hasNoElement('#editor p:contains(bc)', 'deletes selected text "bc"');
  assert.hasNoElement('#editor p:contains(12)', 'deletes selected text "12"');

  assert.hasElement('#editor li:contains(6)', 'leaves remaining text in list item');
});
Exemplo n.º 23
0
test('right arrow at end of card moves cursor to next section', assert => {
  let mobiledoc = Helpers.mobiledoc.build(({post, markupSection, cardSection}) => {
    return post([
      cardSection('my-card'),
      markupSection('p')
    ]);
  });
  editor = new Editor({mobiledoc, cards});
  editor.render(editorElement);
  let sectionHead = editor.post.sections.tail.headPosition();

  // Before zwnj
  let sectionElement = editor.post.sections.head.renderNode.element;
  Helpers.dom.moveCursorTo(editor, sectionElement.lastChild, 0);
  Helpers.dom.triggerRightArrowKey(editor);
  let { range } = editor;

  assert.positionIsEqual(range.head, sectionHead);
  assert.positionIsEqual(range.tail, sectionHead);

  // After zwnj
  Helpers.dom.moveCursorTo(editor, sectionElement.lastChild, 1);
  Helpers.dom.triggerRightArrowKey(editor);
  range = editor.range;

  // On wrapper
  Helpers.dom.moveCursorTo(editor, editorElement.firstChild, 2);
  Helpers.dom.triggerRightArrowKey(editor);
  range = editor.range;

  assert.positionIsEqual(range.head, sectionHead);
  assert.positionIsEqual(range.tail, sectionHead);
});
test('selecting text that starts in a list item and ends in a markup section', (assert) => {
  const build = Helpers.mobiledoc.build;
  const mobiledoc = build(({post, markupSection, listSection, listItem, marker}) =>
    post([
      listSection('ul', [
        listItem([marker('123')]),
        listItem([marker('456')])
      ]),
      markupSection('p', [marker('def')])
    ])
  );
  editor = new Editor({mobiledoc});
  editor.render(editorElement);

  Helpers.dom.selectText('23', editorElement, 'de', editorElement);
  Helpers.dom.triggerEvent(document, 'mouseup');
  Helpers.dom.triggerDelete(editor);

  assert.hasElement('#editor li:contains(1f)',
                    'combines sides of selection');

  assert.hasNoElement('#editor li:contains(123)', 'deletes li 1');
  assert.hasNoElement('#editor li:contains(456)', 'deletes li 2');
  assert.hasNoElement('#editor p:contains(def)', 'deletes p content');
  assert.hasNoElement('#editor p', 'removes p entirely');
});
Exemplo n.º 25
0
  test('left arrow at start of card moves selection to prev section', assert => {
    let mobiledoc = Helpers.mobiledoc.build(
      ({post, markupSection, marker, cardSection}) => {
      return post([
        markupSection('p', [marker('abc')]),
        cardSection('my-card')
      ]);
    });
    editor = new Editor({mobiledoc, cards});
    editor.render(editorElement);

    let cardHead = editor.post.sections.tail.headPosition();
    let sectionTail = editor.post.sections.head.tailPosition();

    // Before zwnj
    Helpers.dom.moveCursorTo(editor, editorElement.lastChild.firstChild, 0);
    Helpers.dom.triggerLeftArrowKey(editor, MODIFIERS.SHIFT);
    let { range } = editor;

    assert.positionIsEqual(range.head, sectionTail);
    assert.positionIsEqual(range.tail, cardHead);

    // After zwnj
    Helpers.dom.moveCursorTo(editor, editorElement.lastChild.firstChild, 1);
    Helpers.dom.triggerLeftArrowKey(editor, MODIFIERS.SHIFT);
    range = editor.range;

    assert.positionIsEqual(range.head, sectionTail);
    assert.positionIsEqual(range.tail, cardHead);
  });
test('selecting text that includes a card section and deleting deletes card section', (assert) => {
  const build = Helpers.mobiledoc.build;
  const mobiledoc = build(({post, markupSection, cardSection, marker}) =>
    post([
      markupSection('p', [marker('abc')]),
      cardSection('simple-card'),
      markupSection('p', [marker('def')])
    ])
  );
  const cards = [{
    name: 'simple-card',
    type: 'dom',
    render() {
      return $('<span id="card-el"></span>')[0];
    }
  }];
  editor = new Editor({mobiledoc, cards});
  editor.render(editorElement);

  assert.hasElement('#card-el', 'precond - card el is rendered');

  Helpers.dom.selectText('bc', editorElement, 'de', editorElement);
  Helpers.dom.triggerEvent(document, 'mouseup');

  Helpers.dom.triggerDelete(editor);

  assert.hasElement('#editor p:contains(af)', 'combines sides of selection');

  assert.hasNoElement('#editor span#card-el', 'card el is removed');
  assert.hasNoElement('#editor p:contains(abc)', 'previous section 1 is removed');
  assert.hasNoElement('#editor p:contains(def)', 'previous section 2 is removed');
});
Exemplo n.º 27
0
  test('right arrow at end of card moves to next list item', (assert) => {
    let mobiledoc = Helpers.mobiledoc.build(
      ({post, listSection, listItem, marker, cardSection}) => {
      return post([
        cardSection('my-card'),
        listSection('ul', [listItem([marker('abc')])])
      ]);
    });
    editor = new Editor({mobiledoc, cards});
    editor.render(editorElement);

    let cardTail = editor.post.sections.head.tailPosition();
    let itemHead = editor.post.sections.tail.items.head.headPosition();

    // Before zwnj
    Helpers.dom.moveCursorTo(editor, editorElement.firstChild.lastChild, 0);
    Helpers.dom.triggerRightArrowKey(editor, MODIFIERS.SHIFT);
    let { range } = editor;

    assert.positionIsEqual(range.head, cardTail);
    assert.positionIsEqual(range.tail, itemHead);

    // After zwnj
    Helpers.dom.moveCursorTo(editor, editorElement.firstChild.lastChild, 1);
    Helpers.dom.triggerRightArrowKey(editor, MODIFIERS.SHIFT);
    range = editor.range;

    assert.positionIsEqual(range.head, cardTail);
    assert.positionIsEqual(range.tail, itemHead);
  });
test('keystroke of delete at start of section joins with previous section', (assert) => {
  editor = new Editor({mobiledoc: mobileDocWith2Sections});
  editor.render(editorElement);

  let secondSectionTextNode = editor.element.childNodes[1].firstChild;

  assert.equal(secondSectionTextNode.textContent, 'second section',
               'precond - section section text node');

  Helpers.dom.moveCursorTo(editor, secondSectionTextNode, 0);
  //editor.range = null;
  Helpers.dom.triggerDelete(editor);

  assert.equal(editor.element.childNodes.length, 1, 'only 1 section remaining');

  let secondSectionNode = editor.element.firstChild;
  secondSectionTextNode = secondSectionNode.firstChild;
  assert.equal(secondSectionNode.textContent,
               'first sectionsecond section',
               'joins two sections');

  Helpers.dom.insertText(editor, 'X');

  assert.hasElement('#editor p:contains(first sectionXsecond section)',
                    'inserts text at correct spot');
});
Exemplo n.º 29
0
test('marking atom with markup adds markup', (assert) => {
  assert.expect(1);
  let done = assert.async();

  editor = new Editor({mobiledoc: mobiledocWithAtom, atoms: [simpleAtom]});
  editor.render(editorElement);

  let pNode = $('#editor p')[0];
  Helpers.dom.selectRange(pNode.firstChild, 16, pNode.lastChild, 0);

  Helpers.wait(() => {
    editor.run(postEditor => {
      let markup = editor.builder.createMarkup('strong');
      postEditor.addMarkupToRange(editor.range, markup);
    });

    assert.postIsSimilar(editor.post, Helpers.postAbstract.build(
      ({post, markupSection, atom, marker, markup}) => {
        return post([
          markupSection('p', [
            marker('text before atom'),
            atom('simple-atom', 'Bob', {}, [markup('strong')]),
            marker('text after atom')
          ])
        ]);
      }));

    done();
  });
});
test('removing last card from mobiledoc allows additional editing', (assert) => {
  const done = assert.async();
  let button;
  const cards = [{
    name: 'simple-card',
    type: 'dom',
    render({env}) {
      button = $('<button>Click me</button>');
      button.on('click', env.remove);
      return button[0];
    }
  }];
  editor = new Editor({mobiledoc, cards});
  editor.render(editorElement);

  assert.hasElement('#editor button:contains(Click me)', 'precond - button');

  button.click();

  setTimeout(() => {
    assert.hasNoElement('#editor button:contains(Click me)', 'button is removed');
    assert.hasNoElement('#editor p');
    Helpers.dom.moveCursorTo($('#editor')[0]);
    Helpers.dom.insertText(editor, 'X');
    assert.hasElement('#editor p:contains(X)');

    done();
  });
});