add/delete answer placeholder tests
authorliana.bakradze <liana.bakradze@jetbrains.com>
Thu, 18 Aug 2016 11:38:57 +0000 (14:38 +0300)
committerliana.bakradze <liana.bakradze@jetbrains.com>
Thu, 18 Aug 2016 11:38:57 +0000 (14:38 +0300)
python/educational-core/course-creator/testData/actions/addPlaceholder/deletePlaceholder_after.txt [new file with mode: 0644]
python/educational-core/course-creator/testData/actions/addPlaceholder/deletePlaceholder_before.txt [new file with mode: 0644]
python/educational-core/course-creator/testData/actions/addPlaceholder/onePlaceholder_after.txt [new file with mode: 0644]
python/educational-core/course-creator/testData/actions/addPlaceholder/onePlaceholder_before.txt [new file with mode: 0644]
python/educational-core/course-creator/testData/actions/addPlaceholder/placeholderIntersection.txt [new file with mode: 0644]
python/educational-core/course-creator/testData/actions/addPlaceholder/withoutSelection_after.txt [new file with mode: 0644]
python/educational-core/course-creator/testData/actions/addPlaceholder/withoutSelection_before.txt [new file with mode: 0644]
python/educational-core/course-creator/testSrc/com/jetbrains/edu/coursecreator/CCTestCase.java
python/educational-core/course-creator/testSrc/com/jetbrains/edu/coursecreator/CCTestsUtil.java
python/educational-core/course-creator/testSrc/com/jetbrains/edu/coursecreator/actions/CCAnswerPlaceholderActionTest.java [new file with mode: 0644]
python/educational-core/course-creator/testSrc/com/jetbrains/edu/coursecreator/actions/CCShowPreviewTest.java

diff --git a/python/educational-core/course-creator/testData/actions/addPlaceholder/deletePlaceholder_after.txt b/python/educational-core/course-creator/testData/actions/addPlaceholder/deletePlaceholder_after.txt
new file mode 100644 (file)
index 0000000..56b857f
--- /dev/null
@@ -0,0 +1 @@
+we're going to delete this placeholder
\ No newline at end of file
diff --git a/python/educational-core/course-creator/testData/actions/addPlaceholder/deletePlaceholder_before.txt b/python/educational-core/course-creator/testData/actions/addPlaceholder/deletePlaceholder_before.txt
new file mode 100644 (file)
index 0000000..4c54702
--- /dev/null
@@ -0,0 +1 @@
+we're going to delete <placeholder>thi<caret>s</placeholder> placeholder
\ No newline at end of file
diff --git a/python/educational-core/course-creator/testData/actions/addPlaceholder/onePlaceholder_after.txt b/python/educational-core/course-creator/testData/actions/addPlaceholder/onePlaceholder_after.txt
new file mode 100644 (file)
index 0000000..ae22d67
--- /dev/null
@@ -0,0 +1 @@
+<placeholder taskText="type here" hint="Test hint">here</placeholder> will be added one placeholder
\ No newline at end of file
diff --git a/python/educational-core/course-creator/testData/actions/addPlaceholder/onePlaceholder_before.txt b/python/educational-core/course-creator/testData/actions/addPlaceholder/onePlaceholder_before.txt
new file mode 100644 (file)
index 0000000..ba43c83
--- /dev/null
@@ -0,0 +1 @@
+<selection>here</selection> will be added one placeholder
\ No newline at end of file
diff --git a/python/educational-core/course-creator/testData/actions/addPlaceholder/placeholderIntersection.txt b/python/educational-core/course-creator/testData/actions/addPlaceholder/placeholderIntersection.txt
new file mode 100644 (file)
index 0000000..c5c6689
--- /dev/null
@@ -0,0 +1 @@
+type <placeholder>h<selection>ere</selection></placeholder>
\ No newline at end of file
diff --git a/python/educational-core/course-creator/testData/actions/addPlaceholder/withoutSelection_after.txt b/python/educational-core/course-creator/testData/actions/addPlaceholder/withoutSelection_after.txt
new file mode 100644 (file)
index 0000000..fd68bcc
--- /dev/null
@@ -0,0 +1,3 @@
+def f():
+  pass
+  <placeholder taskText="type here" hint="Test hint">type here</placeholder>
\ No newline at end of file
diff --git a/python/educational-core/course-creator/testData/actions/addPlaceholder/withoutSelection_before.txt b/python/educational-core/course-creator/testData/actions/addPlaceholder/withoutSelection_before.txt
new file mode 100644 (file)
index 0000000..186cd19
--- /dev/null
@@ -0,0 +1,3 @@
+def f():
+  pass
+  <caret>
\ No newline at end of file
index d1756f2d31e3a57846965bdd19d020fea1931edc..9f1fd16ca1731e2dfac10b6ef52d4ef4d7d803e6 100644 (file)
@@ -7,16 +7,21 @@ import com.intellij.openapi.command.WriteCommandAction;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.editor.markup.MarkupModel;
+import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.EditorTestUtil;
 import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
 import com.jetbrains.edu.learning.StudyTaskManager;
 import com.jetbrains.edu.learning.courseFormat.*;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.junit.ComparisonFailure;
 
 import java.io.File;
 import java.io.IOException;
