/*******************************************************************************
* Copyright (c) 2013 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.ui.views.palette.test;
import java.util.Properties;
import junit.framework.TestCase;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.ITextEditor;
import org.jboss.tools.common.model.ui.views.palette.XModelPaletteInsertHelper;
import org.jboss.tools.test.util.TestProjectProvider;
import org.jboss.tools.test.util.WorkbenchUtils;
/**
* The JUnit test cases for issue https://issues.jboss.org/browse/JBIDE-14735
*
* @author Victor Rubezhny
*
*/
public class PaletteInsertHelperTest extends TestCase {
private static final String PROJECT_NAME = "StaticWebProject"; //$NON-NLS-1$
private static final String PAGE_NAME = "/WebContent/html5test.html"; //$NON-NLS-1$
private static final String TEMPLATE_START_TEXT =
"<a href=\"\" id=\"button-1\" data-role=\"button\">Link button</a>\n"; //$NON-NLS-1$
private static final String BASE_LINE_TEXT = "<div data-role=\"content\">"; //$NON-NLS-1$
// Test Data for JBIDE-15194
private static final String PAGE_NAME_2 = "/WebContent/html5test2.html"; //$NON-NLS-1$
private static final String TEMPLATE_START_TEXT_2 =
"<div data-role=\"page\" id=\"page-1\">\n" + //$NON-NLS-1$
"\t<div data-role=\"header\">\n" + //$NON-NLS-1$
"\t\t<h1>Page Title</h1>\n" + //$NON-NLS-1$
"\t</div>\n" + //$NON-NLS-1$
"\t<div data-role=\"content\">\n" + //$NON-NLS-1$
"\t\t<p>Page content goes here.</p>"; //$NON-NLS-1$
private static final String TEMPLATE_END_TEXT_2 =
"\t</div>\n\t<div data-role=\"footer\">\n\t\t<h4>Page Footer</h4>\n\t</div>\n</div>\n"; //$NON-NLS-1$
private static final String BASE_LINE_TEXT_2 = "<div>"; //$NON-NLS-1$
private static final String BASE_LINE_END_TEXT2 = "</div>"; //$NON-NLS-1$
TestProjectProvider provider = null;
protected IProject project = null;
public void setUp() throws Exception {
provider = new TestProjectProvider("org.jboss.tools.common.model.ui.test", null, PROJECT_NAME, false);
project = provider.getProject();
}
protected void tearDown() throws Exception {
if(provider != null) {
provider.dispose();
project = null;
}
}
public void testPaletteInsertHelper() {
IFile testfile = project.getFile(PAGE_NAME);
assertTrue("Test file doesn't exist: " + project.getName() + "/" + PAGE_NAME,
(testfile.exists() && testfile.isAccessible()));
IEditorPart editor = WorkbenchUtils.openEditor(PROJECT_NAME + "/" + PAGE_NAME);
assertNotNull("Cannot open an editor for the page: " + project.getName() + "/" + PAGE_NAME,
editor);
try {
ITextEditor textEditor = (ITextEditor)editor.getAdapter(ITextEditor.class);
assertNotNull("Cannot open a text editor for the page: " + project.getName() + "/" + PAGE_NAME,
textEditor);
IDocument document = (IDocument)editor.getAdapter(IDocument.class);
assertNotNull("Cannot get a document for the page: " + project.getName() + "/" + PAGE_NAME,
textEditor);
Properties pp = new Properties();
pp.setProperty(XModelPaletteInsertHelper.PROPERTY_START_TEXT, TEMPLATE_START_TEXT);
pp.setProperty(XModelPaletteInsertHelper.PROPERTY_END_TEXT, "");
pp.setProperty(XModelPaletteInsertHelper.PROPERTY_NEW_LINE, "true");
pp.setProperty(XModelPaletteInsertHelper.PROPERTY_REFORMAT_BODY, "yes");
int tabWidth = getTabWidth();
try {
String text = document.get();
int baseLineOffset = text.indexOf(BASE_LINE_TEXT);
assertTrue("Base text line not found in document", baseLineOffset != -1);
// Base line indent
int baseLine = document.getLineOfOffset(baseLineOffset);
String lineText = document.get(document.getLineOffset(baseLine), document.getLineLength(baseLine));
String lineDelimiter = document.getLineDelimiter(baseLine);
int baseLineInsetWidth = calculateDisplayedWidth(getIndentOfLine(lineText, lineDelimiter), tabWidth);
assertTrue("Wrong test page template: base line inset must not be 0", baseLineInsetWidth > 0);
// Next (empty) line template
lineText = document.get(document.getLineOffset(baseLine + 1), document.getLineLength(baseLine + 1));
assertTrue("Wrong test page template: empty line must not contain a text", lineText.trim().isEmpty());
lineDelimiter = document.getLineDelimiter(baseLine + 1);
int emptyLineInsetWidth = calculateDisplayedWidth(getIndentOfLine(lineText, lineDelimiter), tabWidth);
assertTrue("Wrong test page template: empty line inset must not be greater than base line inset", emptyLineInsetWidth > baseLineInsetWidth);
int index = text.indexOf('|');
assertTrue("Insertion position not found in document", index != -1);
try {
document.replace(index, "|".length(), "");
} catch (BadLocationException e) {
fail("Cannot modify document: " + e.getLocalizedMessage());
}
textEditor.selectAndReveal(index, 0);
// Insert template into current selection
XModelPaletteInsertHelper.getInstance().insertIntoEditor(textEditor, pp);
String updatedText = document.get();
int indexOfChange = updatedText.indexOf(TEMPLATE_START_TEXT.trim());
assertTrue("Changed text line not found in document", indexOfChange != -1);
int changedLine = document.getLineOfOffset(indexOfChange);
lineText = document.get(document.getLineOffset(changedLine), document.getLineLength(changedLine));
lineDelimiter = document.getLineDelimiter(changedLine);
int changedLineInsetWidth = calculateDisplayedWidth(getIndentOfLine(lineText, lineDelimiter), tabWidth);
assertTrue("Changed line indent must be greater than base line offset by value of tab width", changedLineInsetWidth - baseLineInsetWidth == tabWidth);
// Repeat the insert operation in the next line
int newIndex = document.getLineOffset(changedLine + 1);
textEditor.selectAndReveal(newIndex, 0);
// Insert template into current selection
XModelPaletteInsertHelper.getInstance().insertIntoEditor(textEditor, pp);
updatedText = document.get();
indexOfChange = updatedText.indexOf(TEMPLATE_START_TEXT.trim(), newIndex);
assertTrue("Second changed text line not found in document", indexOfChange != -1);
int secondChangedLine = document.getLineOfOffset(indexOfChange);
lineText = document.get(document.getLineOffset(secondChangedLine), document.getLineLength(secondChangedLine));
lineDelimiter = document.getLineDelimiter(secondChangedLine);
int secondChangedLineInsetWidth = calculateDisplayedWidth(getIndentOfLine(lineText, lineDelimiter), tabWidth);
assertTrue("Indent of second changed line must be the same as indent of first changed line", changedLineInsetWidth == secondChangedLineInsetWidth);
} catch (BadLocationException e) {
fail("Exception occured: " + e.getLocalizedMessage());
}
} finally {
if (editor != null)
WorkbenchUtils.closeAllEditors();
}
}
/**
* Test case for issue JBIDE-15194
*/
public void testPaletteInsertHelperMultiline() {
IFile testfile = project.getFile(PAGE_NAME_2);
assertTrue("Test file doesn't exist: " + project.getName() + "/" + PAGE_NAME_2,
(testfile.exists() && testfile.isAccessible()));
IEditorPart editor = WorkbenchUtils.openEditor(PROJECT_NAME + "/" + PAGE_NAME_2);
assertNotNull("Cannot open an editor for the page: " + project.getName() + "/" + PAGE_NAME_2,
editor);
try {
ITextEditor textEditor = (ITextEditor)editor.getAdapter(ITextEditor.class);
assertNotNull("Cannot open a text editor for the page: " + project.getName() + "/" + PAGE_NAME_2,
textEditor);
IDocument document = (IDocument)editor.getAdapter(IDocument.class);
assertNotNull("Cannot get a document for the page: " + project.getName() + "/" + PAGE_NAME_2,
textEditor);
Properties pp = new Properties();
pp.setProperty(XModelPaletteInsertHelper.PROPERTY_START_TEXT, TEMPLATE_START_TEXT_2);
pp.setProperty(XModelPaletteInsertHelper.PROPERTY_END_TEXT, TEMPLATE_END_TEXT_2);
pp.setProperty(XModelPaletteInsertHelper.PROPERTY_NEW_LINE, "true");
pp.setProperty(XModelPaletteInsertHelper.PROPERTY_REFORMAT_BODY, "yes");
int tabWidth = getTabWidth();
try {
String text = document.get();
int baseLineOffset = text.indexOf(BASE_LINE_TEXT_2 + "|" + BASE_LINE_END_TEXT2);
assertTrue("Base text line not found in document", baseLineOffset != -1);
// Base line indent
int baseLine = document.getLineOfOffset(baseLineOffset);
String lineText = document.get(document.getLineOffset(baseLine), document.getLineLength(baseLine));
String lineDelimiter = document.getLineDelimiter(baseLine);
int baseLineInsetWidth = calculateDisplayedWidth(getIndentOfLine(lineText, lineDelimiter), tabWidth);
assertTrue("Wrong test page template: base line inset must not be 0", baseLineInsetWidth > 0);
int index = text.indexOf('|');
assertTrue("Insertion position not found in document", index != -1);
try {
document.replace(index, "|".length(), "");
} catch (BadLocationException e) {
fail("Cannot modify document: " + e.getLocalizedMessage());
}
textEditor.selectAndReveal(index, 0);
// Insert template into current selection
XModelPaletteInsertHelper.getInstance().insertIntoEditor(textEditor, pp);
String updatedText = document.get();
String[] templateStartLines = TEMPLATE_START_TEXT_2.split("\n");
String[] templateEndLines = TEMPLATE_END_TEXT_2.split("\n");
// Check the base line (it should be splitted into two lines)
baseLineOffset = updatedText.indexOf(BASE_LINE_TEXT_2);
assertTrue("Base text line not found in document", baseLineOffset != -1);
baseLine = document.getLineOfOffset(baseLineOffset);
baseLineInsetWidth = calculateDisplayedWidth(getIndentOfLine(lineText, lineDelimiter), tabWidth);
String baseLineText = document.get(document.getLineOffset(baseLine), document.getLineLength(baseLine)).trim();
assertTrue("Base line wasn't splitter or start of base line text isn't found",
BASE_LINE_TEXT_2.trim().equals(baseLineText.trim()));
int newIndex = document.getLineOffset(baseLine + 1);
/// Check indent of first row of template start text and find the end of inserted template start text
boolean doCheck = true;
int changedLine = baseLine + 1;
int secondChangedLineInsetWidth = -1;
for (String line : templateStartLines) {
lineText = document.get(document.getLineOffset(changedLine), document.getLineLength(changedLine));
assertTrue("Changed text line from start template not found in document",
line.trim().equals(lineText.trim()));
if (doCheck) {
lineDelimiter = document.getLineDelimiter(changedLine);
secondChangedLineInsetWidth = calculateDisplayedWidth(getIndentOfLine(lineText, lineDelimiter), tabWidth);
assertTrue("Indent of second changed line must be greater than indent of first changed line by a tab width",
baseLineInsetWidth + tabWidth == secondChangedLineInsetWidth);
doCheck = false;
}
changedLine++;
}
secondChangedLineInsetWidth = -1;
// Check indent of last row of template end text and find the end of inserted template end text
for (String line : templateEndLines) {
lineText = document.get(document.getLineOffset(changedLine), document.getLineLength(changedLine));
assertTrue("Changed text line from start template not found in document",
line.trim().equals(lineText.trim()));
changedLine++;
}
// check the indent of the last line
lineDelimiter = document.getLineDelimiter(changedLine - 1); // Because the index is incremented already
secondChangedLineInsetWidth = calculateDisplayedWidth(getIndentOfLine(lineText, lineDelimiter), tabWidth);
assertTrue("Indent of pre-last changed line must be greater than indent of first changed line by a tab width",
baseLineInsetWidth + tabWidth == secondChangedLineInsetWidth);
// Check the indent of base line text ending (should be the same as the base line text starting one)
lineText = document.get(document.getLineOffset(changedLine), document.getLineLength(changedLine));
assertTrue("Changed text line from end template not found in document",
BASE_LINE_END_TEXT2.trim().equals(lineText.trim()));
lineDelimiter = document.getLineDelimiter(changedLine);
secondChangedLineInsetWidth = calculateDisplayedWidth(getIndentOfLine(lineText, lineDelimiter), tabWidth);
assertTrue("Indent of last changed line must be greater than indent of first changed line by a tab width",
baseLineInsetWidth == secondChangedLineInsetWidth);
} catch (BadLocationException e) {
fail("Exception occured: " + e.getLocalizedMessage());
}
} finally {
if (editor != null)
WorkbenchUtils.closeAllEditors();
}
}
public void testOffsetCorrectionToStartNode(){
checkCorrectOffsetOrSelection("/WebContent/start_node.html", "<table", "");
}
public void testOffsetCorrectionToEndNode(){
checkCorrectOffsetOrSelection("/WebContent/end_node.html", "END", "");
}
public void testSelectionCorrectionToNode(){
checkCorrectOffsetOrSelection("/WebContent/full_node.html", "<td", "END");
}
public void testSelectionCorrectionExcludeNodes(){
checkCorrectOffsetOrSelection("/WebContent/exclude_node.html", "<td", "END");
}
public void testSelectionCorrectionBetweenNodes(){
checkCorrectOffsetOrSelection("/WebContent/between_nodes.html", "START", "");
}
public void testTextNode(){
checkNotCorrectionOffsetOrSelection("/WebContent/test_text.html");
}
private void checkNotCorrectionOffsetOrSelection(String fileName) {
IFile testfile = project.getFile(fileName);
assertTrue("Test file doesn't exist: " + project.getName() + "/" + fileName,
(testfile.exists() && testfile.isAccessible()));
IEditorPart editor = WorkbenchUtils.openEditor(PROJECT_NAME + "/" + fileName);
assertNotNull("Cannot open an editor for the page: " + project.getName() + "/" + fileName,
editor);
try {
ITextEditor textEditor = (ITextEditor)editor.getAdapter(ITextEditor.class);
assertNotNull("Cannot open a text editor for the page: " + project.getName() + "/" + fileName,
textEditor);
IDocument document = (IDocument)editor.getAdapter(IDocument.class);
assertNotNull("Cannot get a document for the page: " + project.getName() + "/" + fileName,
textEditor);
try {
String text = document.get();
int startOffset = text.indexOf("|");
assertTrue("First | marker not found", startOffset >= 0);
document.replace(startOffset, 1, "");
text = document.get();
int endOffset = text.indexOf("|", startOffset);
if(endOffset >= 0){
document.replace(endOffset, 1, "");
}else{
endOffset = startOffset;
}
int length = endOffset - startOffset;
for(int index = startOffset; index < endOffset; index++){
int newOffset = XModelPaletteInsertHelper.getInstance().correctOffset(document, index, null);
assertEquals("Corrector did correct the offset", index, newOffset);
}
} catch (BadLocationException e) {
fail("Exception occured: " + e.getLocalizedMessage());
}
} finally {
if (editor != null)
WorkbenchUtils.closeAllEditors();
}
}
private void checkCorrectOffsetOrSelection(String fileName, String startTest, String endTest) {
IFile testfile = project.getFile(fileName);
assertTrue("Test file doesn't exist: " + project.getName() + "/" + fileName,
(testfile.exists() && testfile.isAccessible()));
IEditorPart editor = WorkbenchUtils.openEditor(PROJECT_NAME + "/" + fileName);
assertNotNull("Cannot open an editor for the page: " + project.getName() + "/" + fileName,
editor);
try {
ITextEditor textEditor = (ITextEditor)editor.getAdapter(ITextEditor.class);
assertNotNull("Cannot open a text editor for the page: " + project.getName() + "/" + fileName,
textEditor);
IDocument document = (IDocument)editor.getAdapter(IDocument.class);
assertNotNull("Cannot get a document for the page: " + project.getName() + "/" + fileName,
textEditor);
try {
String text = document.get();
int startOffset = text.indexOf("|");
assertTrue("First | marker not found", startOffset >= 0);
document.replace(startOffset, 1, "");
text = document.get();
int endOffset = text.indexOf("|", startOffset);
if(endOffset >= 0){
document.replace(endOffset, 1, "");
}else{
endOffset = startOffset;
}
int length = endOffset - startOffset;
if(length == 0){
int newOffset = XModelPaletteInsertHelper.getInstance().correctOffset(document, startOffset, null);
assertNotSame("Corrector did not correct the offset", startOffset, newOffset);
String testString = document.get(newOffset, startTest.length());
assertEquals("String not found for returned offset", startTest, testString);
}else{
ITextSelection newSelection = XModelPaletteInsertHelper.getInstance().correctSelection(document, new TextSelection(document, startOffset, length), (String)null);
if(newSelection.getLength() == 0){
assertTrue("Selection must be with 0 length", endTest.length() == 0);
}
String testStartString = document.get(newSelection.getOffset(), startTest.length());
assertEquals("String not found for returned offset", startTest, testStartString);
String testEndString = document.get(newSelection.getOffset()+newSelection.getLength(), endTest.length());
assertEquals("String not found for returned offset", endTest, testEndString);
}
} catch (BadLocationException e) {
fail("Exception occured: " + e.getLocalizedMessage());
}
} finally {
if (editor != null)
WorkbenchUtils.closeAllEditors();
}
}
private int calculateDisplayedWidth(String string, int tabWidth) {
int column= 0;
for (int i= 0; i < string.length(); i++)
if ('\t' == string.charAt(i))
column += tabWidth - (column % tabWidth);
else
column++;
return column;
}
private String getLineDelimiter(IDocument document, int line) throws BadLocationException {
String delim = document.getLineDelimiter(line);
return delim == null ? "" : delim;
}
private static String getIndentOfLine(String line, String lineDelimiter) {
int i= 0;
for (; i < line.length(); i++) {
if (!Character.isWhitespace(line.charAt(i)))
break;
if (lineDelimiter != null && lineDelimiter.indexOf(line.charAt(i)) != -1)
break;
}
return line.substring(0, i);
}
private static int getTabWidth() {
return Platform.getPreferencesService().getInt("org.eclipse.ui.editors", AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH, 4, new IScopeContext[]{new InstanceScope()}); //$NON-NLS-1$
}
}