mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-04 17:20:55 +07:00
[IFT] Exclude testGuiFramework dependency from IFT modules
Also make test script to wait editor analyzed IDEA-CR-70569 GitOrigin-RevId: f7b3f69043de4fd064aa1c4c95c25622766825a1
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a088f477b2
commit
4cbe1d21b1
@@ -16,6 +16,6 @@
|
|||||||
<orderEntry type="module" module-name="intellij.featuresTrainer" />
|
<orderEntry type="module" module-name="intellij.featuresTrainer" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.debugger" />
|
<orderEntry type="module" module-name="intellij.platform.debugger" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.testGuiFramework" />
|
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
@@ -10,8 +10,6 @@ import com.intellij.openapi.editor.impl.EditorComponentImpl
|
|||||||
import com.intellij.openapi.wm.ToolWindowId
|
import com.intellij.openapi.wm.ToolWindowId
|
||||||
import com.intellij.openapi.wm.ToolWindowManager
|
import com.intellij.openapi.wm.ToolWindowManager
|
||||||
import com.intellij.openapi.wm.impl.content.BaseLabel
|
import com.intellij.openapi.wm.impl.content.BaseLabel
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.ui.InplaceButton
|
import com.intellij.ui.InplaceButton
|
||||||
import com.intellij.ui.UIBundle
|
import com.intellij.ui.UIBundle
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
@@ -43,7 +41,7 @@ class JavaInheritanceHierarchyLesson
|
|||||||
|
|
||||||
test {
|
test {
|
||||||
Thread.sleep(1000)
|
Thread.sleep(1000)
|
||||||
GuiTestUtil.shortcut(Key.ENTER)
|
invokeActionViaShortcut("ENTER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ package com.intellij.java.ift.lesson.navigation
|
|||||||
|
|
||||||
import com.intellij.find.SearchTextArea
|
import com.intellij.find.SearchTextArea
|
||||||
import com.intellij.java.ift.JavaLessonsBundle
|
import com.intellij.java.ift.JavaLessonsBundle
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.impl.actionButton
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.usageView.UsageViewBundle
|
import com.intellij.usageView.UsageViewBundle
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.LessonUtil
|
import training.dsl.LessonUtil
|
||||||
@@ -95,7 +92,7 @@ class JavaOccurrencesLesson
|
|||||||
stateCheck {
|
stateCheck {
|
||||||
editor.headerComponent == null
|
editor.headerComponent == null
|
||||||
}
|
}
|
||||||
test { GuiTestUtil.shortcut(Key.ESCAPE) }
|
test { invokeActionViaShortcut("ESCAPE") }
|
||||||
}
|
}
|
||||||
actionTask("FindNext") {
|
actionTask("FindNext") {
|
||||||
JavaLessonsBundle.message("java.find.occurrences.find.next.in.editor", action(it))
|
JavaLessonsBundle.message("java.find.occurrences.find.next.in.editor", action(it))
|
||||||
|
|||||||
@@ -4,11 +4,9 @@ package com.intellij.java.ift.lesson.refactorings
|
|||||||
import com.intellij.java.refactoring.JavaRefactoringBundle
|
import com.intellij.java.refactoring.JavaRefactoringBundle
|
||||||
import com.intellij.refactoring.RefactoringBundle
|
import com.intellij.refactoring.RefactoringBundle
|
||||||
import com.intellij.refactoring.extractMethod.ExtractMethodHandler
|
import com.intellij.refactoring.extractMethod.ExtractMethodHandler
|
||||||
import com.intellij.testGuiFramework.impl.button
|
|
||||||
import com.intellij.ui.UIBundle
|
import com.intellij.ui.UIBundle
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
||||||
import training.dsl.TaskTestContext
|
|
||||||
import training.dsl.dropMnemonic
|
import training.dsl.dropMnemonic
|
||||||
import training.dsl.parseLessonSample
|
import training.dsl.parseLessonSample
|
||||||
import training.learn.LessonsBundle
|
import training.learn.LessonsBundle
|
||||||
@@ -46,10 +44,8 @@ class JavaExtractMethodCocktailSortLesson
|
|||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
with(TaskTestContext.guiTestCase) {
|
dialog(RefactoringBundle.message("extract.method.title")) {
|
||||||
dialog(RefactoringBundle.message("extract.method.title"), needToKeepDialog=true) {
|
button(refactorButtonText).click()
|
||||||
button(refactorButtonText).click()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,10 +59,8 @@ class JavaExtractMethodCocktailSortLesson
|
|||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
with(TaskTestContext.guiTestCase) {
|
dialog(processDuplicatesTitle) {
|
||||||
dialog(processDuplicatesTitle) {
|
button(replaceButtonText).click()
|
||||||
button(replaceButtonText).click()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ package com.intellij.java.ift.lesson.refactorings
|
|||||||
import com.intellij.CommonBundle
|
import com.intellij.CommonBundle
|
||||||
import com.intellij.java.ift.JavaLessonsBundle
|
import com.intellij.java.ift.JavaLessonsBundle
|
||||||
import com.intellij.refactoring.RefactoringBundle
|
import com.intellij.refactoring.RefactoringBundle
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.util.ui.UIUtil
|
import com.intellij.util.ui.UIUtil
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.LessonUtil
|
import training.dsl.LessonUtil
|
||||||
@@ -88,8 +86,8 @@ class JavaRefactoringMenuLesson : RefactoringMenuLessonBase("java.refactoring.me
|
|||||||
stateCheck {
|
stateCheck {
|
||||||
!extractConstantDialogShowing()
|
!extractConstantDialogShowing()
|
||||||
}
|
}
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
GuiTestUtil.shortcut(Key.ENTER)
|
invokeActionViaShortcut("ENTER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import com.intellij.codeInsight.template.impl.TemplateManagerImpl
|
|||||||
import com.intellij.java.ift.JavaLessonsBundle
|
import com.intellij.java.ift.JavaLessonsBundle
|
||||||
import com.intellij.java.refactoring.JavaRefactoringBundle
|
import com.intellij.java.refactoring.JavaRefactoringBundle
|
||||||
import com.intellij.refactoring.rename.RenameProcessor
|
import com.intellij.refactoring.rename.RenameProcessor
|
||||||
import com.intellij.testGuiFramework.impl.button
|
|
||||||
import com.intellij.util.ui.UIUtil
|
import com.intellij.util.ui.UIUtil
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
import training.dsl.LessonUtil.checkExpectedStateOfEditor
|
import training.dsl.LessonUtil.checkExpectedStateOfEditor
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ package com.intellij.java.ift.lesson.run
|
|||||||
import com.intellij.icons.AllIcons
|
import com.intellij.icons.AllIcons
|
||||||
import com.intellij.java.ift.JavaLessonsBundle
|
import com.intellij.java.ift.JavaLessonsBundle
|
||||||
import com.intellij.openapi.editor.LogicalPosition
|
import com.intellij.openapi.editor.LogicalPosition
|
||||||
import com.intellij.testGuiFramework.impl.button
|
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.TaskTestContext
|
import training.dsl.TaskTestContext
|
||||||
import training.dsl.highlightButtonById
|
import training.dsl.highlightButtonById
|
||||||
import training.learn.lesson.general.run.CommonDebugLesson
|
import training.learn.lesson.general.run.CommonDebugLesson
|
||||||
|
|
||||||
class JavaDebugLesson : CommonDebugLesson("java.debug.workflow") {
|
class JavaDebugLesson : CommonDebugLesson("java.debug.workflow") {
|
||||||
|
|
||||||
|
override val testScriptProperties = TaskTestContext.TestScriptProperties(duration = 30)
|
||||||
|
|
||||||
private val demoClassName = JavaRunLessonsUtils.demoClassName
|
private val demoClassName = JavaRunLessonsUtils.demoClassName
|
||||||
override val configurationName: String = demoClassName
|
override val configurationName: String = demoClassName
|
||||||
override val sample = JavaRunLessonsUtils.demoSample
|
override val sample = JavaRunLessonsUtils.demoSample
|
||||||
@@ -41,11 +43,9 @@ class JavaDebugLesson : CommonDebugLesson("java.debug.workflow") {
|
|||||||
!inHotSwapDialog()
|
!inHotSwapDialog()
|
||||||
}
|
}
|
||||||
proposeModificationRestore(afterFixText)
|
proposeModificationRestore(afterFixText)
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
with(TaskTestContext.guiTestCase) {
|
dialog(null) {
|
||||||
dialog(null, needToKeepDialog = true) {
|
button("Reload").click()
|
||||||
button("Yes").click()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,8 +64,5 @@ class JavaDebugLesson : CommonDebugLesson("java.debug.workflow") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val testScriptProperties: TaskTestContext.TestScriptProperties
|
|
||||||
get() = TaskTestContext.TestScriptProperties(duration = 20)
|
|
||||||
|
|
||||||
override val fileName: String = "$demoClassName.java"
|
override val fileName: String = "$demoClassName.java"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,15 +12,14 @@
|
|||||||
<orderEntry type="library" name="kotlin-stdlib-jdk8" level="project" />
|
<orderEntry type="library" name="kotlin-stdlib-jdk8" level="project" />
|
||||||
<orderEntry type="library" scope="TEST" name="kotlin-test" level="project" />
|
<orderEntry type="library" scope="TEST" name="kotlin-test" level="project" />
|
||||||
<orderEntry type="library" name="Guava" level="project" />
|
<orderEntry type="library" name="Guava" level="project" />
|
||||||
<orderEntry type="library" name="fest" level="project" />
|
<orderEntry type="library" exported="" name="fest" level="project" />
|
||||||
<orderEntry type="library" name="fest-swing" level="project" />
|
<orderEntry type="library" exported="" name="fest-swing" level="project" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
|
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.execution.impl" />
|
<orderEntry type="module" module-name="intellij.platform.execution.impl" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.diff.impl" />
|
<orderEntry type="module" module-name="intellij.platform.diff.impl" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.debugger" />
|
<orderEntry type="module" module-name="intellij.platform.debugger" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.debugger.impl" />
|
<orderEntry type="module" module-name="intellij.platform.debugger.impl" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.testGuiFramework" />
|
|
||||||
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
|
<orderEntry type="module" module-name="intellij.platform.testFramework" scope="TEST" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.statistics" />
|
<orderEntry type="module" module-name="intellij.platform.statistics" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.tasks.impl" />
|
<orderEntry type="module" module-name="intellij.platform.tasks.impl" />
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ abstract class TaskContext : LearningDslBase {
|
|||||||
open fun addStep(step: CompletableFuture<Boolean>) = Unit
|
open fun addStep(step: CompletableFuture<Boolean>) = Unit
|
||||||
|
|
||||||
/** [action] What should be done to pass the current task */
|
/** [action] What should be done to pass the current task */
|
||||||
open fun test(action: TaskTestContext.() -> Unit) = Unit
|
open fun test(waitEditorToBeReady: Boolean = true, action: TaskTestContext.() -> Unit) = Unit
|
||||||
|
|
||||||
fun triggerByFoundPathAndHighlight(highlightBorder: Boolean = true, highlightInside: Boolean = false, usePulsation: Boolean = false,
|
fun triggerByFoundPathAndHighlight(highlightBorder: Boolean = true, highlightInside: Boolean = false, usePulsation: Boolean = false,
|
||||||
checkPath: TaskRuntimeContext.(tree: JTree, path: TreePath) -> Boolean) {
|
checkPath: TaskRuntimeContext.(tree: JTree, path: TreePath) -> Boolean) {
|
||||||
|
|||||||
@@ -1,35 +1,58 @@
|
|||||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package training.dsl
|
package training.dsl
|
||||||
|
|
||||||
|
import com.intellij.ide.util.treeView.NodeRenderer
|
||||||
import com.intellij.openapi.actionSystem.ActionManager
|
import com.intellij.openapi.actionSystem.ActionManager
|
||||||
import com.intellij.testGuiFramework.cellReader.ExtendedJListCellReader
|
import com.intellij.openapi.actionSystem.impl.ActionButton
|
||||||
import com.intellij.testGuiFramework.fixtures.ComponentFixture
|
import com.intellij.openapi.application.invokeAndWaitIfNeeded
|
||||||
import com.intellij.testGuiFramework.fixtures.IdeFrameFixture
|
import com.intellij.openapi.wm.impl.IdeFrameImpl
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
import com.intellij.ui.KeyStrokeAdapter
|
||||||
import com.intellij.testGuiFramework.framework.Timeouts
|
import com.intellij.ui.MultilineTreeCellRenderer
|
||||||
import com.intellij.testGuiFramework.impl.GuiTestCase
|
import com.intellij.ui.SimpleColoredComponent
|
||||||
import com.intellij.testGuiFramework.impl.findComponentWithTimeout
|
import org.fest.swing.core.GenericTypeMatcher
|
||||||
import com.intellij.testGuiFramework.impl.waitUntilFound
|
|
||||||
import com.intellij.testGuiFramework.util.step
|
|
||||||
import org.fest.swing.core.Robot
|
import org.fest.swing.core.Robot
|
||||||
|
import org.fest.swing.driver.BasicJListCellReader
|
||||||
|
import org.fest.swing.driver.ComponentDriver
|
||||||
|
import org.fest.swing.exception.ComponentLookupException
|
||||||
|
import org.fest.swing.exception.WaitTimedOutError
|
||||||
|
import org.fest.swing.fixture.AbstractComponentFixture
|
||||||
import org.fest.swing.fixture.ContainerFixture
|
import org.fest.swing.fixture.ContainerFixture
|
||||||
|
import org.fest.swing.fixture.JButtonFixture
|
||||||
import org.fest.swing.fixture.JListFixture
|
import org.fest.swing.fixture.JListFixture
|
||||||
|
import org.fest.swing.timing.Condition
|
||||||
|
import org.fest.swing.timing.Pause
|
||||||
import org.fest.swing.timing.Timeout
|
import org.fest.swing.timing.Timeout
|
||||||
|
import training.ui.LearningUiUtil
|
||||||
|
import training.ui.LearningUiUtil.findComponentWithTimeout
|
||||||
import training.util.invokeActionForFocusContext
|
import training.util.invokeActionForFocusContext
|
||||||
import java.awt.Component
|
import java.awt.Component
|
||||||
import java.awt.Container
|
import java.awt.Container
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import javax.swing.JButton
|
||||||
|
import javax.swing.JDialog
|
||||||
|
import javax.swing.JLabel
|
||||||
import javax.swing.JList
|
import javax.swing.JList
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
@LearningDsl
|
@LearningDsl
|
||||||
class TaskTestContext(rt: TaskRuntimeContext): TaskRuntimeContext(rt) {
|
class TaskTestContext(rt: TaskRuntimeContext): TaskRuntimeContext(rt) {
|
||||||
|
private val defaultTimeout = Timeout.timeout(3, TimeUnit.SECONDS)
|
||||||
|
|
||||||
|
val robot: Robot get() = LearningUiUtil.robot
|
||||||
|
|
||||||
data class TestScriptProperties (
|
data class TestScriptProperties (
|
||||||
val duration: Int = 6, //seconds
|
val duration: Int = 15, //seconds
|
||||||
val skipTesting: Boolean = false
|
val skipTesting: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
||||||
fun type(text: String) {
|
fun type(text: String) {
|
||||||
GuiTestUtil.typeText(text)
|
robot.waitForIdle()
|
||||||
|
for (element in text) {
|
||||||
|
robot.type(element)
|
||||||
|
Pause.pause(10, TimeUnit.MILLISECONDS)
|
||||||
|
}
|
||||||
|
Pause.pause(300, TimeUnit.MILLISECONDS)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun actions(vararg actionIds: String) {
|
fun actions(vararg actionIds: String) {
|
||||||
@@ -39,50 +62,274 @@ class TaskTestContext(rt: TaskRuntimeContext): TaskRuntimeContext(rt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ideFrame(action: IdeFrameFixture.() -> Unit) {
|
fun ideFrame(action: ContainerFixture<IdeFrameImpl>.() -> Unit) {
|
||||||
with(guiTestCase) {
|
with(findIdeFrame(robot, defaultTimeout)) {
|
||||||
ideFrame {
|
action()
|
||||||
// Note: It is not recursive call here. It is GuiTestCase#ideFrame
|
|
||||||
action()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <ComponentType : Component> waitComponent(componentClass: Class<ComponentType>, partOfName: String? = null) {
|
fun <ComponentType : Component> waitComponent(componentClass: Class<ComponentType>, partOfName: String? = null) {
|
||||||
waitUntilFound(null, componentClass, Timeouts.seconds02) {
|
LearningUiUtil.waitUntilFound(robot, null, typeMatcher(componentClass) {
|
||||||
(if (partOfName != null) it.javaClass.name.contains(partOfName) else true) && it.isShowing
|
(if (partOfName != null) it.javaClass.name.contains(partOfName)
|
||||||
|
else true) && it.isShowing
|
||||||
|
}, defaultTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a JList component in hierarchy of context component with a containingItem and returns JListFixture.
|
||||||
|
*
|
||||||
|
* @throws ComponentLookupException if component has not been found or timeout exceeded
|
||||||
|
*/
|
||||||
|
fun <C : Container> ContainerFixture<C>.jList(containingItem: String? = null, timeout: Timeout = defaultTimeout): JListFixture {
|
||||||
|
return generalListFinder(timeout, containingItem) { element, p -> element == p }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a JButton component in hierarchy of context component with a name and returns ExtendedButtonFixture.
|
||||||
|
*
|
||||||
|
* @throws ComponentLookupException if component has not been found or timeout exceeded
|
||||||
|
*/
|
||||||
|
fun <C : Container> ContainerFixture<C>.button(name: String, timeout: Timeout = defaultTimeout): JButtonFixture {
|
||||||
|
val jButton: JButton = findComponentWithTimeout(timeout) { it.isShowing && it.isVisible && it.text == name }
|
||||||
|
return JButtonFixture(robot(), jButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <C : Container> ContainerFixture<C>.actionButton(actionName: String, timeout: Timeout = defaultTimeout)
|
||||||
|
: AbstractComponentFixture<*, ActionButton, ComponentDriver<*>> {
|
||||||
|
val actionButton: ActionButton = findComponentWithTimeout(timeout) {
|
||||||
|
it.isShowing && it.isEnabled && actionName == it.action.templatePresentation.text
|
||||||
}
|
}
|
||||||
|
return ActionButtonFixture(robot(), actionButton)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modified copy-paste
|
// Modified copy-paste
|
||||||
fun <C : Container> ContainerFixture<C>.jListContains(partOfItem: String? = null, timeout: Timeout = Timeouts.seconds02): JListFixture {
|
fun <C : Container> ContainerFixture<C>.jListContains(partOfItem: String? = null, timeout: Timeout = defaultTimeout): JListFixture {
|
||||||
return step("search '$partOfItem' in list") {
|
return generalListFinder(timeout, partOfItem) { element, p -> element.contains(p) }
|
||||||
val extCellReader = ExtendedJListCellReader()
|
|
||||||
val myJList: JList<*> = findComponentWithTimeout(timeout) { jList: JList<*> ->
|
|
||||||
if (partOfItem == null) true //if were searching for any jList()
|
|
||||||
else {
|
|
||||||
val elements = (0 until jList.model.size).map { extCellReader.valueAt(jList, it) }
|
|
||||||
elements.any { it.toString().contains(partOfItem) } && jList.isShowing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val jListFixture = JListFixture(robot(), myJList)
|
|
||||||
jListFixture.replaceCellReader(extCellReader)
|
|
||||||
return@step jListFixture
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds JDialog with a specific title (if title is null showing dialog should be only one) and returns created JDialogFixture
|
||||||
|
*/
|
||||||
|
fun dialog(title: String? = null,
|
||||||
|
ignoreCaseTitle: Boolean = false,
|
||||||
|
predicate: (String, String) -> Boolean = { found: String, wanted: String -> found == wanted },
|
||||||
|
timeout: Timeout = defaultTimeout,
|
||||||
|
func: ContainerFixture<JDialog>.() -> Unit = {})
|
||||||
|
: AbstractComponentFixture<*, JDialog, ComponentDriver<*>> {
|
||||||
|
val jDialogFixture = if (title == null) {
|
||||||
|
val jDialog = LearningUiUtil.waitUntilFound(robot, null, typeMatcher(JDialog::class.java) { true }, timeout)
|
||||||
|
JDialogFixture(robot, jDialog)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
val dialog = withPauseWhenNull(timeout = timeout) {
|
||||||
|
val allMatchedDialogs = robot.finder().findAll(typeMatcher(JDialog::class.java) {
|
||||||
|
it.isFocused &&
|
||||||
|
if (ignoreCaseTitle) predicate(it.title.toLowerCase(), title.toLowerCase()) else predicate(it.title, title)
|
||||||
|
}).filter { it.isShowing && it.isEnabled && it.isVisible }
|
||||||
|
if (allMatchedDialogs.size > 1) throw Exception(
|
||||||
|
"Found more than one (${allMatchedDialogs.size}) dialogs matched title \"$title\"")
|
||||||
|
allMatchedDialogs.firstOrNull()
|
||||||
|
}
|
||||||
|
JDialogFixture(robot, dialog)
|
||||||
|
}
|
||||||
|
catch (timeoutError: WaitTimedOutError) {
|
||||||
|
throw ComponentLookupException("Timeout error for finding JDialog by title \"$title\" for ${timeout.duration()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func(jDialogFixture)
|
||||||
|
return jDialogFixture
|
||||||
|
}
|
||||||
|
|
||||||
class SimpleComponentFixture(robot: Robot, target: Component): ComponentFixture<SimpleComponentFixture, Component>(
|
fun ContainerFixture<*>.jComponent(target: Component): AbstractComponentFixture<*, Component, ComponentDriver<*>> {
|
||||||
SimpleComponentFixture::class.java, robot, target)
|
|
||||||
|
|
||||||
fun IdeFrameFixture.jComponent(target: Component): SimpleComponentFixture {
|
|
||||||
return SimpleComponentFixture(robot(), target)
|
return SimpleComponentFixture(robot(), target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun invokeActionViaShortcut(shortcut: String) {
|
||||||
|
val keyStroke = KeyStrokeAdapter.getKeyStroke(shortcut)
|
||||||
|
robot.pressAndReleaseKey(keyStroke.keyCode, keyStroke.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Volatile
|
@Volatile
|
||||||
var inTestMode: Boolean = false
|
var inTestMode: Boolean = false
|
||||||
|
}
|
||||||
|
|
||||||
val guiTestCase: GuiTestCase by lazy { GuiTestCase() }
|
////////////------------------------------
|
||||||
|
private fun <C : Container> ContainerFixture<C>.generalListFinder(timeout: Timeout,
|
||||||
|
containingItem: String?,
|
||||||
|
predicate: (String, String) -> Boolean): JListFixture {
|
||||||
|
val extCellReader = ExtendedJListCellReader()
|
||||||
|
val myJList: JList<*> = findComponentWithTimeout(timeout) { jList: JList<*> ->
|
||||||
|
if (containingItem == null) true //if were searching for any jList()
|
||||||
|
else {
|
||||||
|
val elements = (0 until jList.model.size).mapNotNull { extCellReader.valueAt(jList, it) }
|
||||||
|
elements.any { predicate(it, containingItem) } && jList.isShowing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jListFixture = JListFixture(robot(), myJList)
|
||||||
|
jListFixture.replaceCellReader(extCellReader)
|
||||||
|
return jListFixture
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* waits for [timeout] when functionProbeToNull() not return null
|
||||||
|
*
|
||||||
|
* @throws WaitTimedOutError with the text: "Timed out waiting for $timeout second(s) until {@code conditionText} will be not null"
|
||||||
|
*/
|
||||||
|
private fun <ReturnType> withPauseWhenNull(conditionText: String = "function to probe",
|
||||||
|
timeout: Timeout = defaultTimeout,
|
||||||
|
functionProbeToNull: () -> ReturnType?): ReturnType {
|
||||||
|
var result: ReturnType? = null
|
||||||
|
waitUntil("$conditionText will be not null", timeout) {
|
||||||
|
result = functionProbeToNull()
|
||||||
|
result != null
|
||||||
|
}
|
||||||
|
return result!!
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun waitUntil(condition: String, timeout: Timeout = defaultTimeout, conditionalFunction: () -> Boolean) {
|
||||||
|
Pause.pause(object : Condition("${timeout.duration()} until $condition") {
|
||||||
|
override fun test() = conditionalFunction()
|
||||||
|
}, timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class SimpleComponentFixture(robot: Robot, target: Component) :
|
||||||
|
ComponentFixture<SimpleComponentFixture, Component>(SimpleComponentFixture::class.java, robot, target)
|
||||||
|
|
||||||
|
|
||||||
|
private fun <ComponentType : Component?> typeMatcher(componentTypeClass: Class<ComponentType>,
|
||||||
|
matcher: (ComponentType) -> Boolean): GenericTypeMatcher<ComponentType> {
|
||||||
|
return object : GenericTypeMatcher<ComponentType>(componentTypeClass) {
|
||||||
|
override fun isMatching(component: ComponentType): Boolean = matcher(component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getValueWithCellRenderer(cellRendererComponent: Component, isExtended: Boolean = true): String? {
|
||||||
|
val result = when (cellRendererComponent) {
|
||||||
|
is JLabel -> cellRendererComponent.text
|
||||||
|
is NodeRenderer -> {
|
||||||
|
if (isExtended) cellRendererComponent.getFullText()
|
||||||
|
else cellRendererComponent.getFirstText()
|
||||||
|
} //should stands before SimpleColoredComponent because it is more specific
|
||||||
|
is SimpleColoredComponent -> cellRendererComponent.getFullText()
|
||||||
|
is MultilineTreeCellRenderer -> cellRendererComponent.text
|
||||||
|
else -> cellRendererComponent.findText()
|
||||||
|
}
|
||||||
|
return result?.trimEnd()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class ExtendedJListCellReader : BasicJListCellReader() {
|
||||||
|
override fun valueAt(list: JList<*>, index: Int): String? {
|
||||||
|
val element = list.model.getElementAt(index) ?: return null
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val cellRendererComponent = (list as JList<Any>).cellRenderer
|
||||||
|
.getListCellRendererComponent(list, element, index, true, true)
|
||||||
|
return getValueWithCellRenderer(cellRendererComponent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SimpleColoredComponent.getFullText(): String {
|
||||||
|
return invokeAndWaitIfNeeded {
|
||||||
|
this.getCharSequence(false).toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun SimpleColoredComponent.getFirstText(): String {
|
||||||
|
return invokeAndWaitIfNeeded {
|
||||||
|
this.getCharSequence(true).toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Component.findText(): String? {
|
||||||
|
try {
|
||||||
|
assert(this is Container)
|
||||||
|
val container = this as Container
|
||||||
|
val resultList = ArrayList<String>()
|
||||||
|
resultList.addAll(
|
||||||
|
findAllWithBFS(container, JLabel::class.java)
|
||||||
|
.asSequence()
|
||||||
|
.filter { !it.text.isNullOrEmpty() }
|
||||||
|
.map { it.text }
|
||||||
|
.toList()
|
||||||
|
)
|
||||||
|
resultList.addAll(
|
||||||
|
findAllWithBFS(container, SimpleColoredComponent::class.java)
|
||||||
|
.asSequence()
|
||||||
|
.filter {
|
||||||
|
it.getFullText().isNotEmpty()
|
||||||
|
}
|
||||||
|
.map {
|
||||||
|
it.getFullText()
|
||||||
|
}
|
||||||
|
.toList()
|
||||||
|
)
|
||||||
|
return resultList.firstOrNull { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
catch (ignored: ComponentLookupException) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <ComponentType : Component> findAllWithBFS(container: Container, clazz: Class<ComponentType>): List<ComponentType> {
|
||||||
|
val result = LinkedList<ComponentType>()
|
||||||
|
val queue: Queue<Component> = LinkedList()
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun check(container: Component) {
|
||||||
|
if (clazz.isInstance(container)) result.add(container as ComponentType)
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.add(container)
|
||||||
|
while (queue.isNotEmpty()) {
|
||||||
|
val polled = queue.poll()
|
||||||
|
check(polled)
|
||||||
|
if (polled is Container)
|
||||||
|
queue.addAll(polled.components)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private open class ComponentFixture<S, C : Component>(selfType: Class<S>, robot: Robot, target: C)
|
||||||
|
: AbstractComponentFixture<S, C, ComponentDriver<*>>(selfType, robot, target) {
|
||||||
|
|
||||||
|
override fun createDriver(robot: Robot): ComponentDriver<*> {
|
||||||
|
return ComponentDriver<Component>(robot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ActionButtonFixture(robot: Robot, target: ActionButton):
|
||||||
|
ComponentFixture<ActionButtonFixture, ActionButton>(ActionButtonFixture::class.java, robot, target), ContainerFixture<ActionButton>
|
||||||
|
|
||||||
|
private class IdeFrameFixture(robot: Robot, target: IdeFrameImpl)
|
||||||
|
: ComponentFixture<IdeFrameFixture, IdeFrameImpl>(IdeFrameFixture::class.java, robot, target), ContainerFixture<IdeFrameImpl>
|
||||||
|
|
||||||
|
private class JDialogFixture(robot: Robot, jDialog: JDialog) :
|
||||||
|
ComponentFixture<JDialogFixture, JDialog>(JDialogFixture::class.java, robot, jDialog), ContainerFixture<JDialog>
|
||||||
|
|
||||||
|
private fun findIdeFrame(robot: Robot, timeout: Timeout): IdeFrameFixture {
|
||||||
|
val matcher: GenericTypeMatcher<IdeFrameImpl> = object : GenericTypeMatcher<IdeFrameImpl>(
|
||||||
|
IdeFrameImpl::class.java) {
|
||||||
|
override fun isMatching(frame: IdeFrameImpl): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return try {
|
||||||
|
Pause.pause(object : Condition("IdeFrame to show up") {
|
||||||
|
override fun test(): Boolean {
|
||||||
|
return !robot.finder().findAll(matcher).isEmpty()
|
||||||
|
}
|
||||||
|
}, timeout)
|
||||||
|
val ideFrame = robot.finder().find(matcher)
|
||||||
|
IdeFrameFixture(robot, ideFrame)
|
||||||
|
}
|
||||||
|
catch (timedOutError: WaitTimedOutError) {
|
||||||
|
throw ComponentLookupException("Unable to find IdeFrame in " + timeout.duration())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ class LessonExecutor(val lesson: KLesson, val project: Project, initialEditor: E
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processTestActions(taskContext: TaskContextImpl) {
|
private fun processTestActions(taskContext: TaskContextImpl) {
|
||||||
if (TaskTestContext.inTestMode) {
|
if (TaskTestContext.inTestMode && taskContext.testActions.isNotEmpty()) {
|
||||||
LessonManager.instance.testActionsExecutor.execute {
|
LessonManager.instance.testActionsExecutor.execute {
|
||||||
taskContext.testActions.forEach { it.run() }
|
taskContext.testActions.forEach { it.run() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import com.intellij.util.Alarm
|
|||||||
import training.dsl.LearningBalloonConfig
|
import training.dsl.LearningBalloonConfig
|
||||||
import training.dsl.TaskContext
|
import training.dsl.TaskContext
|
||||||
import training.dsl.TaskRuntimeContext
|
import training.dsl.TaskRuntimeContext
|
||||||
import training.dsl.TaskTestContext
|
|
||||||
import training.learn.ActionsRecorder
|
import training.learn.ActionsRecorder
|
||||||
import training.learn.LearnBundle
|
import training.learn.LearnBundle
|
||||||
import training.learn.lesson.LessonManager
|
import training.learn.lesson.LessonManager
|
||||||
@@ -189,8 +188,6 @@ private class ExtractTaskPropertiesContext(override val project: Project) : Task
|
|||||||
hasDetection = true
|
hasDetection = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun test(action: TaskTestContext.() -> Unit) = Unit // do nothing
|
|
||||||
|
|
||||||
override fun action(actionId: String): String = "" //Doesn't matter what to return
|
override fun action(actionId: String): String = "" //Doesn't matter what to return
|
||||||
|
|
||||||
override fun code(sourceSample: String): String = "" //Doesn't matter what to return
|
override fun code(sourceSample: String): String = "" //Doesn't matter what to return
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package training.dsl.impl
|
package training.dsl.impl
|
||||||
|
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx
|
||||||
import com.intellij.openapi.application.ModalityState
|
import com.intellij.openapi.application.*
|
||||||
import com.intellij.openapi.application.WriteAction
|
|
||||||
import com.intellij.openapi.application.invokeLater
|
|
||||||
import com.intellij.openapi.command.WriteCommandAction
|
import com.intellij.openapi.command.WriteCommandAction
|
||||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||||
@@ -222,9 +220,21 @@ internal class TaskContextImpl(private val lessonExecutor: LessonExecutor,
|
|||||||
steps.add(step)
|
steps.add(step)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun test(action: TaskTestContext.() -> Unit) {
|
override fun test(waitEditorToBeReady: Boolean, action: TaskTestContext.() -> Unit) {
|
||||||
testActions.add(Runnable {
|
testActions.add(Runnable {
|
||||||
DumbService.getInstance(runtimeContext.project).waitForSmartMode()
|
DumbService.getInstance(runtimeContext.project).waitForSmartMode()
|
||||||
|
// This wait implementation is quite ugly, but it works and it is needed in the test mode only. So should be ok for now.
|
||||||
|
if (waitEditorToBeReady) {
|
||||||
|
val psiFile = invokeAndWaitIfNeeded { PsiDocumentManager.getInstance(project).getPsiFile(runtimeContext.editor.document) } ?: return@Runnable
|
||||||
|
var t = 0
|
||||||
|
val step = 100
|
||||||
|
while (!runReadAction { DaemonCodeAnalyzerEx.getInstanceEx(project).isErrorAnalyzingFinished(psiFile) }) {
|
||||||
|
Thread.sleep(step.toLong())
|
||||||
|
t += step
|
||||||
|
if (t > 3000) return@Runnable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TaskTestContext(runtimeContext).action()
|
TaskTestContext(runtimeContext).action()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,13 @@ import com.intellij.openapi.editor.actions.ToggleShowLineNumbersGloballyAction
|
|||||||
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
|
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
|
||||||
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
||||||
import com.intellij.openapi.util.SystemInfo
|
import com.intellij.openapi.util.SystemInfo
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.impl.jList
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.util.ui.UIUtil
|
import com.intellij.util.ui.UIUtil
|
||||||
|
import org.fest.swing.driver.ComponentDriver
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
import training.learn.LearnBundle
|
import training.learn.LearnBundle
|
||||||
import training.learn.LessonsBundle
|
import training.learn.LessonsBundle
|
||||||
import training.learn.course.KLesson
|
import training.learn.course.KLesson
|
||||||
|
import java.awt.Component
|
||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
import javax.swing.JPanel
|
import javax.swing.JPanel
|
||||||
|
|
||||||
@@ -64,8 +63,8 @@ class GotoActionLesson(private val sample: LessonSample, private val firstLesson
|
|||||||
// Note 1: it is editor from test IDE fixture
|
// Note 1: it is editor from test IDE fixture
|
||||||
// Note 2: In order to pass this task without interference with later task I need to firstly focus lesson
|
// Note 2: In order to pass this task without interference with later task I need to firstly focus lesson
|
||||||
// and only then press Escape
|
// and only then press Escape
|
||||||
editor.requestFocus()
|
ComponentDriver<Component>(robot).focusAndWaitForFocusGain(editor.contentComponent)
|
||||||
GuiTestUtil.shortcut(Key.ESCAPE)
|
invokeActionViaShortcut("ESCAPE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ package training.learn.lesson.general.assistance
|
|||||||
import com.intellij.codeInsight.CodeInsightBundle
|
import com.intellij.codeInsight.CodeInsightBundle
|
||||||
import com.intellij.ide.util.PropertiesComponent
|
import com.intellij.ide.util.PropertiesComponent
|
||||||
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
||||||
import com.intellij.testGuiFramework.impl.button
|
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.LessonSample
|
import training.dsl.LessonSample
|
||||||
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
||||||
@@ -59,7 +58,7 @@ class CodeFormatLesson(private val sample: LessonSample, private val optimizeImp
|
|||||||
restoreAfterStateBecomeFalse {
|
restoreAfterStateBecomeFalse {
|
||||||
focusOwner is EditorComponentImpl
|
focusOwner is EditorComponentImpl
|
||||||
}
|
}
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
properties.setValue("LayoutCode.optimizeImports", true)
|
properties.setValue("LayoutCode.optimizeImports", true)
|
||||||
ideFrame {
|
ideFrame {
|
||||||
button("Run").click()
|
button("Run").click()
|
||||||
|
|||||||
@@ -2,11 +2,6 @@
|
|||||||
package training.learn.lesson.general.assistance
|
package training.learn.lesson.general.assistance
|
||||||
|
|
||||||
import com.intellij.ide.IdeBundle
|
import com.intellij.ide.IdeBundle
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.impl.jList
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.testGuiFramework.util.Modifier
|
|
||||||
import com.intellij.testGuiFramework.util.Shortcut
|
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
||||||
import training.learn.LessonsBundle
|
import training.learn.LessonsBundle
|
||||||
@@ -59,9 +54,8 @@ abstract class EditorCodingAssistanceLesson(private val sample: LessonSample) :
|
|||||||
restoreIfModifiedOrMoved()
|
restoreIfModifiedOrMoved()
|
||||||
test {
|
test {
|
||||||
Thread.sleep(500)
|
Thread.sleep(500)
|
||||||
val errorDescriptionShortcut = Shortcut(hashSetOf(Modifier.CONTROL), Key.F1)
|
invokeActionViaShortcut("CONTROL F1")
|
||||||
GuiTestUtil.shortcut(errorDescriptionShortcut)
|
invokeActionViaShortcut("CONTROL F1")
|
||||||
GuiTestUtil.shortcut(errorDescriptionShortcut)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ package training.learn.lesson.general.assistance
|
|||||||
import com.intellij.codeInsight.documentation.DocumentationComponent
|
import com.intellij.codeInsight.documentation.DocumentationComponent
|
||||||
import com.intellij.codeInsight.documentation.QuickDocUtil
|
import com.intellij.codeInsight.documentation.QuickDocUtil
|
||||||
import com.intellij.codeInsight.hint.ImplementationViewComponent
|
import com.intellij.codeInsight.hint.ImplementationViewComponent
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.LessonSample
|
import training.dsl.LessonSample
|
||||||
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
||||||
@@ -31,7 +29,7 @@ class QuickPopupsLesson(private val sample: LessonSample) :
|
|||||||
stateCheck { checkDocComponentClosed() }
|
stateCheck { checkDocComponentClosed() }
|
||||||
restoreIfModifiedOrMoved()
|
restoreIfModifiedOrMoved()
|
||||||
test {
|
test {
|
||||||
GuiTestUtil.shortcut(Key.ESCAPE)
|
invokeActionViaShortcut("ESCAPE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package training.learn.lesson.general.completion
|
package training.learn.lesson.general.completion
|
||||||
|
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.LessonSample
|
import training.dsl.LessonSample
|
||||||
import training.dsl.LessonUtil
|
import training.dsl.LessonUtil
|
||||||
@@ -46,7 +44,7 @@ abstract class BasicCompletionLessonBase : KLesson("Basic completion", LessonsBu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
test {
|
test {
|
||||||
GuiTestUtil.typeText(item1StartToType)
|
type(item1StartToType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
task("EditorChooseLookupItem") {
|
task("EditorChooseLookupItem") {
|
||||||
@@ -59,8 +57,8 @@ abstract class BasicCompletionLessonBase : KLesson("Basic completion", LessonsBu
|
|||||||
!isTheFirstVariant(ui)
|
!isTheFirstVariant(ui)
|
||||||
} ?: true
|
} ?: true
|
||||||
}
|
}
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
GuiTestUtil.shortcut(Key.ENTER)
|
invokeActionViaShortcut("ENTER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waitBeforeContinue(500)
|
waitBeforeContinue(500)
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ import com.intellij.openapi.wm.impl.content.BaseLabel
|
|||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil.shortcut
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.ui.UIBundle
|
import com.intellij.ui.UIBundle
|
||||||
import com.intellij.ui.table.JBTable
|
import com.intellij.ui.table.JBTable
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
@@ -56,7 +54,7 @@ abstract class DeclarationAndUsagesLesson
|
|||||||
actions(it)
|
actions(it)
|
||||||
ideFrame {
|
ideFrame {
|
||||||
waitComponent(JBTable::class.java, "ShowUsagesTable")
|
waitComponent(JBTable::class.java, "ShowUsagesTable")
|
||||||
shortcut(Key.ENTER)
|
invokeActionViaShortcut("ENTER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ package training.learn.lesson.general.navigation
|
|||||||
import com.intellij.ide.dnd.aware.DnDAwareTree
|
import com.intellij.ide.dnd.aware.DnDAwareTree
|
||||||
import com.intellij.openapi.editor.LogicalPosition
|
import com.intellij.openapi.editor.LogicalPosition
|
||||||
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.ui.speedSearch.SpeedSearchSupply
|
import com.intellij.ui.speedSearch.SpeedSearchSupply
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.LessonUtil
|
import training.dsl.LessonUtil
|
||||||
@@ -48,7 +46,7 @@ abstract class FileStructureLesson
|
|||||||
text(LessonsBundle.message("file.structure.navigate", LessonUtil.rawEnter()))
|
text(LessonsBundle.message("file.structure.navigate", LessonUtil.rawEnter()))
|
||||||
stateCheck { editor.caretModel.logicalPosition == methodToFindPosition }
|
stateCheck { editor.caretModel.logicalPosition == methodToFindPosition }
|
||||||
restoreState { !checkWordInSearch(searchSubstring) }
|
restoreState { !checkWordInSearch(searchSubstring) }
|
||||||
test { GuiTestUtil.shortcut(Key.ENTER) }
|
test { invokeActionViaShortcut("ENTER") }
|
||||||
}
|
}
|
||||||
task("ActivateStructureToolWindow") {
|
task("ActivateStructureToolWindow") {
|
||||||
text(LessonsBundle.message("file.structure.toolwindow", action(it)))
|
text(LessonsBundle.message("file.structure.toolwindow", action(it)))
|
||||||
|
|||||||
@@ -9,20 +9,16 @@ import com.intellij.find.impl.FindInProjectSettingsBase
|
|||||||
import com.intellij.find.impl.FindPopupPanel
|
import com.intellij.find.impl.FindPopupPanel
|
||||||
import com.intellij.icons.AllIcons
|
import com.intellij.icons.AllIcons
|
||||||
import com.intellij.openapi.actionSystem.impl.ActionButton
|
import com.intellij.openapi.actionSystem.impl.ActionButton
|
||||||
import com.intellij.testGuiFramework.fixtures.extended.ExtendedTableFixture
|
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.impl.actionButton
|
|
||||||
import com.intellij.testGuiFramework.impl.button
|
|
||||||
import com.intellij.testGuiFramework.impl.findComponentWithTimeout
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.usages.UsagePresentation
|
import com.intellij.usages.UsagePresentation
|
||||||
import com.intellij.util.ui.UIUtil
|
import com.intellij.util.ui.UIUtil
|
||||||
import org.fest.swing.core.MouseClickInfo
|
import org.fest.swing.core.MouseClickInfo
|
||||||
import org.fest.swing.data.TableCell
|
import org.fest.swing.data.TableCell
|
||||||
|
import org.fest.swing.fixture.JTableFixture
|
||||||
import org.fest.swing.fixture.JTextComponentFixture
|
import org.fest.swing.fixture.JTextComponentFixture
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
import training.learn.LessonsBundle
|
import training.learn.LessonsBundle
|
||||||
import training.learn.course.KLesson
|
import training.learn.course.KLesson
|
||||||
|
import training.ui.LearningUiUtil.findComponentWithTimeout
|
||||||
import java.awt.event.InputEvent
|
import java.awt.event.InputEvent
|
||||||
import java.awt.event.KeyEvent
|
import java.awt.event.KeyEvent
|
||||||
import javax.swing.*
|
import javax.swing.*
|
||||||
@@ -42,7 +38,6 @@ class FindInFilesLesson(override val existedFile: String)
|
|||||||
!popup.helper.isReplaceState
|
!popup.helper.isReplaceState
|
||||||
}
|
}
|
||||||
test {
|
test {
|
||||||
Thread.sleep(300)
|
|
||||||
actions(it)
|
actions(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,7 +56,7 @@ class FindInFilesLesson(override val existedFile: String)
|
|||||||
LessonUtil.rawKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.ALT_DOWN_MASK))))
|
LessonUtil.rawKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.ALT_DOWN_MASK))))
|
||||||
highlightAndTriggerWhenButtonSelected(wholeWordsButtonText)
|
highlightAndTriggerWhenButtonSelected(wholeWordsButtonText)
|
||||||
showWarningIfPopupClosed(false)
|
showWarningIfPopupClosed(false)
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
ideFrame {
|
ideFrame {
|
||||||
actionButton(wholeWordsButtonText).click()
|
actionButton(wholeWordsButtonText).click()
|
||||||
}
|
}
|
||||||
@@ -84,9 +79,8 @@ class FindInFilesLesson(override val existedFile: String)
|
|||||||
restoreByUi(restoreId = showPopupTaskId)
|
restoreByUi(restoreId = showPopupTaskId)
|
||||||
test {
|
test {
|
||||||
ideFrame {
|
ideFrame {
|
||||||
Thread.sleep(300)
|
|
||||||
val table = findComponentWithTimeout { table: JTable -> table.findLastRowIndexOfItemWithText(it) != -1 }
|
val table = findComponentWithTimeout { table: JTable -> table.findLastRowIndexOfItemWithText(it) != -1 }
|
||||||
val tableFixture = ExtendedTableFixture(robot(), table)
|
val tableFixture = JTableFixture(robot(), table)
|
||||||
val rowIndex = table.findLastRowIndexOfItemWithText(it)
|
val rowIndex = table.findLastRowIndexOfItemWithText(it)
|
||||||
tableFixture.click(TableCell.row(rowIndex).column(0), MouseClickInfo.leftButton())
|
tableFixture.click(TableCell.row(rowIndex).column(0), MouseClickInfo.leftButton())
|
||||||
}
|
}
|
||||||
@@ -97,7 +91,7 @@ class FindInFilesLesson(override val existedFile: String)
|
|||||||
text(LessonsBundle.message("find.in.files.go.to.file", LessonUtil.rawEnter()))
|
text(LessonsBundle.message("find.in.files.go.to.file", LessonUtil.rawEnter()))
|
||||||
stateCheck { virtualFile.name != existedFile.substringAfterLast('/') }
|
stateCheck { virtualFile.name != existedFile.substringAfterLast('/') }
|
||||||
restoreByUi(restoreId = showPopupTaskId)
|
restoreByUi(restoreId = showPopupTaskId)
|
||||||
test { GuiTestUtil.shortcut(Key.ENTER) }
|
test { invokeActionViaShortcut("ENTER") }
|
||||||
}
|
}
|
||||||
|
|
||||||
task("ReplaceInPath") {
|
task("ReplaceInPath") {
|
||||||
@@ -157,7 +151,6 @@ class FindInFilesLesson(override val existedFile: String)
|
|||||||
showWarningIfPopupClosed(true)
|
showWarningIfPopupClosed(true)
|
||||||
test {
|
test {
|
||||||
ideFrame {
|
ideFrame {
|
||||||
Thread.sleep(300)
|
|
||||||
button(replaceAllButtonText).click()
|
button(replaceAllButtonText).click()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,10 +161,9 @@ class FindInFilesLesson(override val existedFile: String)
|
|||||||
text(LessonsBundle.message("find.in.files.confirm.replace", strong(replaceButtonText)))
|
text(LessonsBundle.message("find.in.files.confirm.replace", strong(replaceButtonText)))
|
||||||
stateCheck { editor.document.charsSequence.contains("orange") }
|
stateCheck { editor.document.charsSequence.contains("orange") }
|
||||||
restoreByUi(delayMillis = defaultRestoreDelay)
|
restoreByUi(delayMillis = defaultRestoreDelay)
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
ideFrame {
|
dialog(title = "Replace All") {
|
||||||
Thread.sleep(300)
|
button(replaceButtonText).click()
|
||||||
findMessageDialog(replaceAllDialogTitle).click(replaceButtonText)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import com.intellij.openapi.application.invokeLater
|
|||||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||||
import com.intellij.openapi.ui.Messages
|
import com.intellij.openapi.ui.Messages
|
||||||
import com.intellij.openapi.wm.IdeFrame
|
import com.intellij.openapi.wm.IdeFrame
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.ui.SearchTextField
|
import com.intellij.ui.SearchTextField
|
||||||
import com.intellij.ui.components.JBList
|
import com.intellij.ui.components.JBList
|
||||||
import com.intellij.ui.components.fields.ExtendableTextField
|
import com.intellij.ui.components.fields.ExtendableTextField
|
||||||
@@ -89,7 +87,9 @@ abstract class RecentFilesLesson : KLesson("Recent Files and Locations", Lessons
|
|||||||
restoreState {
|
restoreState {
|
||||||
!checkRecentFilesSearch("rfd") || previous.ui?.isShowing != true
|
!checkRecentFilesSearch("rfd") || previous.ui?.isShowing != true
|
||||||
}
|
}
|
||||||
test { GuiTestUtil.shortcut(Key.ENTER) }
|
test(waitEditorToBeReady = false) {
|
||||||
|
invokeActionViaShortcut("ENTER")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionTask("RecentFiles") {
|
actionTask("RecentFiles") {
|
||||||
@@ -112,7 +112,7 @@ abstract class RecentFilesLesson : KLesson("Recent Files and Locations", Lessons
|
|||||||
restoreIfRecentFilesPopupClosed()
|
restoreIfRecentFilesPopupClosed()
|
||||||
test {
|
test {
|
||||||
repeat(countOfFilesToDelete) {
|
repeat(countOfFilesToDelete) {
|
||||||
GuiTestUtil.shortcut(Key.DELETE)
|
invokeActionViaShortcut("DELETE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ abstract class RecentFilesLesson : KLesson("Recent Files and Locations", Lessons
|
|||||||
task {
|
task {
|
||||||
text(LessonsBundle.message("recent.files.close.popup", LessonUtil.rawKeyStroke(KeyEvent.VK_ESCAPE)))
|
text(LessonsBundle.message("recent.files.close.popup", LessonUtil.rawKeyStroke(KeyEvent.VK_ESCAPE)))
|
||||||
stateCheck { focusOwner is IdeFrame }
|
stateCheck { focusOwner is IdeFrame }
|
||||||
test { GuiTestUtil.shortcut(Key.ESCAPE) }
|
test { invokeActionViaShortcut("ESCAPE") }
|
||||||
}
|
}
|
||||||
|
|
||||||
actionTask("RecentLocations") {
|
actionTask("RecentLocations") {
|
||||||
@@ -146,7 +146,7 @@ abstract class RecentFilesLesson : KLesson("Recent Files and Locations", Lessons
|
|||||||
restoreState {
|
restoreState {
|
||||||
!checkRecentLocationsSearch(stringForRecentFilesSearch) || previous.ui?.isShowing != true
|
!checkRecentLocationsSearch(stringForRecentFilesSearch) || previous.ui?.isShowing != true
|
||||||
}
|
}
|
||||||
test { GuiTestUtil.shortcut(Key.ENTER) }
|
test { invokeActionViaShortcut("ENTER") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,9 +188,7 @@ abstract class RecentFilesLesson : KLesson("Recent Files and Locations", Lessons
|
|||||||
private fun checkWordInSearch(expected: String, component: JComponent): Boolean {
|
private fun checkWordInSearch(expected: String, component: JComponent): Boolean {
|
||||||
val supply = SpeedSearchSupply.getSupply(component)
|
val supply = SpeedSearchSupply.getSupply(component)
|
||||||
val enteredPrefix = supply?.enteredPrefix ?: return false
|
val enteredPrefix = supply?.enteredPrefix ?: return false
|
||||||
val equals = enteredPrefix.equals(expected, ignoreCase = true)
|
return enteredPrefix.equals(expected, ignoreCase = true)
|
||||||
System.err.println("expected = '$expected', enteredPrefix = '$enteredPrefix', equals = $equals")
|
|
||||||
return equals
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TaskContext.restoreIfRecentFilesPopupClosed() {
|
private fun TaskContext.restoreIfRecentFilesPopupClosed() {
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ import com.intellij.openapi.editor.impl.EditorComponentImpl
|
|||||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||||
import com.intellij.psi.search.EverythingGlobalScope
|
import com.intellij.psi.search.EverythingGlobalScope
|
||||||
import com.intellij.psi.search.ProjectScope
|
import com.intellij.psi.search.ProjectScope
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.testGuiFramework.util.Modifier
|
|
||||||
import com.intellij.testGuiFramework.util.Shortcut
|
|
||||||
import com.intellij.ui.components.fields.ExtendableTextField
|
import com.intellij.ui.components.fields.ExtendableTextField
|
||||||
import com.intellij.util.ui.UIUtil
|
import com.intellij.util.ui.UIUtil
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
@@ -52,7 +48,7 @@ abstract class SearchEverywhereLesson : KLesson("Search everywhere", LessonsBund
|
|||||||
!checkInsideSearchEverywhere()
|
!checkInsideSearchEverywhere()
|
||||||
}
|
}
|
||||||
test {
|
test {
|
||||||
GuiTestUtil.shortcut(Key.ENTER)
|
invokeActionViaShortcut("ENTER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +75,7 @@ abstract class SearchEverywhereLesson : KLesson("Search everywhere", LessonsBund
|
|||||||
!checkInsideSearchEverywhere() && focusOwner !is JList<*>
|
!checkInsideSearchEverywhere() && focusOwner !is JList<*>
|
||||||
}
|
}
|
||||||
test {
|
test {
|
||||||
GuiTestUtil.shortcut(Shortcut(HashSet(setOf(Modifier.ALT)), Key.P))
|
invokeActionViaShortcut("ALT P")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +89,7 @@ abstract class SearchEverywhereLesson : KLesson("Search everywhere", LessonsBund
|
|||||||
task {
|
task {
|
||||||
text(LessonsBundle.message("search.everywhere.close.documentation.popup", LessonUtil.rawKeyStroke(KeyEvent.VK_ESCAPE)))
|
text(LessonsBundle.message("search.everywhere.close.documentation.popup", LessonUtil.rawKeyStroke(KeyEvent.VK_ESCAPE)))
|
||||||
stateCheck { previous.ui?.isShowing != true }
|
stateCheck { previous.ui?.isShowing != true }
|
||||||
test { GuiTestUtil.shortcut(Key.ESCAPE) }
|
test { invokeActionViaShortcut("ENTER") }
|
||||||
}
|
}
|
||||||
|
|
||||||
task {
|
task {
|
||||||
@@ -103,8 +99,8 @@ abstract class SearchEverywhereLesson : KLesson("Search everywhere", LessonsBund
|
|||||||
if (TaskTestContext.inTestMode) task {
|
if (TaskTestContext.inTestMode) task {
|
||||||
stateCheck { focusOwner is EditorComponentImpl }
|
stateCheck { focusOwner is EditorComponentImpl }
|
||||||
test {
|
test {
|
||||||
GuiTestUtil.shortcut(Key.ESCAPE)
|
invokeActionViaShortcut("ESCAPE")
|
||||||
GuiTestUtil.shortcut(Key.ESCAPE)
|
invokeActionViaShortcut("ESCAPE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package training.learn.lesson.general.refactorings
|
|||||||
|
|
||||||
import com.intellij.CommonBundle
|
import com.intellij.CommonBundle
|
||||||
import com.intellij.refactoring.RefactoringBundle
|
import com.intellij.refactoring.RefactoringBundle
|
||||||
import com.intellij.testGuiFramework.impl.button
|
|
||||||
import com.intellij.ui.UIBundle
|
import com.intellij.ui.UIBundle
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
||||||
@@ -43,11 +42,9 @@ class ExtractMethodCocktailSortLesson(private val sample: LessonSample)
|
|||||||
}
|
}
|
||||||
|
|
||||||
restoreByUi(delayMillis = defaultRestoreDelay)
|
restoreByUi(delayMillis = defaultRestoreDelay)
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
with(TaskTestContext.guiTestCase) {
|
dialog(extractMethodDialogTitle) {
|
||||||
dialog(extractMethodDialogTitle, needToKeepDialog = true) {
|
button(okButtonText).click()
|
||||||
button(okButtonText).click()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,11 +58,9 @@ class ExtractMethodCocktailSortLesson(private val sample: LessonSample)
|
|||||||
}
|
}
|
||||||
|
|
||||||
restoreByUi(restoreId = startTaskId, delayMillis = defaultRestoreDelay)
|
restoreByUi(restoreId = startTaskId, delayMillis = defaultRestoreDelay)
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
with(TaskTestContext.guiTestCase) {
|
dialog(extractMethodDialogTitle) {
|
||||||
dialog(extractMethodDialogTitle) {
|
button(yesButtonText).click()
|
||||||
button(yesButtonText).click()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,11 +71,9 @@ class ExtractMethodCocktailSortLesson(private val sample: LessonSample)
|
|||||||
previous.ui?.isShowing?.not() ?: true
|
previous.ui?.isShowing?.not() ?: true
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
with(TaskTestContext.guiTestCase) {
|
dialog(replaceFragmentDialogTitle) {
|
||||||
dialog(replaceFragmentDialogTitle) {
|
button(UIBundle.message("replace.prompt.replace.button").dropMnemonic()).click()
|
||||||
button(UIBundle.message("replace.prompt.replace.button").dropMnemonic()).click()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package training.learn.lesson.general.refactorings
|
package training.learn.lesson.general.refactorings
|
||||||
|
|
||||||
import com.intellij.testGuiFramework.impl.jList
|
|
||||||
import com.intellij.ui.components.JBList
|
import com.intellij.ui.components.JBList
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.LessonSample
|
import training.dsl.LessonSample
|
||||||
@@ -40,9 +39,13 @@ class ExtractVariableFromBubbleLesson(private val sample: LessonSample)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionTask("NextTemplateVariable") {
|
task("NextTemplateVariable") {
|
||||||
//TODO: fix the shortcut: it should be ${action(it)} but with preference for Enter
|
//TODO: fix the shortcut: it should be ${action(it)} but with preference for Enter
|
||||||
LessonsBundle.message("extract.variable.choose.name", LessonUtil.rawEnter())
|
text(LessonsBundle.message("extract.variable.choose.name", LessonUtil.rawEnter()))
|
||||||
|
trigger(it)
|
||||||
|
test(waitEditorToBeReady = false) {
|
||||||
|
actions(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package training.learn.lesson.general.refactorings
|
|||||||
|
|
||||||
import com.intellij.idea.ActionsBundle
|
import com.intellij.idea.ActionsBundle
|
||||||
import com.intellij.refactoring.rename.inplace.InplaceRefactoring
|
import com.intellij.refactoring.rename.inplace.InplaceRefactoring
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.ui.components.JBList
|
import com.intellij.ui.components.JBList
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
import training.dsl.LessonUtil.restoreIfModifiedOrMoved
|
||||||
@@ -38,7 +36,7 @@ abstract class RefactoringMenuLessonBase(lessonId: String) : KLesson(lessonId, L
|
|||||||
stateCheck { hasInplaceRename() }
|
stateCheck { hasInplaceRename() }
|
||||||
restoreState(delayMillis = defaultRestoreDelay, restoreId = showPopupTaskId) { focusOwner !is JBList<*> }
|
restoreState(delayMillis = defaultRestoreDelay, restoreId = showPopupTaskId) { focusOwner !is JBList<*> }
|
||||||
test {
|
test {
|
||||||
GuiTestUtil.shortcut(Key.ENTER)
|
invokeActionViaShortcut("ENTER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,8 +45,8 @@ abstract class RefactoringMenuLessonBase(lessonId: String) : KLesson(lessonId, L
|
|||||||
stateCheck {
|
stateCheck {
|
||||||
!hasInplaceRename()
|
!hasInplaceRename()
|
||||||
}
|
}
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
GuiTestUtil.shortcut(Key.ENTER)
|
invokeActionViaShortcut("ENTER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ import com.intellij.openapi.editor.impl.EditorComponentImpl
|
|||||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.tasks.TaskBundle
|
import com.intellij.tasks.TaskBundle
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.util.ui.UIUtil
|
import com.intellij.util.ui.UIUtil
|
||||||
import com.intellij.xdebugger.*
|
import com.intellij.xdebugger.*
|
||||||
import com.intellij.xdebugger.impl.XDebugSessionImpl
|
import com.intellij.xdebugger.impl.XDebugSessionImpl
|
||||||
@@ -196,7 +194,7 @@ abstract class CommonDebugLesson(id: String) : KLesson(id, LessonsBundle.message
|
|||||||
proposeModificationRestore(sample.text)
|
proposeModificationRestore(sample.text)
|
||||||
test {
|
test {
|
||||||
Thread.sleep(500)
|
Thread.sleep(500)
|
||||||
GuiTestUtil.shortcut(Key.ESCAPE)
|
invokeActionViaShortcut("ESCAPE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,8 +247,8 @@ abstract class CommonDebugLesson(id: String) : KLesson(id, LessonsBundle.message
|
|||||||
proposeModificationRestore(sample.text)
|
proposeModificationRestore(sample.text)
|
||||||
test {
|
test {
|
||||||
Thread.sleep(500)
|
Thread.sleep(500)
|
||||||
GuiTestUtil.shortcut(if (stepIntoDirection == "→") Key.RIGHT else Key.LEFT)
|
invokeActionViaShortcut(if (stepIntoDirection == "→") "RIGHT" else "LEFT")
|
||||||
GuiTestUtil.shortcut(Key.ENTER)
|
invokeActionViaShortcut("ENTER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,7 +284,7 @@ abstract class CommonDebugLesson(id: String) : KLesson(id, LessonsBundle.message
|
|||||||
else checkForBreakpoints()
|
else checkForBreakpoints()
|
||||||
}
|
}
|
||||||
test {
|
test {
|
||||||
GuiTestUtil.shortcut(Key.ESCAPE)
|
invokeActionViaShortcut("ESCAPE")
|
||||||
invokeLater {
|
invokeLater {
|
||||||
WriteCommandAction.runWriteCommandAction(project) {
|
WriteCommandAction.runWriteCommandAction(project) {
|
||||||
val offset = sample.text.indexOf("[0]")
|
val offset = sample.text.indexOf("[0]")
|
||||||
@@ -356,6 +354,9 @@ abstract class CommonDebugLesson(id: String) : KLesson(id, LessonsBundle.message
|
|||||||
}
|
}
|
||||||
|
|
||||||
task(expressionToBeEvaluated) {
|
task(expressionToBeEvaluated) {
|
||||||
|
before {
|
||||||
|
LearningUiHighlightingManager.clearHighlights()
|
||||||
|
}
|
||||||
text(LessonsBundle.message("debug.workflow.type.result", code(it),
|
text(LessonsBundle.message("debug.workflow.type.result", code(it),
|
||||||
strong(XDebuggerBundle.message("xdebugger.evaluate.label.expression"))))
|
strong(XDebuggerBundle.message("xdebugger.evaluate.label.expression"))))
|
||||||
stateCheck { checkWordInTextField(it) }
|
stateCheck { checkWordInTextField(it) }
|
||||||
@@ -377,7 +378,10 @@ abstract class CommonDebugLesson(id: String) : KLesson(id, LessonsBundle.message
|
|||||||
dialog?.title == XDebuggerBundle.message("xdebugger.evaluate.dialog.title") && root?.children?.size == 1
|
dialog?.title == XDebuggerBundle.message("xdebugger.evaluate.dialog.title") && root?.children?.size == 1
|
||||||
}
|
}
|
||||||
proposeModificationRestore(afterFixText)
|
proposeModificationRestore(afterFixText)
|
||||||
test { GuiTestUtil.shortcut(Key.ENTER) }
|
test(waitEditorToBeReady = false) {
|
||||||
|
invokeActionViaShortcut("ENTER")
|
||||||
|
invokeActionViaShortcut("ESCAPE")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import com.intellij.execution.ExecutionBundle
|
|||||||
import com.intellij.execution.RunManager
|
import com.intellij.execution.RunManager
|
||||||
import com.intellij.idea.ActionsBundle
|
import com.intellij.idea.ActionsBundle
|
||||||
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
||||||
import com.intellij.testGuiFramework.impl.button
|
|
||||||
import com.intellij.testGuiFramework.impl.jList
|
|
||||||
import com.intellij.ui.UIBundle
|
import com.intellij.ui.UIBundle
|
||||||
import com.intellij.ui.components.JBCheckBox
|
import com.intellij.ui.components.JBCheckBox
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
@@ -108,7 +106,7 @@ abstract class CommonRunConfigurationLesson(id: String) : KLesson(id, LessonsBun
|
|||||||
stateCheck {
|
stateCheck {
|
||||||
focusOwner is EditorComponentImpl
|
focusOwner is EditorComponentImpl
|
||||||
}
|
}
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
ideFrame {
|
ideFrame {
|
||||||
button("Cancel").click()
|
button("Cancel").click()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,327 @@
|
|||||||
|
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
package training.ui
|
||||||
|
|
||||||
|
import com.intellij.util.ConcurrencyUtil
|
||||||
|
import com.intellij.util.ui.EdtInvocationManager
|
||||||
|
import org.fest.swing.awt.AWT
|
||||||
|
import org.fest.swing.core.*
|
||||||
|
import org.fest.swing.core.Robot
|
||||||
|
import org.fest.swing.edt.GuiActionRunner
|
||||||
|
import org.fest.swing.edt.GuiQuery
|
||||||
|
import org.fest.swing.hierarchy.ComponentHierarchy
|
||||||
|
import org.fest.swing.timing.Pause
|
||||||
|
import java.awt.*
|
||||||
|
import java.util.concurrent.CountDownLatch
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import javax.swing.JComponent
|
||||||
|
import javax.swing.JPopupMenu
|
||||||
|
import javax.swing.SwingUtilities
|
||||||
|
|
||||||
|
// It is a copy-paster from testGuiFramework (with several changes)
|
||||||
|
internal class IftSmartWaitRobot : Robot {
|
||||||
|
|
||||||
|
override fun moveMouse(component: Component) {
|
||||||
|
var where = AWT.visibleCenterOf(component)
|
||||||
|
if (component is JComponent) {
|
||||||
|
Scrolling.scrollToVisible(this, component)
|
||||||
|
where = AWT.visibleCenterOf(component)
|
||||||
|
}
|
||||||
|
moveMouse(component, where)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun moveMouse(component: Component, point: Point) {
|
||||||
|
val translatedPoint = performOnEdt { AWT.translate(component, point.x, point.y) }
|
||||||
|
requireNotNull(translatedPoint) { "Translated point should be not null" }
|
||||||
|
moveMouse(translatedPoint.x, translatedPoint.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun moveMouse(point: Point) {
|
||||||
|
moveMouse(point.x, point.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun click(component: Component) {
|
||||||
|
moveMouse(component)
|
||||||
|
basicRobot.click(component)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun click(component: Component, mouseButton: MouseButton) {
|
||||||
|
moveMouse(component)
|
||||||
|
basicRobot.click(component, mouseButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun click(component: Component, mouseButton: MouseButton, counts: Int) {
|
||||||
|
moveMouse(component)
|
||||||
|
basicRobot.click(component, mouseButton, counts)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun click(component: Component, point: Point) {
|
||||||
|
moveMouse(component, point)
|
||||||
|
basicRobot.click(component, point)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showWindow(window: Window) {
|
||||||
|
basicRobot.showWindow(window)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showWindow(window: Window, dimension: Dimension) {
|
||||||
|
basicRobot.showWindow(window, dimension)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showWindow(window: Window, dimension: Dimension?, p2: Boolean) {
|
||||||
|
basicRobot.showWindow(window, dimension, p2)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isActive(): Boolean = basicRobot.isActive
|
||||||
|
|
||||||
|
|
||||||
|
override fun pressAndReleaseKey(p0: Int, vararg p1: Int) {
|
||||||
|
basicRobot.pressAndReleaseKey(p0, *p1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showPopupMenu(component: Component): JPopupMenu =
|
||||||
|
basicRobot.showPopupMenu(component)
|
||||||
|
|
||||||
|
override fun showPopupMenu(component: Component, point: Point): JPopupMenu =
|
||||||
|
basicRobot.showPopupMenu(component, point)
|
||||||
|
|
||||||
|
override fun jitter(component: Component) {
|
||||||
|
basicRobot.jitter(component)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun jitter(component: Component, point: Point) {
|
||||||
|
basicRobot.jitter(component, point)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pressModifiers(p0: Int) {
|
||||||
|
basicRobot.pressModifiers(p0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pressMouse(mouseButton: MouseButton) {
|
||||||
|
basicRobot.pressMouse(mouseButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pressMouse(component: Component, point: Point) {
|
||||||
|
basicRobot.pressMouse(component, point)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pressMouse(component: Component, point: Point, mouseButton: MouseButton) {
|
||||||
|
basicRobot.pressMouse(component, point, mouseButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pressMouse(point: Point, mouseButton: MouseButton) {
|
||||||
|
basicRobot.pressMouse(point, mouseButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hierarchy(): ComponentHierarchy =
|
||||||
|
basicRobot.hierarchy()
|
||||||
|
|
||||||
|
override fun releaseKey(p0: Int) {
|
||||||
|
basicRobot.releaseKey(p0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isDragging(): Boolean = basicRobot.isDragging
|
||||||
|
|
||||||
|
override fun printer(): ComponentPrinter = basicRobot.printer()
|
||||||
|
|
||||||
|
override fun type(char: Char) {
|
||||||
|
basicRobot.type(char)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun type(char: Char, component: Component) {
|
||||||
|
basicRobot.type(char, component)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun requireNoJOptionPaneIsShowing() {
|
||||||
|
basicRobot.requireNoJOptionPaneIsShowing()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cleanUp() {
|
||||||
|
basicRobot.cleanUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun releaseMouse(mouseButton: MouseButton) {
|
||||||
|
basicRobot.releaseMouse(mouseButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pressKey(p0: Int) {
|
||||||
|
basicRobot.pressKey(p0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun settings(): Settings = basicRobot.settings()
|
||||||
|
|
||||||
|
override fun enterText(text: String) {
|
||||||
|
basicRobot.enterText(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun enterText(text: String, component: Component) {
|
||||||
|
basicRobot.enterText(text, component)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun releaseMouseButtons() {
|
||||||
|
basicRobot.releaseMouseButtons()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun rightClick(component: Component) {
|
||||||
|
basicRobot.rightClick(component)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun focus(component: Component) {
|
||||||
|
basicRobot.focus(component)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doubleClick(component: Component) {
|
||||||
|
basicRobot.doubleClick(component)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cleanUpWithoutDisposingWindows() {
|
||||||
|
basicRobot.cleanUpWithoutDisposingWindows()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isReadyForInput(component: Component): Boolean = basicRobot.isReadyForInput(component)
|
||||||
|
|
||||||
|
override fun focusAndWaitForFocusGain(component: Component) {
|
||||||
|
basicRobot.focusAndWaitForFocusGain(component)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun releaseModifiers(p0: Int) {
|
||||||
|
basicRobot.releaseModifiers(p0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findActivePopupMenu(): JPopupMenu? {
|
||||||
|
return basicRobot.findActivePopupMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun rotateMouseWheel(component: Component, p1: Int) {
|
||||||
|
basicRobot.rotateMouseWheel(component, p1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun rotateMouseWheel(p0: Int) {
|
||||||
|
basicRobot.rotateMouseWheel(p0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pressAndReleaseKeys(vararg p0: Int) {
|
||||||
|
basicRobot.pressAndReleaseKeys(*p0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun finder(): ComponentFinder = basicRobot.finder()
|
||||||
|
|
||||||
|
private val basicRobot: BasicRobot = BasicRobot.robotWithCurrentAwtHierarchyWithoutScreenLock() as BasicRobot
|
||||||
|
|
||||||
|
init {
|
||||||
|
settings().delayBetweenEvents(10)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val waitConst = 30L
|
||||||
|
private var myAwareClick: Boolean = false
|
||||||
|
|
||||||
|
override fun waitForIdle() {
|
||||||
|
if (myAwareClick) {
|
||||||
|
Thread.sleep(50)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Pause.pause(waitConst)
|
||||||
|
if (!SwingUtilities.isEventDispatchThread()) EdtInvocationManager.getInstance().invokeAndWait({ })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close(w: Window) {
|
||||||
|
basicRobot.close(w)
|
||||||
|
basicRobot.waitForIdle()
|
||||||
|
}
|
||||||
|
|
||||||
|
//smooth mouse move
|
||||||
|
override fun moveMouse(x: Int, y: Int) {
|
||||||
|
val pauseConstMs = settings().delayBetweenEvents().toLong()
|
||||||
|
val n = 20
|
||||||
|
val start = MouseInfo.getPointerInfo().location
|
||||||
|
val dx = (x - start.x) / n.toDouble()
|
||||||
|
val dy = (y - start.y) / n.toDouble()
|
||||||
|
for (step in 1..n) {
|
||||||
|
try {
|
||||||
|
Pause.pause(pauseConstMs)
|
||||||
|
}
|
||||||
|
catch (e: InterruptedException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
basicRobot.moveMouse(
|
||||||
|
(start.x + dx * ((Math.log(1.0 * step / n) - Math.log(1.0 / n)) * n / (0 - Math.log(1.0 / n)))).toInt(),
|
||||||
|
(start.y + dy * ((Math.log(1.0 * step / n) - Math.log(1.0 / n)) * n / (0 - Math.log(1.0 / n)))).toInt())
|
||||||
|
}
|
||||||
|
basicRobot.moveMouse(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
//smooth mouse move to component
|
||||||
|
override fun moveMouse(c: Component, x: Int, y: Int) {
|
||||||
|
moveMouseWithAttempts(c, x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
//smooth mouse move for find and click actions
|
||||||
|
override fun click(c: Component, where: Point, button: MouseButton, times: Int) {
|
||||||
|
moveMouseAndClick(c, where, button, times)
|
||||||
|
}
|
||||||
|
|
||||||
|
//we are replacing BasicRobot click with our click because the original one cannot handle double click rightly (BasicRobot creates unnecessary move event between click event which breaks clickCount from 2 to 1)
|
||||||
|
override fun click(where: Point, button: MouseButton, times: Int) {
|
||||||
|
moveMouseAndClick(null, where, button, times)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun moveMouseAndClick(c: Component? = null, where: Point, button: MouseButton, times: Int) {
|
||||||
|
if (c != null) moveMouse(c, where.x, where.y) else moveMouse(where.x, where.y)
|
||||||
|
//pause between moving cursor and performing a click.
|
||||||
|
Pause.pause(waitConst)
|
||||||
|
myEdtAwareClick(button, times, where, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun moveMouseWithAttempts(c: Component, x: Int, y: Int, attempts: Int = 3) {
|
||||||
|
if (attempts == 0) return
|
||||||
|
waitFor { c.isShowing }
|
||||||
|
|
||||||
|
val componentLocation: Point = requireNotNull(performOnEdt { AWT.translate(c, x, y) })
|
||||||
|
moveMouse(componentLocation.x, componentLocation.y)
|
||||||
|
|
||||||
|
val componentLocationAfterMove: Point = requireNotNull(performOnEdt { AWT.translate(c, x, y) })
|
||||||
|
val mouseLocation = MouseInfo.getPointerInfo().location
|
||||||
|
if (mouseLocation.x != componentLocationAfterMove.x || mouseLocation.y != componentLocationAfterMove.y)
|
||||||
|
moveMouseWithAttempts(c, x, y, attempts - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun myInnerClick(button: MouseButton, times: Int, point: Point, component: Component?) {
|
||||||
|
if (component == null)
|
||||||
|
basicRobot.click(point, button, times)
|
||||||
|
else
|
||||||
|
basicRobot.click(component, point, button, times)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun waitFor(condition: () -> Boolean) {
|
||||||
|
val timeout = 5000 //5 sec
|
||||||
|
val cdl = CountDownLatch(1)
|
||||||
|
val executor = ConcurrencyUtil.newSingleScheduledThreadExecutor("SmartWaitRobot").scheduleWithFixedDelay(Runnable {
|
||||||
|
if (condition()) {
|
||||||
|
cdl.countDown()
|
||||||
|
}
|
||||||
|
}, 0, 100, TimeUnit.MILLISECONDS)
|
||||||
|
cdl.await(timeout.toLong(), TimeUnit.MILLISECONDS)
|
||||||
|
executor.cancel(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun myEdtAwareClick(button: MouseButton, times: Int, point: Point, component: Component?) {
|
||||||
|
awareClick {
|
||||||
|
myInnerClick(button, times, point, component)
|
||||||
|
}
|
||||||
|
waitForIdle()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> performOnEdt(body: () -> T): T? =
|
||||||
|
GuiActionRunner.execute(object : GuiQuery<T>() {
|
||||||
|
override fun executeInEDT() = body.invoke()
|
||||||
|
})
|
||||||
|
|
||||||
|
private fun awareClick(body: () -> Unit) {
|
||||||
|
myAwareClick = true
|
||||||
|
body.invoke()
|
||||||
|
myAwareClick = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package training.ui
|
package training.ui
|
||||||
|
|
||||||
import org.fest.swing.core.BasicRobot
|
|
||||||
import org.fest.swing.core.GenericTypeMatcher
|
import org.fest.swing.core.GenericTypeMatcher
|
||||||
import org.fest.swing.core.Robot
|
import org.fest.swing.core.Robot
|
||||||
import org.fest.swing.exception.ComponentLookupException
|
import org.fest.swing.exception.ComponentLookupException
|
||||||
import org.fest.swing.exception.WaitTimedOutError
|
import org.fest.swing.exception.WaitTimedOutError
|
||||||
|
import org.fest.swing.fixture.ContainerFixture
|
||||||
import org.fest.swing.timing.Condition
|
import org.fest.swing.timing.Condition
|
||||||
import org.fest.swing.timing.Pause
|
import org.fest.swing.timing.Pause
|
||||||
import org.fest.swing.timing.Timeout
|
import org.fest.swing.timing.Timeout
|
||||||
@@ -18,7 +18,8 @@ import java.util.concurrent.atomic.AtomicReference
|
|||||||
object LearningUiUtil {
|
object LearningUiUtil {
|
||||||
@Volatile
|
@Volatile
|
||||||
private var myRobot: Robot? = null
|
private var myRobot: Robot? = null
|
||||||
private val robot: Robot
|
|
||||||
|
val robot: Robot
|
||||||
get() {
|
get() {
|
||||||
if(myRobot == null)
|
if(myRobot == null)
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
@@ -29,7 +30,7 @@ object LearningUiUtil {
|
|||||||
|
|
||||||
private fun initializeRobot() {
|
private fun initializeRobot() {
|
||||||
if (myRobot != null) releaseRobot()
|
if (myRobot != null) releaseRobot()
|
||||||
myRobot = BasicRobot.robotWithCurrentAwtHierarchyWithoutScreenLock() // acquires ScreenLock
|
myRobot = IftSmartWaitRobot()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun releaseRobot() {
|
private fun releaseRobot() {
|
||||||
@@ -119,4 +120,23 @@ object LearningUiUtil {
|
|||||||
"Unable to find ${componentClass.simpleName} ${if (container != null) "in container $container" else ""} in ${timeout.duration()}(ms)")
|
"Unable to find ${componentClass.simpleName} ${if (container != null) "in container $container" else ""} in ${timeout.duration()}(ms)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* function to find component of returning type inside a container (gets from receiver).
|
||||||
|
*
|
||||||
|
* @throws ComponentLookupException if desired component haven't been found under the container (gets from receiver) in specified timeout
|
||||||
|
*/
|
||||||
|
inline fun <reified ComponentType : Component, ContainerComponentType : Container> ContainerFixture<ContainerComponentType>?.findComponentWithTimeout(
|
||||||
|
timeout: Timeout = Timeout.timeout(10, TimeUnit.SECONDS),
|
||||||
|
crossinline finderFunction: (ComponentType) -> Boolean = { true }): ComponentType {
|
||||||
|
try {
|
||||||
|
return waitUntilFound(robot, this?.target() as Container?,
|
||||||
|
typeMatcher(ComponentType::class.java) { finderFunction(it) },
|
||||||
|
timeout)
|
||||||
|
}
|
||||||
|
catch (e: WaitTimedOutError) {
|
||||||
|
throw ComponentLookupException(
|
||||||
|
"Unable to find ${ComponentType::class.java.name} ${if (this?.target() != null) "in container ${this.target()}" else ""} in ${timeout.duration()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -39,8 +39,7 @@ class LearningLessonsAutoExecutor(val project: Project, private val progress: Pr
|
|||||||
val lessons = CourseManager.instance.lessonsForModules
|
val lessons = CourseManager.instance.lessonsForModules
|
||||||
|
|
||||||
for (lesson in lessons) {
|
for (lesson in lessons) {
|
||||||
if (lesson !is KLesson) continue
|
if (lesson !is KLesson || lesson.testScriptProperties.skipTesting) continue
|
||||||
if (lesson.testScriptProperties.skipTesting) continue
|
|
||||||
progress.checkCanceled()
|
progress.checkCanceled()
|
||||||
runSingleLesson(lesson)
|
runSingleLesson(lesson)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<orderEntry type="module" module-name="intellij.featuresTrainer" />
|
<orderEntry type="module" module-name="intellij.featuresTrainer" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.debugger" />
|
<orderEntry type="module" module-name="intellij.platform.debugger" />
|
||||||
<orderEntry type="module" module-name="intellij.platform.testGuiFramework" />
|
|
||||||
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
|
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
|
||||||
|
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package com.jetbrains.python.ift.lesson.completion
|
package com.jetbrains.python.ift.lesson.completion
|
||||||
|
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.jetbrains.python.ift.PythonLessonsBundle
|
import com.jetbrains.python.ift.PythonLessonsBundle
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.LessonUtil.checkExpectedStateOfEditor
|
import training.dsl.LessonUtil.checkExpectedStateOfEditor
|
||||||
@@ -74,7 +72,7 @@ class FStringCompletionLesson
|
|||||||
stateCheck {
|
stateCheck {
|
||||||
editor.document.text == result
|
editor.document.text == result
|
||||||
}
|
}
|
||||||
test { GuiTestUtil.shortcut(Key.ENTER) }
|
test(waitEditorToBeReady = false) { invokeActionViaShortcut("ENTER") }
|
||||||
}
|
}
|
||||||
text(PythonLessonsBundle.message("python.f.string.completion.result.message"))
|
text(PythonLessonsBundle.message("python.f.string.completion.result.message"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package com.jetbrains.python.ift.lesson.completion
|
package com.jetbrains.python.ift.lesson.completion
|
||||||
|
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil.typeText
|
|
||||||
import com.intellij.testGuiFramework.impl.jList
|
|
||||||
import com.jetbrains.python.ift.PythonLessonsBundle
|
import com.jetbrains.python.ift.PythonLessonsBundle
|
||||||
import training.dsl.LessonContext
|
import training.dsl.LessonContext
|
||||||
import training.dsl.LessonUtil.checkExpectedStateOfEditor
|
import training.dsl.LessonUtil.checkExpectedStateOfEditor
|
||||||
@@ -48,16 +46,14 @@ class PythonPostfixCompletionLesson
|
|||||||
checkExpectedStateOfEditor(sample) { completionSuffix.startsWith(it) }
|
checkExpectedStateOfEditor(sample) { completionSuffix.startsWith(it) }
|
||||||
}
|
}
|
||||||
test {
|
test {
|
||||||
ideFrame {
|
type(completionSuffix)
|
||||||
typeText(completionSuffix)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
task {
|
task {
|
||||||
text(PythonLessonsBundle.message("python.postfix.completion.select.item", code(completionSuffix)))
|
text(PythonLessonsBundle.message("python.postfix.completion.select.item", code(completionSuffix)))
|
||||||
stateCheck { editor.document.text == result }
|
stateCheck { editor.document.text == result }
|
||||||
restoreByUi()
|
restoreByUi()
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
ideFrame {
|
ideFrame {
|
||||||
jList("ifnn").item(0).doubleClick()
|
jList("ifnn").item(0).doubleClick()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
package com.jetbrains.python.ift.lesson.completion
|
package com.jetbrains.python.ift.lesson.completion
|
||||||
|
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.jetbrains.python.ift.PythonLessonsBundle
|
import com.jetbrains.python.ift.PythonLessonsBundle
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
import training.dsl.LessonUtil.checkExpectedStateOfEditor
|
import training.dsl.LessonUtil.checkExpectedStateOfEditor
|
||||||
@@ -67,7 +65,7 @@ class PythonTabCompletionLesson
|
|||||||
restoreAfterStateBecomeFalse {
|
restoreAfterStateBecomeFalse {
|
||||||
selectNeededItem()?.not() ?: true
|
selectNeededItem()?.not() ?: true
|
||||||
}
|
}
|
||||||
test { GuiTestUtil.shortcut(Key.TAB) }
|
test { invokeActionViaShortcut("TAB") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
package com.jetbrains.python.ift.lesson.refactorings
|
package com.jetbrains.python.ift.lesson.refactorings
|
||||||
|
|
||||||
import com.intellij.icons.AllIcons
|
import com.intellij.icons.AllIcons
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.jetbrains.python.ift.PythonLessonsBundle
|
import com.jetbrains.python.ift.PythonLessonsBundle
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
import training.dsl.LessonUtil.checkExpectedStateOfEditor
|
import training.dsl.LessonUtil.checkExpectedStateOfEditor
|
||||||
@@ -70,7 +68,7 @@ class PythonInPlaceRefactoringLesson
|
|||||||
val expected = template.replace("<caret>", "").replace("<name>", newName)
|
val expected = template.replace("<caret>", "").replace("<name>", newName)
|
||||||
newName != variableName && editor.document.text == expected
|
newName != variableName && editor.document.text == expected
|
||||||
}
|
}
|
||||||
test { GuiTestUtil.shortcut(Key.ENTER) }
|
test { invokeActionViaShortcut("ENTER") }
|
||||||
}
|
}
|
||||||
|
|
||||||
waitBeforeContinue(500)
|
waitBeforeContinue(500)
|
||||||
@@ -127,7 +125,7 @@ class PythonInPlaceRefactoringLesson
|
|||||||
ui.javaClass.name.contains("ChangeSignaturePopup")
|
ui.javaClass.name.contains("ChangeSignaturePopup")
|
||||||
}
|
}
|
||||||
restoreByUi(delayMillis = defaultRestoreDelay)
|
restoreByUi(delayMillis = defaultRestoreDelay)
|
||||||
test { GuiTestUtil.shortcut(Key.ENTER) }
|
test { invokeActionViaShortcut("ENTER") }
|
||||||
}
|
}
|
||||||
|
|
||||||
task {
|
task {
|
||||||
@@ -138,7 +136,7 @@ class PythonInPlaceRefactoringLesson
|
|||||||
restoreAfterStateBecomeFalse(restoreId = showIntentionsTaskId) {
|
restoreAfterStateBecomeFalse(restoreId = showIntentionsTaskId) {
|
||||||
previous.ui?.isShowing != true
|
previous.ui?.isShowing != true
|
||||||
}
|
}
|
||||||
test { GuiTestUtil.shortcut(Key.ENTER) }
|
test(waitEditorToBeReady = false) { invokeActionViaShortcut("ENTER") }
|
||||||
}
|
}
|
||||||
task {
|
task {
|
||||||
lateinit var beforeSecondRefactoring: String
|
lateinit var beforeSecondRefactoring: String
|
||||||
@@ -152,9 +150,9 @@ class PythonInPlaceRefactoringLesson
|
|||||||
it.className.contains("PySuggestedRefactoringExecution") && it.methodName == "performChangeSignature"
|
it.className.contains("PySuggestedRefactoringExecution") && it.methodName == "performChangeSignature"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
type("0")
|
type("0")
|
||||||
GuiTestUtil.shortcut(Key.ENTER)
|
invokeActionViaShortcut("ENTER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
text(PythonLessonsBundle.message("python.in.place.refactoring.remark.about.application.scope"))
|
text(PythonLessonsBundle.message("python.in.place.refactoring.remark.about.application.scope"))
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ import com.intellij.openapi.application.invokeAndWaitIfNeeded
|
|||||||
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
import com.intellij.openapi.editor.impl.EditorComponentImpl
|
||||||
import com.intellij.openapi.wm.IdeFocusManager
|
import com.intellij.openapi.wm.IdeFocusManager
|
||||||
import com.intellij.refactoring.RefactoringBundle
|
import com.intellij.refactoring.RefactoringBundle
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.impl.button
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.util.ui.UIUtil
|
import com.intellij.util.ui.UIUtil
|
||||||
import com.intellij.util.ui.table.JBTableRow
|
import com.intellij.util.ui.table.JBTableRow
|
||||||
import com.jetbrains.python.PyBundle
|
import com.jetbrains.python.PyBundle
|
||||||
@@ -51,7 +48,7 @@ class PythonQuickFixesRefactoringLesson
|
|||||||
restoreState {
|
restoreState {
|
||||||
!editor.document.text.contains(it)
|
!editor.document.text.contains(it)
|
||||||
}
|
}
|
||||||
test { GuiTestUtil.shortcut(Key.ESCAPE) }
|
test(waitEditorToBeReady = false) { invokeActionViaShortcut("ESCAPE") }
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareRuntimeTask { // restore point
|
prepareRuntimeTask { // restore point
|
||||||
@@ -86,7 +83,7 @@ class PythonQuickFixesRefactoringLesson
|
|||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
restoreByUi(delayMillis = defaultRestoreDelay)
|
restoreByUi(delayMillis = defaultRestoreDelay)
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
ideFrame {
|
ideFrame {
|
||||||
jListContains(quickFixItemText).clickItem(Pattern.compile(".*$quickFixItemText.*"))
|
jListContains(quickFixItemText).clickItem(Pattern.compile(".*$quickFixItemText.*"))
|
||||||
}
|
}
|
||||||
@@ -103,12 +100,12 @@ class PythonQuickFixesRefactoringLesson
|
|||||||
UIUtil.getParentOfType(JDialog::class.java, editor) != null
|
UIUtil.getParentOfType(JDialog::class.java, editor) != null
|
||||||
}
|
}
|
||||||
restoreByUi()
|
restoreByUi()
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
invokeAndWaitIfNeeded(ModalityState.any()) {
|
invokeAndWaitIfNeeded(ModalityState.any()) {
|
||||||
val ui = previous.ui ?: return@invokeAndWaitIfNeeded
|
val ui = previous.ui ?: return@invokeAndWaitIfNeeded
|
||||||
IdeFocusManager.getInstance(project).requestFocus(ui, true)
|
IdeFocusManager.getInstance(project).requestFocus(ui, true)
|
||||||
}
|
}
|
||||||
GuiTestUtil.shortcut(Key.ENTER)
|
invokeActionViaShortcut("ENTER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
task {
|
task {
|
||||||
@@ -118,12 +115,12 @@ class PythonQuickFixesRefactoringLesson
|
|||||||
stateCheck {
|
stateCheck {
|
||||||
(previous.ui as? EditorComponentImpl)?.text == "0"
|
(previous.ui as? EditorComponentImpl)?.text == "0"
|
||||||
}
|
}
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
invokeAndWaitIfNeeded(ModalityState.any()) {
|
invokeAndWaitIfNeeded(ModalityState.any()) {
|
||||||
val ui = previous.ui ?: return@invokeAndWaitIfNeeded
|
val ui = previous.ui ?: return@invokeAndWaitIfNeeded
|
||||||
IdeFocusManager.getInstance(project).requestFocus(ui, true)
|
IdeFocusManager.getInstance(project).requestFocus(ui, true)
|
||||||
}
|
}
|
||||||
GuiTestUtil.shortcut(Key.BACK_SPACE)
|
invokeActionViaShortcut("BACK_SPACE")
|
||||||
type("0")
|
type("0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,11 +141,9 @@ class PythonQuickFixesRefactoringLesson
|
|||||||
!stackInsideDialogRefactoring()
|
!stackInsideDialogRefactoring()
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
with(TaskTestContext.guiTestCase) {
|
dialog("Change Signature") {
|
||||||
dialog("Change Signature") {
|
button("Refactor").click()
|
||||||
button("Refactor").click()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,12 @@ package com.jetbrains.python.ift.lesson.refactorings
|
|||||||
|
|
||||||
import com.intellij.ide.DataManager
|
import com.intellij.ide.DataManager
|
||||||
import com.intellij.ide.actions.exclusion.ExclusionHandler
|
import com.intellij.ide.actions.exclusion.ExclusionHandler
|
||||||
import com.intellij.openapi.application.runReadAction
|
|
||||||
import com.intellij.refactoring.RefactoringBundle
|
import com.intellij.refactoring.RefactoringBundle
|
||||||
import com.intellij.testGuiFramework.framework.GuiTestUtil
|
|
||||||
import com.intellij.testGuiFramework.framework.Timeouts
|
|
||||||
import com.intellij.testGuiFramework.impl.button
|
|
||||||
import com.intellij.testGuiFramework.impl.jTree
|
|
||||||
import com.intellij.testGuiFramework.util.Key
|
|
||||||
import com.intellij.ui.tree.TreeVisitor
|
import com.intellij.ui.tree.TreeVisitor
|
||||||
import com.intellij.usageView.UsageViewBundle
|
import com.intellij.usageView.UsageViewBundle
|
||||||
import com.intellij.util.ui.tree.TreeUtil
|
import com.intellij.util.ui.tree.TreeUtil
|
||||||
import com.jetbrains.python.ift.PythonLessonsBundle
|
import com.jetbrains.python.ift.PythonLessonsBundle
|
||||||
|
import org.fest.swing.fixture.JTreeFixture
|
||||||
import org.jetbrains.annotations.Nullable
|
import org.jetbrains.annotations.Nullable
|
||||||
import training.dsl.*
|
import training.dsl.*
|
||||||
import training.learn.LessonsBundle
|
import training.learn.LessonsBundle
|
||||||
@@ -24,6 +19,7 @@ import javax.swing.JTree
|
|||||||
import javax.swing.tree.TreePath
|
import javax.swing.tree.TreePath
|
||||||
|
|
||||||
class PythonRenameLesson : KLesson("Rename", LessonsBundle.message("rename.lesson.name")) {
|
class PythonRenameLesson : KLesson("Rename", LessonsBundle.message("rename.lesson.name")) {
|
||||||
|
override val testScriptProperties = TaskTestContext.TestScriptProperties(10)
|
||||||
private val template = """
|
private val template = """
|
||||||
class Championship:
|
class Championship:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -55,9 +51,6 @@ class PythonRenameLesson : KLesson("Rename", LessonsBundle.message("rename.lesso
|
|||||||
print(c.<name>)
|
print(c.<name>)
|
||||||
""".trimIndent() + '\n'
|
""".trimIndent() + '\n'
|
||||||
|
|
||||||
/** For test only */
|
|
||||||
private val substringPredicate: (String, String) -> Boolean = { found: String, wanted: String -> found.contains(wanted) }
|
|
||||||
|
|
||||||
private val sample = parseLessonSample(template.replace("<name>", "teams"))
|
private val sample = parseLessonSample(template.replace("<name>", "teams"))
|
||||||
|
|
||||||
private val replacePreviewPattern = Pattern.compile(".*Variable to be renamed to (\\w+).*")
|
private val replacePreviewPattern = Pattern.compile(".*Variable to be renamed to (\\w+).*")
|
||||||
@@ -66,10 +59,13 @@ class PythonRenameLesson : KLesson("Rename", LessonsBundle.message("rename.lesso
|
|||||||
prepareSample(sample)
|
prepareSample(sample)
|
||||||
val dynamicWord = UsageViewBundle.message("usage.view.results.node.dynamic")
|
val dynamicWord = UsageViewBundle.message("usage.view.results.node.dynamic")
|
||||||
var replace: String? = null
|
var replace: String? = null
|
||||||
|
var dynamicItem: String? = null
|
||||||
task("RenameElement") {
|
task("RenameElement") {
|
||||||
text(PythonLessonsBundle.message("python.rename.press.rename", action(it), code("teams"), code("teams_number")))
|
text(PythonLessonsBundle.message("python.rename.press.rename", action(it), code("teams"), code("teams_number")))
|
||||||
triggerByFoundPathAndHighlight { tree: JTree, path: TreePath ->
|
triggerByFoundPathAndHighlight { tree: JTree, path: TreePath ->
|
||||||
if (path.pathCount == 2 && path.getPathComponent(1).toString().contains(dynamicWord)) {
|
val pathStr = path.getPathComponent(1).toString()
|
||||||
|
if (path.pathCount == 2 && pathStr.contains(dynamicWord)) {
|
||||||
|
dynamicItem = pathStr
|
||||||
replace = replacePreviewPattern.matcher(tree.model.root.toString()).takeIf { m -> m.find() }?.group(1)
|
replace = replacePreviewPattern.matcher(tree.model.root.toString()).takeIf { m -> m.find() }?.group(1)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@@ -77,11 +73,9 @@ class PythonRenameLesson : KLesson("Rename", LessonsBundle.message("rename.lesso
|
|||||||
}
|
}
|
||||||
test {
|
test {
|
||||||
actions(it)
|
actions(it)
|
||||||
with(TaskTestContext.guiTestCase) {
|
dialog {
|
||||||
dialog {
|
type("teams_number")
|
||||||
typeText("teams_number")
|
button("Refactor").click()
|
||||||
button("Refactor").click()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,12 +96,14 @@ class PythonRenameLesson : KLesson("Rename", LessonsBundle.message("rename.lesso
|
|||||||
}
|
}
|
||||||
showWarningIfFindToolbarClosed()
|
showWarningIfFindToolbarClosed()
|
||||||
test {
|
test {
|
||||||
|
//TODO: Fix tree access
|
||||||
|
val jTree = previous.ui as? JTree ?: return@test
|
||||||
|
val di = dynamicItem ?: return@test
|
||||||
ideFrame {
|
ideFrame {
|
||||||
val jTree = runReadAction {
|
val jTreeFixture = JTreeFixture(robot, jTree)
|
||||||
jTree(dynamicReferencesString, timeout = Timeouts.seconds03, predicate = substringPredicate)
|
jTreeFixture.replaceSeparator("@@@")
|
||||||
}
|
jTreeFixture.expandPath(di)
|
||||||
// WARNING: several exception will be here because of UsageNode#toString inside info output during this operation
|
// WARNING: several exception will be here because of UsageNode#toString inside info output during this operation
|
||||||
jTree.doubleClickPath()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,8 +127,8 @@ class PythonRenameLesson : KLesson("Rename", LessonsBundle.message("rename.lesso
|
|||||||
showWarningIfFindToolbarClosed()
|
showWarningIfFindToolbarClosed()
|
||||||
test {
|
test {
|
||||||
ideFrame {
|
ideFrame {
|
||||||
type("co_me")
|
type("come")
|
||||||
GuiTestUtil.shortcut(Key.DELETE)
|
invokeActionViaShortcut("DELETE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,7 +145,7 @@ class PythonRenameLesson : KLesson("Rename", LessonsBundle.message("rename.lesso
|
|||||||
text(PythonLessonsBundle.message("python.rename.finish.refactoring", strong(confirmRefactoringButton)))
|
text(PythonLessonsBundle.message("python.rename.finish.refactoring", strong(confirmRefactoringButton)))
|
||||||
stateCheck { editor.document.text == result }
|
stateCheck { editor.document.text == result }
|
||||||
showWarningIfFindToolbarClosed()
|
showWarningIfFindToolbarClosed()
|
||||||
test {
|
test(waitEditorToBeReady = false) {
|
||||||
ideFrame {
|
ideFrame {
|
||||||
button(confirmRefactoringButton).click()
|
button(confirmRefactoringButton).click()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user