/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xwiki.gwt.wysiwyg.client.plugin.line; import org.xwiki.gwt.dom.client.DOMUtils; import org.xwiki.gwt.dom.client.Event; import org.xwiki.gwt.dom.client.Range; import org.xwiki.gwt.wysiwyg.client.RichTextAreaTestCase; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.LoadEvent; import com.google.gwt.user.client.Command; /** * Unit tests for {@link LinePlugin}. * * @version $Id: 570014f008b13662045ed3d0e9c5419308ce169b $ */ public class LinePluginTest extends RichTextAreaTestCase { /** * The name of the paragraph HTML element. */ private static final String PARAGRAPH = "p"; /** * The name of the anchor HTML element. */ private static final String ANCHOR = "a"; /** * The name of the line break HTML element. */ private static final String BR = "br"; /** * The plug-in being tested. */ private LinePlugin plugin; @Override public void onLoad(LoadEvent event) { super.onLoad(event); plugin = GWT.create(LinePlugin.class); plugin.init(rta, null); } @Override protected void gwtTearDown() throws Exception { plugin.destroy(); super.gwtTearDown(); } /** * @see XWIKI-3283: Hitting enter twice between 2 titles doesn't create new line in IE6 */ public void testEnterBetweenHeadingsWithInnerSpan() { deferTest(new Command() { public void execute() { doTestEnterBetweenHeadingsWithInnerSpan(); } }); } /** * @see XWIKI-3283: Hitting enter twice between 2 titles doesn't create new line in IE6 */ private void doTestEnterBetweenHeadingsWithInnerSpan() { rta.setHTML("<h2><span>title 2</span></h2><h3><span>title 3</span></h3>"); // Place the caret at the end of the first heading. Range range = rta.getDocument().createRange(); range.selectNodeContents(getBody().getFirstChild().getFirstChild().getFirstChild()); range.collapse(false); select(range); // Type Enter. rta .onBrowserEvent((Event) rta.getDocument() .createKeyDownEvent(false, false, false, false, KeyCodes.KEY_ENTER)); // Check if the caret is inside a span which is inside paragraph. range = rta.getDocument().getSelection().getRangeAt(0); assertNotNull(DOMUtils.getInstance().getFirstAncestor(range.getStartContainer(), "span")); assertNotNull(DOMUtils.getInstance().getFirstAncestor(range.getStartContainer(), PARAGRAPH)); } /** * Tests if the caret is placed inside a new paragraph after pressing Enter between two headings that contain only * text. */ public void testEnterBetweenHeadingsWithoutInnerSpan() { deferTest(new Command() { public void execute() { rta.setHTML("<h2>title 2</h2><h3>title 3/h3>"); // Place the caret at the end of the first heading. Range range = rta.getDocument().createRange(); range.selectNodeContents(getBody().getFirstChild().getFirstChild()); range.collapse(false); select(range); // Type Enter. rta.onBrowserEvent((Event) rta.getDocument().createKeyDownEvent(false, false, false, false, KeyCodes.KEY_ENTER)); // Check if the caret is inside a paragraph. range = rta.getDocument().getSelection().getRangeAt(0); assertNotNull(DOMUtils.getInstance().getFirstAncestor(range.getStartContainer(), PARAGRAPH)); } }); } /** * Tests if the caret is placed inside a new paragraph after pressing Enter inside a text node that is a direct * child of body. */ public void testEnterInBodyWithPlainText() { deferTest(new Command() { public void execute() { doTestEnterInBodyWithPlainText(); } }); } /** * Tests if the caret is placed inside a new paragraph after pressing Enter inside a text node that is a direct * child of body. */ private void doTestEnterInBodyWithPlainText() { rta.setHTML("amazing!"); // Place the caret at the end of the first heading. Range range = rta.getDocument().createRange(); range.setStart(getBody().getFirstChild(), 1); range.setEnd(getBody().getFirstChild(), 3); select(range); // Type Enter. rta .onBrowserEvent((Event) rta.getDocument() .createKeyDownEvent(false, false, false, false, KeyCodes.KEY_ENTER)); // Check if the caret is inside a paragraph. range = rta.getDocument().getSelection().getRangeAt(0); assertNotNull(DOMUtils.getInstance().getFirstAncestor(range.getStartContainer(), PARAGRAPH)); // Check the result. assertEquals("a<p>zing!</p>", clean(rta.getHTML())); } /** * Tests if the caret is placed inside a new paragraph after pressing Enter inside a text node that is a descendant * of body with only in-line parents. */ public void testEnterInBodyWithStyledText() { deferTest(new Command() { public void execute() { doTestEnterInBodyWithStyledText(); } }); } /** * Tests if the caret is placed inside a new paragraph after pressing Enter inside a text node that is a descendant * of body with only in-line parents. */ private void doTestEnterInBodyWithStyledText() { rta.setHTML("<strong>xwiki</strong>enterprise"); // Place the caret at the end of the first heading. Range range = rta.getDocument().createRange(); range.selectNode(getBody().getFirstChild().getFirstChild()); range.collapse(false); select(range); // Type Enter. rta .onBrowserEvent((Event) rta.getDocument() .createKeyDownEvent(false, false, false, false, KeyCodes.KEY_ENTER)); // Check if the caret is inside a strong element which is inside a paragraph. range = rta.getDocument().getSelection().getRangeAt(0); assertNotNull(DOMUtils.getInstance().getFirstAncestor(range.getStartContainer(), "strong")); assertNotNull(DOMUtils.getInstance().getFirstAncestor(range.getStartContainer(), PARAGRAPH)); } /** * Tests that pressing Enter before a link doesn't leave an empty link on the previous line. * * @see XWIKI-4193: When hitting Return at the end of the link the new line should not be a link */ public void testEnterBeforeLink() { deferTest(new Command() { public void execute() { doTestEnterBeforeLink(); } }); } /** * @see #testEnterBeforeLink() */ private void doTestEnterBeforeLink() { rta.setHTML("<p>1<a href=\"http://www.xwiki.org\"><!--*-->2</a></p>"); // Place the caret before the link. Range range = rta.getDocument().createRange(); range.selectNode(getBody().getFirstChild().getLastChild().getLastChild()); range.collapse(true); select(range); // Type Enter. rta .onBrowserEvent((Event) rta.getDocument() .createKeyDownEvent(false, false, false, false, KeyCodes.KEY_ENTER)); // We should have two paragraphs and one link. assertEquals(2, getBody().getElementsByTagName(PARAGRAPH).getLength()); assertEquals(1, getBody().getElementsByTagName(ANCHOR).getLength()); // The link should be in the second paragraph. assertEquals(1, getBody().getElementsByTagName(PARAGRAPH).getItem(1).getElementsByTagName(ANCHOR).getLength()); } /** * Tests that pressing Enter after a link doesn't create an empty link on the new line. * * @see XWIKI-4193: When hitting Return at the end of the link the new line should not be a link */ public void testEnterAfterLink() { deferTest(new Command() { public void execute() { doTestEnterAfterLink(); } }); } /** * @see #testEnterAfterLink() */ private void doTestEnterAfterLink() { rta.setHTML("<p><a href=\"http://www.xwiki.org\"><em>XWiki<!--*--></em></a></p>"); // Place the caret after the link. Range range = rta.getDocument().createRange(); range.selectNode(getBody().getFirstChild().getFirstChild().getFirstChild().getFirstChild()); range.collapse(false); select(range); // Type Enter. rta .onBrowserEvent((Event) rta.getDocument() .createKeyDownEvent(false, false, false, false, KeyCodes.KEY_ENTER)); // We should have two paragraphs and one link. assertEquals(2, getBody().getElementsByTagName(PARAGRAPH).getLength()); assertEquals(1, getBody().getElementsByTagName(ANCHOR).getLength()); // The link should be in the first paragraph. assertEquals(1, getBody().getElementsByTagName(PARAGRAPH).getItem(0).getElementsByTagName(ANCHOR).getLength()); } /** * Tests if pressing Enter in the middle of a link splits that link in two. * * @see XWIKI-4193: When hitting Return at the end of the link the new line should not be a link */ public void testEnterInLink() { deferTest(new Command() { public void execute() { doTestEnterInLink(); } }); } /** * @see #testEnterInLink() */ private void doTestEnterInLink() { rta.setHTML("<p><a href=\"http://www.xwiki.org\">XWiki</a></p>"); // Place the caret inside the link. Range range = rta.getDocument().createRange(); range.setStart(getBody().getFirstChild().getFirstChild().getFirstChild(), 3); range.collapse(true); select(range); // Type Enter. rta .onBrowserEvent((Event) rta.getDocument() .createKeyDownEvent(false, false, false, false, KeyCodes.KEY_ENTER)); // We should have two paragraphs and two links. assertEquals(2, getBody().getElementsByTagName(PARAGRAPH).getLength()); assertEquals(2, getBody().getElementsByTagName(ANCHOR).getLength()); // Each paragraph should contain one link. assertEquals(1, getBody().getElementsByTagName(PARAGRAPH).getItem(0).getElementsByTagName(ANCHOR).getLength()); assertEquals(1, getBody().getElementsByTagName(PARAGRAPH).getItem(1).getElementsByTagName(ANCHOR).getLength()); } /** * Tests that pressing Shift+Enter before a link inserts a line break and doesn't break the link. * * @see XWIKI-4193: When hitting Return at the end of the link the new line should not be a link */ public void testShiftEnterBeforeLink() { deferTest(new Command() { public void execute() { doTestShiftEnterBeforeLink(); } }); } /** * @see #testShiftEnterBeforeLink() */ private void doTestShiftEnterBeforeLink() { rta.setHTML("<p>2<a href=\"http://www.xwiki.org\"><strong>1</strong></a></p>"); // Place the caret before the link. Range range = rta.getDocument().createRange(); range.selectNode(getBody().getFirstChild().getLastChild().getFirstChild().getFirstChild()); range.collapse(true); select(range); // Type Shift+Enter. rta.onBrowserEvent((Event) rta.getDocument().createKeyDownEvent(false, false, true, false, KeyCodes.KEY_ENTER)); // We should have one paragraph, one link and one line break. assertEquals(1, getBody().getElementsByTagName(PARAGRAPH).getLength()); assertEquals(1, getBody().getElementsByTagName(ANCHOR).getLength()); assertEquals(1, getBody().getElementsByTagName(BR).getLength()); // Type Enter. rta .onBrowserEvent((Event) rta.getDocument() .createKeyDownEvent(false, false, false, false, KeyCodes.KEY_ENTER)); // We should have two paragraphs and one link. assertEquals(2, getBody().getElementsByTagName(PARAGRAPH).getLength()); assertEquals(1, getBody().getElementsByTagName(ANCHOR).getLength()); // The link should be in the second paragraph. assertEquals(1, getBody().getElementsByTagName(PARAGRAPH).getItem(1).getElementsByTagName(ANCHOR).getLength()); } /** * Tests that pressing Enter after a link inserts a line break and doesn't break the link. * * @see XWIKI-4193: When hitting Return at the end of the link the new line should not be a link */ public void testShiftEnterAfterLink() { deferTest(new Command() { public void execute() { doTestShiftEnterAfterLink(); } }); } /** * @see #testShiftEnterAfterLink() */ private void doTestShiftEnterAfterLink() { rta.setHTML("<p><a href=\"http://www.xwiki.org\">XWiki<!--*--></a></p>"); // Place the caret after the link. Range range = rta.getDocument().createRange(); range.selectNode(getBody().getFirstChild().getFirstChild().getFirstChild()); range.collapse(false); select(range); // Type Shift+Enter. rta.onBrowserEvent((Event) rta.getDocument().createKeyDownEvent(false, false, true, false, KeyCodes.KEY_ENTER)); // We should have one paragraph and one link. assertEquals(1, getBody().getElementsByTagName(PARAGRAPH).getLength()); assertEquals(1, getBody().getElementsByTagName(ANCHOR).getLength()); // We should have at least one BR for a line break. Some browser need another one to serve as an empty line. assertTrue(getBody().getElementsByTagName(BR).getLength() > 0); // Type Enter. rta .onBrowserEvent((Event) rta.getDocument() .createKeyDownEvent(false, false, false, false, KeyCodes.KEY_ENTER)); // We should have two paragraphs and one link. assertEquals(2, getBody().getElementsByTagName(PARAGRAPH).getLength()); assertEquals(1, getBody().getElementsByTagName(ANCHOR).getLength()); // The link should be in the first paragraph. assertEquals(1, getBody().getElementsByTagName(PARAGRAPH).getItem(0).getElementsByTagName(ANCHOR).getLength()); } }