@@ -28,6 +33,43 @@ import java.util.regex.Pattern;
 public abstract class CCTestCase extends LightPlatformCodeInsightFixtureTestCase {
   private static final Logger LOG = Logger.getInstance(CCTestCase.class);
 
+  @Nullable
+  public static RangeHighlighter getHighlighter(MarkupModel model, AnswerPlaceholder placeholder) {
+    for (RangeHighlighter highlighter : model.getAllHighlighters()) {
+      int endOffset = placeholder.getOffset() + placeholder.getRealLength();
+      if (highlighter.getStartOffset() == placeholder.getOffset() && highlighter.getEndOffset() == endOffset) {
+        return highlighter;
+      }
+    }
+    return null;
+  }
+
+  protected static void checkHighlighters(TaskFile taskFile, MarkupModel markupModel) {
+    for (AnswerPlaceholder answerPlaceholder : taskFile.getAnswerPlaceholders()) {
+      if (getHighlighter(markupModel, answerPlaceholder) == null) {
+        throw new AssertionError("No highlighter for placeholder: " + CCTestsUtil.getPlaceholderPresentation(answerPlaceholder));
+      }
+    }
+  }
+
+  public void checkByFile(TaskFile taskFile, String fileName, boolean useLength) {
+    Pair<Document, List<AnswerPlaceholder>> placeholders = getPlaceholders(fileName, useLength, true);
+    String message = "Placeholders don't match";
+    if (taskFile.getAnswerPlaceholders().size() != placeholders.second.size()) {
+      throw new ComparisonFailure(message,
+                                  CCTestsUtil.getPlaceholdersPresentation(taskFile.getAnswerPlaceholders()),
+                                  CCTestsUtil.getPlaceholdersPresentation(placeholders.second));
+    }
+    for (AnswerPlaceholder answerPlaceholder : placeholders.getSecond()) {
+      AnswerPlaceholder placeholder = taskFile.getAnswerPlaceholder(answerPlaceholder.getOffset());
+      if (!CCTestsUtil.comparePlaceholders(placeholder, answerPlaceholder)) {
+        throw new ComparisonFailure(message,
+                                    CCTestsUtil.getPlaceholdersPresentation(taskFile.getAnswerPlaceholders()),
+                                    CCTestsUtil.getPlaceholdersPresentation(placeholders.second));
+      }
+    }
+  }
+
   @Override
   protected String getTestDataPath() {
     //TODO: rewrite to work for plugin
@@ -63,7 +105,6 @@ public abstract class CCTestCase extends LightPlatformCodeInsightFixtureTestCase
         }
       }
     });
