tests for task file actions
[idea/community.git] / python / educational-core / course-creator / testSrc / com / jetbrains / edu / coursecreator / CCTestCase.java
1 package com.jetbrains.edu.coursecreator;
2
3 import com.intellij.openapi.application.ApplicationManager;
4 import com.intellij.openapi.application.Result;
5 import com.intellij.openapi.command.WriteCommandAction;
6 import com.intellij.openapi.diagnostic.Logger;
7 import com.intellij.openapi.editor.Document;
8 import com.intellij.openapi.editor.EditorFactory;
9 import com.intellij.openapi.editor.markup.MarkupModel;
10 import com.intellij.openapi.editor.markup.RangeHighlighter;
11 import com.intellij.openapi.fileEditor.FileDocumentManager;
12 import com.intellij.openapi.util.Pair;
13 import com.intellij.openapi.util.TextRange;
14 import com.intellij.openapi.util.io.FileUtil;
15 import com.intellij.openapi.vfs.LocalFileSystem;
16 import com.intellij.openapi.vfs.VirtualFile;
17 import com.intellij.testFramework.EditorTestUtil;
18 import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
19 import com.jetbrains.edu.learning.StudyTaskManager;
20 import com.jetbrains.edu.learning.StudyUtils;
21 import com.jetbrains.edu.learning.courseFormat.*;
22 import org.jetbrains.annotations.NotNull;
23 import org.jetbrains.annotations.Nullable;
24 import org.junit.ComparisonFailure;
25
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31
32 public abstract class CCTestCase extends CodeInsightFixtureTestCase {
33   private static final Logger LOG = Logger.getInstance(CCTestCase.class);
34
35   @Nullable
36   public static RangeHighlighter getHighlighter(MarkupModel model, AnswerPlaceholder placeholder) {
37     for (RangeHighlighter highlighter : model.getAllHighlighters()) {
38       int endOffset = placeholder.getOffset() + placeholder.getRealLength();
39       if (highlighter.getStartOffset() == placeholder.getOffset() && highlighter.getEndOffset() == endOffset) {
40         return highlighter;
41       }
42     }
43     return null;
44   }
45
46   protected static void checkHighlighters(TaskFile taskFile, MarkupModel markupModel) {
47     for (AnswerPlaceholder answerPlaceholder : taskFile.getAnswerPlaceholders()) {
48       if (getHighlighter(markupModel, answerPlaceholder) == null) {
49         throw new AssertionError("No highlighter for placeholder: " + CCTestsUtil.getPlaceholderPresentation(answerPlaceholder));
50       }
51     }
52   }
53
54   public void checkByFile(TaskFile taskFile, String fileName, boolean useLength) {
55     Pair<Document, List<AnswerPlaceholder>> placeholders = getPlaceholders(fileName, useLength, true);
56     String message = "Placeholders don't match";
57     if (taskFile.getAnswerPlaceholders().size() != placeholders.second.size()) {
58       throw new ComparisonFailure(message,
59                                   CCTestsUtil.getPlaceholdersPresentation(taskFile.getAnswerPlaceholders()),
60                                   CCTestsUtil.getPlaceholdersPresentation(placeholders.second));
61     }
62     for (AnswerPlaceholder answerPlaceholder : placeholders.getSecond()) {
63       AnswerPlaceholder placeholder = taskFile.getAnswerPlaceholder(answerPlaceholder.getOffset());
64       if (!CCTestsUtil.comparePlaceholders(placeholder, answerPlaceholder)) {
65         throw new ComparisonFailure(message,
66                                     CCTestsUtil.getPlaceholdersPresentation(taskFile.getAnswerPlaceholders()),
67                                     CCTestsUtil.getPlaceholdersPresentation(placeholders.second));
68       }
69     }
70   }
71
72   @Override
73   protected String getBasePath() {
74     return "/community/python/educational-core/course-creator/testData";
75   }
76
77   @Override
78   protected void setUp() throws Exception {
79     super.setUp();
80     Course course = new Course();
81     course.setName("test course");
82     course.setCourseDirectory(getProject().getBasePath());
83     StudyTaskManager.getInstance(getProject()).setCourse(course);
84
85     Lesson lesson = new Lesson();
86     lesson.setName("lesson1");
87     Task task = new Task();
88     task.setName("task1");
89     task.setIndex(1);
90     lesson.addTask(task);
91     lesson.setIndex(1);
92     course.getLessons().add(lesson);
93     course.setCourseMode(CCUtils.COURSE_MODE);
94     course.initCourse(false);
95     ApplicationManager.getApplication().runWriteAction(new Runnable() {
96       @Override
97       public void run() {
98         try {
99           VirtualFile lesson1 = myFixture.getProject().getBaseDir().createChildDirectory(this, "lesson1");
100           lesson1.createChildDirectory(this, "task1");
101         }
102         catch (IOException e) {
103           //ignore
104         }
105       }
106     });
107   }
108
109   protected VirtualFile copyFileToTask(String name) {
110     return myFixture.copyFileToProject(name, FileUtil.join(getProject().getBasePath(), "lesson1", "task1", name));
111   }
112
113   protected VirtualFile configureByTaskFile(String name) {
114     Task task = StudyTaskManager.getInstance(getProject()).getCourse().getLessons().get(0).getTaskList().get(0);
115     TaskFile taskFile = new TaskFile();
116     taskFile.setTask(task);
117     task.getTaskFiles().put(name, taskFile);
118     VirtualFile file = copyFileToTask(name);
119     myFixture.configureFromExistingVirtualFile(file);
120     Document document = FileDocumentManager.getInstance().getDocument(file);
121     for (AnswerPlaceholder placeholder : getPlaceholders(document, false)) {
122       taskFile.addAnswerPlaceholder(placeholder);
123     }
124     taskFile.sortAnswerPlaceholders();
125     StudyUtils.drawAllWindows(myFixture.getEditor(), taskFile);
126     CCUtils.createResourceFile(file, StudyTaskManager.getInstance(getProject()).getCourse(), file.getParent());
127     return file;
128   }
129
130   private static List<AnswerPlaceholder> getPlaceholders(Document document, boolean useLength) {
131     final List<AnswerPlaceholder> placeholders = new ArrayList<>();
132     new WriteCommandAction(null) {
133       @Override
134       protected void run(@NotNull Result result) {
135         final String openingTagRx = "<placeholder( taskText=\"(.+?)\")?( possibleAnswer=\"(.+?)\")?( hint=\"(.+?)\")?>";
136         final String closingTagRx = "</placeholder>";
137         CharSequence text = document.getCharsSequence();
138         final Matcher openingMatcher = Pattern.compile(openingTagRx).matcher(text);
139         final Matcher closingMatcher = Pattern.compile(closingTagRx).matcher(text);
140         int pos = 0;
141         while (openingMatcher.find(pos)) {
142           AnswerPlaceholder answerPlaceholder = new AnswerPlaceholder();
143           answerPlaceholder.setUseLength(useLength);
144           String taskText = openingMatcher.group(2);
145           if (taskText != null) {
146             answerPlaceholder.setTaskText(taskText);
147             answerPlaceholder.setLength(taskText.length());
148           }
149           String possibleAnswer = openingMatcher.group(4);
150           if (possibleAnswer != null) {
151             answerPlaceholder.setPossibleAnswer(possibleAnswer);
152           }
153           String hint = openingMatcher.group(6);
154           if (hint != null) {
155             answerPlaceholder.setHint(hint);
156           }
157           answerPlaceholder.setOffset(openingMatcher.start());
158           if (!closingMatcher.find(openingMatcher.end())) {
159             LOG.error("No matching closing tag found");
160           }
161           if (useLength) {
162             answerPlaceholder.setLength(closingMatcher.start() - openingMatcher.end());
163           } else {
164             if (possibleAnswer == null) {
165               answerPlaceholder.setPossibleAnswer(document.getText(TextRange.create(openingMatcher.end(), closingMatcher.start())));
166             }
167           }
168           document.deleteString(closingMatcher.start(), closingMatcher.end());
169           document.deleteString(openingMatcher.start(), openingMatcher.end());
170           placeholders.add(answerPlaceholder);
171           pos = answerPlaceholder.getOffset() + answerPlaceholder.getRealLength();
172         }
173       }
174     }.execute();
175     return placeholders;
176   }
177
178   public Pair<Document, List<AnswerPlaceholder>> getPlaceholders(String name) {
179     return getPlaceholders(name, true, false);
180   }
181
182   public Pair<Document, List<AnswerPlaceholder>> getPlaceholders(String name, boolean useLength, boolean removeMarkers) {
183     VirtualFile resultFile = LocalFileSystem.getInstance().findFileByPath(getTestDataPath() + "/" + name);
184     Document document = FileDocumentManager.getInstance().getDocument(resultFile);
185     Document tempDocument = EditorFactory.getInstance().createDocument(document.getCharsSequence());
186     if (removeMarkers) {
187       EditorTestUtil.extractCaretAndSelectionMarkers(tempDocument);
188     }
189     List<AnswerPlaceholder> placeholders = getPlaceholders(tempDocument, useLength);
190     return Pair.create(tempDocument, placeholders);
191   }
192 }
193
194