use another fixture as base class for course creator tests
[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 configureByTaskFile(String name) {
110     Task task = StudyTaskManager.getInstance(getProject()).getCourse().getLessons().get(0).getTaskList().get(0);
111     TaskFile taskFile = new TaskFile();
112     taskFile.setTask(task);
113     task.getTaskFiles().put(name, taskFile);
114     VirtualFile file =
115       myFixture.copyFileToProject(name, FileUtil.join(getProject().getBasePath(), "lesson1", "task1", name));
116     myFixture.configureFromExistingVirtualFile(file);
117     Document document = FileDocumentManager.getInstance().getDocument(file);
118     for (AnswerPlaceholder placeholder : getPlaceholders(document, false)) {
119       taskFile.addAnswerPlaceholder(placeholder);
120     }
121     taskFile.sortAnswerPlaceholders();
122     StudyUtils.drawAllWindows(myFixture.getEditor(), taskFile);
123     CCUtils.createResourceFile(file, StudyTaskManager.getInstance(getProject()).getCourse(), file.getParent());
124     return file;
125   }
126
127   private static List<AnswerPlaceholder> getPlaceholders(Document document, boolean useLength) {
128     final List<AnswerPlaceholder> placeholders = new ArrayList<>();
129     new WriteCommandAction(null) {
130       @Override
131       protected void run(@NotNull Result result) {
132         final String openingTagRx = "<placeholder( taskText=\"(.+?)\")?( possibleAnswer=\"(.+?)\")?( hint=\"(.+?)\")?>";
133         final String closingTagRx = "</placeholder>";
134         CharSequence text = document.getCharsSequence();
135         final Matcher openingMatcher = Pattern.compile(openingTagRx).matcher(text);
136         final Matcher closingMatcher = Pattern.compile(closingTagRx).matcher(text);
137         int pos = 0;
138         while (openingMatcher.find(pos)) {
139           AnswerPlaceholder answerPlaceholder = new AnswerPlaceholder();
140           answerPlaceholder.setUseLength(useLength);
141           String taskText = openingMatcher.group(2);
142           if (taskText != null) {
143             answerPlaceholder.setTaskText(taskText);
144             answerPlaceholder.setLength(taskText.length());
145           }
146           String possibleAnswer = openingMatcher.group(4);
147           if (possibleAnswer != null) {
148             answerPlaceholder.setPossibleAnswer(possibleAnswer);
149           }
150           String hint = openingMatcher.group(6);
151           if (hint != null) {
152             answerPlaceholder.setHint(hint);
153           }
154           answerPlaceholder.setOffset(openingMatcher.start());
155           if (!closingMatcher.find(openingMatcher.end())) {
156             LOG.error("No matching closing tag found");
157           }
158           if (useLength) {
159             answerPlaceholder.setLength(closingMatcher.start() - openingMatcher.end());
160           } else {
161             if (possibleAnswer == null) {
162               answerPlaceholder.setPossibleAnswer(document.getText(TextRange.create(openingMatcher.end(), closingMatcher.start())));
163             }
164           }
165           document.deleteString(closingMatcher.start(), closingMatcher.end());
166           document.deleteString(openingMatcher.start(), openingMatcher.end());
167           placeholders.add(answerPlaceholder);
168           pos = answerPlaceholder.getOffset() + answerPlaceholder.getRealLength();
169         }
170       }
171     }.execute();
172     return placeholders;
173   }
174
175   public Pair<Document, List<AnswerPlaceholder>> getPlaceholders(String name) {
176     return getPlaceholders(name, true, false);
177   }
178
179   public Pair<Document, List<AnswerPlaceholder>> getPlaceholders(String name, boolean useLength, boolean removeMarkers) {
180     VirtualFile resultFile = LocalFileSystem.getInstance().findFileByPath(getTestDataPath() + "/" + name);
181     Document document = FileDocumentManager.getInstance().getDocument(resultFile);
182     Document tempDocument = EditorFactory.getInstance().createDocument(document.getCharsSequence());
183     if (removeMarkers) {
184       EditorTestUtil.extractCaretAndSelectionMarkers(tempDocument);
185     }
186     List<AnswerPlaceholder> placeholders = getPlaceholders(tempDocument, useLength);
187     return Pair.create(tempDocument, placeholders);
188   }
189 }
190
191