-
   }
 
   protected VirtualFile configureByTaskFile(String name) {
@@ -88,7 +129,7 @@ public abstract class CCTestCase extends LightPlatformCodeInsightFixtureTestCase
     new WriteCommandAction(null) {
       @Override
       protected void run(@NotNull Result result) {
-        final String openingTagRx = "<placeholder( taskText=\"(.+?)\")?( possibleAnswer=\"(.+?)\")?>";
+        final String openingTagRx = "<placeholder( taskText=\"(.+?)\")?( possibleAnswer=\"(.+?)\")?( hint=\"(.+?)\")?>";
         final String closingTagRx = "</placeholder>";
         CharSequence text = document.getCharsSequence();
         final Matcher openingMatcher = Pattern.compile(openingTagRx).matcher(text);
@@ -106,6 +147,10 @@ public abstract class CCTestCase extends LightPlatformCodeInsightFixtureTestCase
           if (possibleAnswer != null) {
             answerPlaceholder.setPossibleAnswer(possibleAnswer);
           }
+          String hint = openingMatcher.group(6);
+          if (hint != null) {
+            answerPlaceholder.setHint(hint);
+          }
           answerPlaceholder.setOffset(openingMatcher.start());
           if (!closingMatcher.find(openingMatcher.end())) {
             LOG.error("No matching closing tag found");
@@ -128,12 +173,24 @@ public abstract class CCTestCase extends LightPlatformCodeInsightFixtureTestCase
   }
 
   public Pair<Document, List<AnswerPlaceholder>> getPlaceholders(String name) {
+    return getPlaceholders(name, true, false);
+  }
+
+  public Pair<Document, List<AnswerPlaceholder>> getPlaceholders(String name, boolean useLength, boolean removeMarkers) {
     VirtualFile resultFile = LocalFileSystem.getInstance().findFileByPath(getTestDataPath() + "/" + name);
     Document document = FileDocumentManager.getInstance().getDocument(resultFile);
     Document tempDocument = EditorFactory.getInstance().createDocument(document.getCharsSequence());
-    List<AnswerPlaceholder> placeholders = getPlaceholders(tempDocument, true);
+    if (removeMarkers) {
+      EditorTestUtil.extractCaretAndSelectionMarkers(tempDocument);
+    }
+    List<AnswerPlaceholder> placeholders = getPlaceholders(tempDocument, useLength);
     return Pair.create(tempDocument, placeholders);
   }
+
+  @Override
+  protected boolean shouldContainTempFiles() {
+    return false;
+  }
 }
 
 
index 5b14b8e2035eb7147d325e77a14d4c3af7834987..8f4fb8a1abed7c53e717d373aa8a6e3afeefa5d1 100644 (file)
@@ -1,8 +1,43 @@
 package com.jetbrains.edu.coursecreator;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.intellij.openapi.util.text.StringUtil;
+import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
+
+import java.util.Collection;
+import java.util.List;
+
 public class CCTestsUtil {
+  public static final String BEFORE_POSTFIX = "_before.txt";
+  public static final String AFTER_POSTFIX = "_after.txt";
+
   private CCTestsUtil() {
   }
 
+  public static boolean comparePlaceholders(AnswerPlaceholder p1, AnswerPlaceholder p2) {
+    if (p1.getOffset() != p2.getOffset()) return false;
+    if (p1.getRealLength() != p2.getRealLength()) return false;
+    if (p1.getPossibleAnswer() != null ? !p1.getPossibleAnswer().equals(p2.getPossibleAnswer()) : p2.getPossibleAnswer() != null) return false;
+    if (p1.getTaskText() != null ? !p1.getTaskText().equals(p2.getTaskText()) : p2.getTaskText() != null) return false;
+    if (!p1.getHints().equals(p1.getHints())) return false;
+    return true;
+  }
 
+  public static String getPlaceholderPresentation(AnswerPlaceholder placeholder) {
+    return "offset=" + placeholder.getOffset() +
+           " length=" + placeholder.getLength() +
+           " possibleAnswer=" + placeholder.getPossibleAnswer() +
+           " taskText=" + placeholder.getTaskText();
+  }
+
+  public static String getPlaceholdersPresentation(List<AnswerPlaceholder> placeholders) {
+    Collection<String> transformed = Collections2.transform(placeholders, new Function<AnswerPlaceholder, String>() {
+      @Override
+      public String apply(AnswerPlaceholder placeholder) {
+        return getPlaceholderPresentation(placeholder);
+      }
+    });
+    return "[" + StringUtil.join(transformed, ",") + "]";
+  }
 }
diff --git a/python/educational-core/course-creator/testSrc/com/jetbrains/edu/coursecreator/actions/CCAnswerPlaceholderActionTest.java b/python/educational-core/course-creator/testSrc/com/jetbrains/edu/coursecreator/actions/CCAnswerPlaceholderActionTest.java
new file mode 100644 (file)
index 0000000..ab91204
--- /dev/null
@@ -0,0 +1,73 @@
+package com.jetbrains.edu.coursecreator.actions;
+
+import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.command.undo.UndoManager;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.edu.coursecreator.CCTestCase;
+import com.jetbrains.edu.coursecreator.CCTestsUtil;
+import com.jetbrains.edu.learning.StudyUtils;
+import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
+import com.jetbrains.edu.learning.courseFormat.TaskFile;
+import com.jetbrains.edu.learning.ui.CCCreateAnswerPlaceholderDialog;
+
+import java.util.Collections;
+import java.util.List;
+
+public class CCAnswerPlaceholderActionTest extends CCTestCase {
+  static class CCTestAction extends CCAddAnswerPlaceholder {
+    @Override
+    protected CCCreateAnswerPlaceholderDialog createDialog(Project project, AnswerPlaceholder answerPlaceholder) {
+      return new CCCreateAnswerPlaceholderDialog(project, answerPlaceholder.getTaskText(), answerPlaceholder.getHints()) {
+        @Override
+        public boolean showAndGet() {
+          return true;
+        }
+
+        @Override
+        public String getTaskText() {
+          return "type here";
+        }
+
+        @Override
+        public List<String> getHints() {
+          return Collections.singletonList("Test hint");
+        }
+      };
+    }
+  }
+
+  public void testPlaceholderWithSelection() {
+    doTest("onePlaceholder");
+  }
+
+  public void testPlaceholderWithoutSelection() {
+    doTest("withoutSelection");
+  }
+
+  public void testPlaceholderIntersection() {
+    configureByTaskFile("placeholderIntersection.txt");
+    Presentation presentation = myFixture.testAction(new CCTestAction());
+    assertTrue(presentation.isVisible() && !presentation.isEnabled());
+  }
+
+  public void testPlaceholderDeleted() {
+    doTest("deletePlaceholder");
+  }
+
+  private void doTest(String name) {
+    VirtualFile virtualFile = configureByTaskFile(name + CCTestsUtil.BEFORE_POSTFIX);
+    myFixture.testAction(new CCTestAction());
+    TaskFile taskFile = StudyUtils.getTaskFile(getProject(), virtualFile);
+    checkByFile(taskFile, name + CCTestsUtil.AFTER_POSTFIX, false);
+    checkHighlighters(taskFile, myFixture.getEditor().getMarkupModel());
+    UndoManager.getInstance(getProject()).undo(FileEditorManager.getInstance(getProject()).getSelectedEditor(virtualFile));
+    checkByFile(taskFile, name + CCTestsUtil.BEFORE_POSTFIX, false);
+  }
+
+  @Override
+  protected String getTestDataPath() {
+    return super.getTestDataPath() + "/actions/addPlaceholder";
+  }
+}
index c105652d44e1d4a7734fb6fc03508d2b1913a243..b5f57febac055dbc255cc4d6337aacd821af5f4c 100644 (file)
@@ -6,16 +6,14 @@ import com.intellij.openapi.actionSystem.LangDataKeys;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.EditorFactory;
-import com.intellij.openapi.editor.markup.MarkupModel;
-import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiFile;
 import com.intellij.testFramework.MapDataContext;
 import com.intellij.testFramework.TestActionEvent;
 import com.jetbrains.edu.coursecreator.CCTestCase;
+import com.jetbrains.edu.coursecreator.CCTestsUtil;
 import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
-import org.jetbrains.annotations.Nullable;
 
 import java.util.List;
 
@@ -36,50 +34,34 @@ public class CCShowPreviewTest extends CCTestCase {
   }
 
   public void testOnePlaceholder() {
-    doTest("test_before.txt", "test_after.txt");
+    doTest("test");
   }
 
   public void testSeveralPlaceholders() {
-    doTest("several_before.txt", "several_after.txt");
+    doTest("several");
   }
 
-  private void doTest(String beforeName, String afterName) {
-    VirtualFile file = configureByTaskFile(beforeName);
+  private void doTest(String name) {
+    VirtualFile file = configureByTaskFile(name + CCTestsUtil.BEFORE_POSTFIX);
     CCShowPreview action = new CCShowPreview();
     TestActionEvent e = getActionEvent(action, getPsiManager().findFile(file));
     action.beforeActionPerformedUpdate(e);
     assertTrue(e.getPresentation().isEnabled() && e.getPresentation().isVisible());
     action.actionPerformed(e);
     Editor editor = EditorFactory.getInstance().getAllEditors()[1];
-    Pair<Document, List<AnswerPlaceholder>> pair = getPlaceholders(afterName);
+    Pair<Document, List<AnswerPlaceholder>> pair = getPlaceholders(name + CCTestsUtil.AFTER_POSTFIX);
     assertEquals("Files don't match", editor.getDocument().getText(), pair.getFirst().getText());
     for (AnswerPlaceholder placeholder : pair.getSecond()) {
-      assertNotNull("No highlighter for placeholder", getHighlighter(editor.getMarkupModel(), placeholder));
+      assertNotNull("No highlighter for placeholder:" + CCTestsUtil.getPlaceholderPresentation(placeholder), getHighlighter(editor.getMarkupModel(), placeholder));
     }
     EditorFactory.getInstance().releaseEditor(editor);
   }
 
-  @Nullable
-  private static RangeHighlighter getHighlighter(MarkupModel model, AnswerPlaceholder placeholder) {
-    for (RangeHighlighter highlighter : model.getAllHighlighters()) {
-      int endOffset = placeholder.getOffset() + placeholder.getRealLength();
-      if (highlighter.getStartOffset() == placeholder.getOffset() && highlighter.getEndOffset() == endOffset) {
-        return highlighter;
-      }
-    }
-    return null;
-  }
-
   @Override
   protected String getTestDataPath() {
     return super.getTestDataPath() + "/actions/preview";
   }
 
-  @Override
-  protected boolean shouldContainTempFiles() {
-    return false;
-  }
-
   TestActionEvent getActionEvent(AnAction action, PsiFile psiFile) {
     MapDataContext context = new MapDataContext();
     context.put(CommonDataKeys.PSI_FILE, psiFile);