Java tutorial
/* * 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.test.wysiwyg; import java.util.Date; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.Keys; import org.xwiki.test.wysiwyg.framework.AbstractWysiwygTestCase; import com.thoughtworks.selenium.Wait; import static org.junit.Assert.*; public class TabsTest extends AbstractWysiwygTestCase { @Test public void testMultipleClicksOnTheSameTab() { setContent("<strong>foo</strong>"); switchToWysiwyg(false); switchToWysiwyg(); switchToSource(); assertSourceText("**foo**"); } /** * Tests that XWIKI-3834 remains fixed. */ @Test public void testMultipleSwitches() { StringBuffer content = new StringBuffer(); // We put quite a lot of content so that the conversion is not immediate. content.append("<strong>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor " + "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation " + "ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in " + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " + "proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); content.append("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt " + "ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " + "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in " + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " + "proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); content.append("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt " + "ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " + "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in " + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " + "proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); content.append("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt " + "ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " + "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in " + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " + "proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</strong>"); setContent(content.toString()); // We go back and forth multiple times to be sure that it is not a matter of chance. switchToSource(false); switchToWysiwyg(false); switchToSource(false); switchToWysiwyg(false); switchToSource(); assertFalse(getSourceText().contains("strong")); } /** * @see XWIKI-4079: Links are lost when switching to Source in the WYSIWYG editor. */ @Test public void testLinksAreNotLostWhenSwitchingToSourceTab() { String content = "Visit [[XWiki>>http://www.xwiki.org]] and our [[blog>>Blog.WebHome]]."; switchToSource(); setSourceText(content); switchToWysiwyg(); switchToSource(); assertSourceText(content); } /** * @see XWIKI-3965: Relative images are not displayed when switching from Source tab to Wysiwyg tab. */ @Test public void testContextDocumentIsPreserved() { // Uploading an image to the current document is difficult. Instead we use a context sensitive velocity script. clickEditPageInWikiSyntaxEditor(); setFieldValue("content", "{{velocity}}$doc.fullName{{/velocity}}"); clickEditPageInWysiwyg(); waitForEditorToLoad(); String expected = getRichTextArea().getText(); switchToSource(); switchToWysiwyg(); assertEquals(expected, getRichTextArea().getText()); } /** * Switches to source tab while the rich text area is still loading. The source text must remain unchanged. */ @Test public void testSwitchToSourceWhileWysiwygIsLoading() { switchToSource(); StringBuffer sourceText = new StringBuffer(); sourceText.append("{{code language=\"java\"}}\n"); sourceText.append("public interface Command {\n"); sourceText.append(" boolean execute(String parameter);\n"); sourceText.append("}\n"); sourceText.append("{{/code}}"); setSourceText(sourceText.toString()); // Set the cursor position before "language" to see if it is preserved. getSourceTextArea().sendKeys(Keys.HOME, Keys.PAGE_UP, Keys.chord(Keys.CONTROL, Keys.ARROW_RIGHT), Keys.ARROW_RIGHT); // Switch to WYSIWYG tab but don't wait for the rich text area to load. switchToWysiwyg(false); // Switch back to source tab. switchToSource(); getSourceTextArea().sendKeys("x"); // Check the source text. We don't assert the cursor position directly because it isn't available when the test // is run in background. assertSourceText(sourceText.substring(0, 7) + "x" + sourceText.substring(7)); } /** * Switches to source tab and waits for the conversion. The cursor should be placed at the start. * * @see XWIKI-4392: Place the caret at the beginning of the content when swtching to WYSIWYG Source editor. */ @Test public void testSwitchToSourceWithHTMLChangesAndWait() { typeText("1"); applyStyleTitle1(); switchToSource(); getSourceTextArea().sendKeys("x"); assertSourceText("x= 1 ="); } /** * Switches to source tab without changing the HTML. The source selection should be preserved. */ @Test public void testSwitchToSourceWithoutHTMLChanges() { switchToSource(); String sourceText = "one **two** three"; setSourceText(sourceText); // Move the caret between the first two *. getSourceTextArea().sendKeys(Keys.chord(Keys.CONTROL, Keys.ARROW_LEFT, Keys.ARROW_LEFT), Keys.ARROW_LEFT); switchToWysiwyg(); // Switch back to source tab without changing the HTML. switchToSource(); getSourceTextArea().sendKeys("x"); // Check the source text. assertSourceText(sourceText.substring(0, 5) + "x" + sourceText.substring(5)); } /** * Switches to source tab but doesn't wait for the result. Comes back to source tab when the result is received. */ @Test public void testSwitchToSourceWithHTMLChangesAndDontWait() { setContent("<!--startmacro:code|-|language=\"java\"|-|public class Apple extends Fruit {\n" + " public String getColor() {\n return Colors.RED;\n }\n}--><!--stopmacro-->"); // Switch to source tab but don't wait for the conversion result. switchToSource(false); // Switch back to WYSIWYG tab. switchToWysiwyg(); // Wait for the conversion result on the WYSIWYG tab. new Wait() { public boolean until() { return getSourceText().length() > 1; } }.wait("Conversion takes too long!"); // Switch to source tab without waiting. The source text was already received. switchToSource(false); assertTrue(getSourceTextArea().isEnabled()); getSourceTextArea().sendKeys("x"); assertSourceText("x{{code language=\"java\"}}\npublic class Apple extends Fruit {\n" + " public String getColor() {\n return Colors.RED;\n }\n}\n{{/code}}"); } /** * Test if the editor switches back to WYSIWYG tab when the conversion from HTML to source text fails. */ @Test public void testSwitchToSourceFailure() { // Put some bogus content in the rich text area. This content should cause a conversion exception. String content = "<span class=\"wikiexternallink\"><a href=\"mailto:x@y.z\">xyz</a></span><!--stopwikilink-->"; setContent(content); // Try to switch to source. Don't wait because the plain text area will remain disabled. switchToSource(false); // The editor switches back to WYSIWYG tab if it catches a conversion exception. waitForElement("//div[@class = 'gwt-TabBarItem gwt-TabBarItem-selected']/div[. = 'WYSIWYG']"); // The HTML mustn't change. assertContent(content); // Let's see if we can correct the mistake. setContent("<p>Should be fine now.</p>"); switchToSource(); assertSourceText("Should be fine now."); } /** * Tests if the switch to source action can be canceled. */ @Test public void testCancelSwitchToSource() { // Put some content in the rich text area. setContent("<h1>Heading</h1><p>paragraph</p><ul><li>list</li></ul><table><tr><td>cell</td></tr></table>"); // Place the caret inside the heading. moveCaret("document.body.firstChild.firstChild", 3); // Switch to source but don't wait till the conversion is done. switchToSource(false); // Switch back to rich text area, before receiving the source text. switchToWysiwyg(); // Change the rich text. typeText("X"); // Switch to source again, this time with a different rich text. Wait for the conversion to end. switchToSource(); // Check the result. assertSourceText("= HeaXding =\n\nparagraph\n\n* list\n\n|cell"); } /** * @see XWIKI-4517: NullPointerException thrown when switching to Source tab before the rich text area has finished * loading */ @Test public void testSwitchToSourceBeforeWysiwygLoad() { // Switch to source and put some content that takes time to render. switchToSource(); String sourceText = "{{code}}long x = 1L;{{/code}}\n\n{{html}}" + new Date().getTime() + "{{/html}}\n\n{{velocity}}$doc.name{{/velocity}}"; setSourceText(sourceText); clickEditSaveAndContinue(); // Reload the page to be able to switch to source tab before the rich text area finishes loading. getSelenium().runScript("window.location.reload(true)"); // Switch to source tab as soon as the source tab is available. waitForElement("//div[@class = 'gwt-TabBarItem']/div[. = 'Source']"); switchToSource(); // Verify the source text. assertSourceText(sourceText); // NOTE: If the WYSIWYG editor is loaded when the page loads then the source text area is unusable until after // the load event fires which happens after all the external resource including in-line frames are completely // loaded. So even though we can switch to source tab before the rich text area finishes loading, we might not // be able to use the plain text area. As a consequence we can't write a more elaborate test. The solution is to // load the editor after the host page finishes loading. } /** * Switches to WYSIWYG tab while the source text area is still loading (i.e. waiting for a HTML to source conversion * result). The rich text must remain unchanged. */ @Test public void testSwitchToWysiwygWhileSourceIsLoading() { String content = "before <!--startmacro:code|-|language=\"java\"|-|\\npublic class Apple extends Fruit {\n" + " public String getColor() {\n return Colors.RED;\n }\n}\n--><!--stopmacro--> after"; setContent(content); // Select some text to see if the selection is preserved. select("document.body.firstChild", 3, "document.body.firstChild", 6); // Switch to source but don't wait for the conversion result. switchToSource(false); // Switch back to WYSIWYG tab before the conversion result is received. switchToWysiwyg(); // Overwrite the selected text. typeText("#"); // Check the result. assertContent(content.substring(0, 3) + "#" + content.substring(6)); } /** * Switches to WYSIWYG tab without changing the source text. The DOM selection should be preserved. */ @Test public void testSwitchToWysiwygWithoutSourceChanges() { setContent("<em>alice</em> and <strong>bob</strong>"); select("document.body.firstChild.firstChild", 3, "document.body.lastChild.firstChild", 1); // Switch to source and wait for the conversion result. switchToSource(); assertSourceText("//alice// and **bob**"); // Switch back to WYSIWYG tab without modifying the source text. switchToWysiwyg(); // Test is the content and the selection were preserved. pushToolBarButton("Clear Formatting"); assertContent("<em>ali</em>ce and b<strong>ob</strong>"); } /** * Switches to WYSIWYG tab and waits for the conversion. The caret should be placed at the start. */ @Test public void testSwitchToWysiwygWithSourceChangesAndWait() { switchToSource(); setSourceText("**X**Wiki"); switchToWysiwyg(); typeText("+"); assertContent("<p><strong>+X</strong>Wiki</p>"); } /** * Switches to WYSIWYG tab but doesn't wait for the rich text area to finish loading. Comes back to WYSIWYG tab when * the rich text area is loaded. */ @Test public void testSwitchToWysiwygWithHTMLChangesAndDontWait() { switchToSource(); String sourceText = "before {{code language=\"java\"}}private static final long x = 1L;{{/code}}"; setSourceText(sourceText); // Switch to WYSIWYG tab but don't wait for the rich text area to load. switchToWysiwyg(false); // Switch back to source tab and wait there for the rich text area to load. switchToSource(); getDriver() .waitUntilElementDisappears(By.xpath("//div[@class = 'xRichTextEditor']//div[@class = 'loading']")); // Switch again to WYSIWYG tab to check the result. switchToWysiwyg(); typeText("#"); switchToSource(); assertSourceText("#" + sourceText); } /** * Tests if the switch to WYSIWYG tab action can be canceled. */ @Test public void testCancelSwitchToWysiwyg() { // Switch to source tab and insert some content that takes time to render. A code macro is perfect for this. switchToSource(); StringBuilder sourceText = new StringBuilder(); sourceText.append("{{code language=\"java\"}}\n"); sourceText.append("public final class Apple extends Fruit {\n"); sourceText.append(" public String getColor() {\n"); sourceText.append(" return \"red\";\n"); sourceText.append(" }\n"); sourceText.append("}\n"); sourceText.append("{{/code}}"); setSourceText(sourceText.toString()); // Place the caret before "Apple". getSourceTextArea().sendKeys(Keys.HOME, Keys.PAGE_UP, Keys.ARROW_DOWN, Keys.chord(Keys.CONTROL, Keys.ARROW_RIGHT, Keys.ARROW_RIGHT, Keys.ARROW_RIGHT), Keys.ARROW_RIGHT); // Switch to rich text but don't wait till the rich text area finishes loading. switchToWysiwyg(false); // Switch back to source before the rich text area is reloaded. switchToSource(); // Change the content. getSourceTextArea().sendKeys("X"); // Switch to WYSIWYG tab again, this time with a different source text. Wait for the rich text area to load. switchToWysiwyg(); // Check the result. switchToSource(); getSourceTextArea().sendKeys("Y"); assertSourceText(sourceText.substring(0, 44) + "XY" + sourceText.substring(44)); } /** * Switches to source tab, changes the source text then switches back to WYSIWYG tab and undoes the change. */ @Test public void testUndoSourceChange() { typeText("1"); applyStyleTitle1(); switchToSource(); // Change the source text. getSourceTextArea().sendKeys(Keys.ARROW_RIGHT, Keys.ARROW_RIGHT, Keys.ARROW_RIGHT, "2"); // Switch to WYSIWYG tab and undo the change. switchToWysiwyg(); // The tool bar is not updated right away. We have to wait for the undo push button to become enabled. waitForPushButton(TOOLBAR_BUTTON_UNDO_TITLE, true); clickUndoButton(); // Check the result. switchToSource(); // NOTE: This is not the right result since the heading style was removed also. This needs to be fixed. assertSourceText("1"); } }