7f18e4809cf42001722826899e0e9479f30163a4
[idea/community.git] / python / testSrc / com / jetbrains / python / refactoring / PyMakeFunctionTopLevelTest.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.python.refactoring;
17
18 import com.intellij.openapi.vfs.VirtualFile;
19 import com.intellij.testFramework.PlatformTestUtil;
20 import com.intellij.testFramework.TestActionEvent;
21 import com.intellij.util.IncorrectOperationException;
22 import com.jetbrains.python.PyBundle;
23 import com.jetbrains.python.fixtures.PyTestCase;
24 import com.jetbrains.python.psi.LanguageLevel;
25 import com.jetbrains.python.refactoring.makeFunctionTopLevel.PyMakeFunctionTopLevelRefactoring;
26 import org.jetbrains.annotations.NotNull;
27 import org.jetbrains.annotations.Nullable;
28
29 import java.io.IOException;
30
31 /**
32  * @author Mikhail Golubev
33  */
34 public class PyMakeFunctionTopLevelTest extends PyTestCase {
35
36   public void doTest(boolean enabled, @Nullable String message) {
37     myFixture.configureByFile(getTestName(true) + ".py");
38     final PyMakeFunctionTopLevelRefactoring action = new PyMakeFunctionTopLevelRefactoring();
39     // Similar to com.intellij.testFramework.fixtures.CodeInsightTestFixture.testAction()
40     final TestActionEvent event = new TestActionEvent(action);
41     action.beforeActionPerformedUpdate(event);
42     assertEquals(enabled, event.getPresentation().isEnabledAndVisible());
43     if (enabled) {
44       try {
45         action.actionPerformed(event);
46         myFixture.checkResultByFile(getTestName(true) + ".after.py");
47       }
48       catch (IncorrectOperationException e) {
49         if (message == null) {
50           fail("Refactoring failed unexpectedly with message: " + e.getMessage());
51         }
52         assertEquals(message, e.getMessage());
53       }
54     }
55   }
56
57   private void doMultiFileTest() throws IOException {
58     final String rootBeforePath = getTestName(true) + "/before";
59     final String rootAfterPath = getTestName(true) + "/after";
60     final VirtualFile copiedDirectory = myFixture.copyDirectoryToProject(rootBeforePath, "");
61     myFixture.configureByFile("main.py");
62     myFixture.testAction(new PyMakeFunctionTopLevelRefactoring());
63     PlatformTestUtil.assertDirectoriesEqual(getVirtualFileByName(getTestDataPath() + rootAfterPath), copiedDirectory);
64   }
65
66   private void doTestSuccess() {
67     doTest(true, null);
68   }
69
70   private void doTestFailure(@NotNull String message) {
71     doTest(true, message);
72   }
73
74   private static boolean isActionEnabled() {
75     final PyMakeFunctionTopLevelRefactoring action = new PyMakeFunctionTopLevelRefactoring();
76     final TestActionEvent event = new TestActionEvent(action);
77     action.beforeActionPerformedUpdate(event);
78     return event.getPresentation().isEnabled(); 
79   }
80
81   // PY-6637
82   public void testLocalFunctionSimple() {
83     doTestSuccess();
84   }
85
86   // PY-6637
87   public void testRefactoringAvailability() {
88     myFixture.configureByFile(getTestName(true) + ".py");
89     moveByText("func");
90     assertFalse(isActionEnabled());
91     moveByText("local");
92     assertTrue(isActionEnabled());
93     moveByText("method");
94     assertTrue(isActionEnabled());
95     moveByText("static_method");
96     assertFalse(isActionEnabled());
97     moveByText("class_method");
98     assertFalse(isActionEnabled());
99   }
100
101   // PY-6637
102   public void testLocalFunctionNonlocalReferenceToOuterScope() {
103     runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
104       @Override
105       public void run() {
106         doTestFailure(PyBundle.message("refactoring.make.function.top.level.error.nonlocal.writes"));
107       }
108     });
109   }
110
111   // PY-6637
112   public void testLocalFunctionNonlocalReferencesInInnerFunction() {
113     runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
114       @Override
115       public void run() {
116         doTestSuccess();
117       }
118     });
119   }
120
121   // PY-6637
122   public void testLocalFunctionReferenceToSelf() {
123     doTestFailure(PyBundle.message("refactoring.make.function.top.level.error.self.reads"));
124   }
125
126   public void testMethodNonlocalReferenceToOuterScope() {
127     runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
128       @Override
129       public void run() {
130         doTestFailure(PyBundle.message("refactoring.make.function.top.level.error.nonlocal.writes"));
131       }
132     });
133   }
134
135   public void testMethodOuterScopeReads() {
136     doTestFailure(PyBundle.message("refactoring.make.function.top.level.error.outer.scope.reads"));
137   }
138
139   public void testMethodOtherMethodCalls() {
140     doTestFailure(PyBundle.message("refactoring.make.function.top.level.error.method.calls"));
141   }
142
143   public void testMethodAttributeWrites() {
144     doTestFailure(PyBundle.message("refactoring.make.function.top.level.error.attribute.writes"));
145   }
146
147   public void testMethodReadPrivateAttributes() {
148     doTestFailure(PyBundle.message("refactoring.make.function.top.level.error.private.attributes"));
149   }
150
151   public void testMethodSelfUsedAsOperand() {
152     doTestFailure(PyBundle.message("refactoring.make.function.top.level.error.special.usage.of.self"));
153   }
154
155   public void testMethodOverriddenSelf() {
156     doTestFailure(PyBundle.message("refactoring.make.function.top.level.error.special.usage.of.self"));
157   }
158
159   public void testMethodSingleAttributeRead() {
160     doTestSuccess();
161   }
162
163   public void testMethodMultipleAttributesRead() {
164     doTestSuccess();
165   }
166
167   public void testMethodImportUpdates() throws IOException {
168     doMultiFileTest();
169   }
170
171   @Override
172   protected String getTestDataPath() {
173     return super.getTestDataPath() + "/refactoring/convertTopLevel/";
174   }
175 }