diff --git a/platform/execution/resources/messages/ExecutionBundle.properties b/platform/execution/resources/messages/ExecutionBundle.properties index 3d3f5ef90906..7eb20c1a46c2 100644 --- a/platform/execution/resources/messages/ExecutionBundle.properties +++ b/platform/execution/resources/messages/ExecutionBundle.properties @@ -150,8 +150,13 @@ junit.running.info.expand.test.action.name=Expand all test suites junit.running.info.select.first.failed.action.name=Select First Failed Test When Finished junit.running.info.include.non.started.in.rerun.failed.action.name=Include Non-Started Tests in Rerun Failed junit.running.info.hide.successful.config.action.name=Hide Successful setUp/tearDown -junit.running.info.scroll.to.stacktrace.action.name=Scroll to Stack Trace +junit.running.info.scroll.to.group.name=Scroll To +junit.running.info.scroll.to.stacktrace.action.name=Stack Trace junit.running.info.scroll.to.stacktrace.action.description=Scroll console to the beginning of assertion or exception stack trace +junit.running.info.scroll.to.top.action.name=Top +junit.running.info.scroll.to.top.action.description=Scroll console to the top after the test ends +junit.running.info.scroll.to.bottom.action.name=Bottom +junit.running.info.scroll.to.bottom.action.description=Scroll console to the bottom after the test ends junit.running.info.open.source.at.exception.action.name=Open Source at Exception junit.running.info.open.source.at.exception.action.description=Go to the line which caused an exception when opening a test source junit.running.info.test.runner.options.group.name=Test Runner Settings diff --git a/platform/testRunner/api-dump.txt b/platform/testRunner/api-dump.txt index 5dfa99b0aaa1..a4aaa049db48 100644 --- a/platform/testRunner/api-dump.txt +++ b/platform/testRunner/api-dump.txt @@ -122,6 +122,7 @@ a:com.intellij.execution.testframework.TestConsoleProperties - sf:HIDE_SUCCESSFUL_CONFIG:com.intellij.util.config.BooleanProperty - sf:INCLUDE_NON_STARTED_IN_RERUN_FAILED:com.intellij.util.config.BooleanProperty - sf:OPEN_FAILURE_LINE:com.intellij.util.config.BooleanProperty +- sf:SCROLL_TO_BOTTOM:com.intellij.util.config.BooleanProperty - sf:SCROLL_TO_SOURCE:com.intellij.util.config.BooleanProperty - sf:SCROLL_TO_STACK_TRACE:com.intellij.util.config.BooleanProperty - sf:SELECT_FIRST_DEFECT:com.intellij.util.config.BooleanProperty diff --git a/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java b/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java index 56ea73b0d0f1..7dc0ef6415bc 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.execution.testframework; import com.intellij.execution.DefaultExecutionTarget; @@ -39,6 +39,7 @@ import java.util.Map; */ public abstract class TestConsoleProperties extends StoringPropertyContainer implements Disposable { public static final BooleanProperty SCROLL_TO_STACK_TRACE = new BooleanProperty("scrollToStackTrace", false); + public static final BooleanProperty SCROLL_TO_BOTTOM = new BooleanProperty("scrollToBottom", false); public static final BooleanProperty SORT_ALPHABETICALLY = new BooleanProperty("sortTestsAlphabetically", false); public static final BooleanProperty SORT_BY_DURATION = new BooleanProperty("sortTestsByDuration", false); public static final BooleanProperty SORT_BY_DECLARATION_ORDER = new BooleanProperty("sortTestsByDeclarationOrder", false); diff --git a/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java b/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java index a2d773e73c00..92ffc183181d 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java @@ -1,5 +1,4 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. - package com.intellij.execution.testframework; import com.intellij.execution.ExecutionBundle; @@ -44,15 +43,16 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab private final AnAction[] actionsToMerge; private final AnAction[] additionalActionsToMerge; - public ToolbarPanel(final TestConsoleProperties properties, - final JComponent parent) { + public ToolbarPanel(TestConsoleProperties properties, JComponent parent) { super(new BorderLayout()); DefaultActionGroup actionGroup = new DefaultActionGroup(); - actionGroup.addAction(new DumbAwareToggleInvertedBooleanProperty(ExecutionBundle.message("junit.run.hide.passed.action.name"), ExecutionBundle.message("junit.run.hide.passed.action.description"), + actionGroup.addAction(new DumbAwareToggleInvertedBooleanProperty(ExecutionBundle.message("junit.run.hide.passed.action.name"), + ExecutionBundle.message("junit.run.hide.passed.action.description"), AllIcons.RunConfigurations.ShowPassed, properties, TestConsoleProperties.HIDE_PASSED_TESTS)); actionGroup.add(new DumbAwareToggleInvertedBooleanProperty(TestRunnerBundle.message("action.show.ignored.text"), - TestRunnerBundle.message("action.show.ignored.description"), AllIcons.RunConfigurations.ShowIgnored, + TestRunnerBundle.message("action.show.ignored.description"), + AllIcons.RunConfigurations.ShowIgnored, properties, TestConsoleProperties.HIDE_IGNORED_TEST)); actionGroup.addSeparator(); @@ -137,8 +137,8 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab } final RunProfile configuration = properties.getConfiguration(); - if (configuration instanceof RunConfiguration) { - myExportAction = ExportTestResultsAction.create(properties.getExecutor().getToolWindowId(), (RunConfiguration)configuration, parent); + if (configuration instanceof RunConfiguration runConfiguration) { + myExportAction = ExportTestResultsAction.create(properties.getExecutor().getToolWindowId(), runConfiguration, parent); moreGroup.addAction(myExportAction); } @@ -157,9 +157,20 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab } secondaryGroup.addSeparator(); - secondaryGroup.add(new DumbAwareToggleBooleanProperty(ExecutionBundle.message("junit.running.info.scroll.to.stacktrace.action.name"), - ExecutionBundle.message("junit.running.info.scroll.to.stacktrace.action.description"), - null, properties, TestConsoleProperties.SCROLL_TO_STACK_TRACE)); + DefaultActionGroup scrollToGroup = new DefaultActionGroup(); + scrollToGroup.getTemplatePresentation().setText(ExecutionBundle.message("junit.running.info.scroll.to.group.name")); + scrollToGroup.setPopup(true); + scrollToGroup.add(new DumbAwareToggleBooleanProperty(ExecutionBundle.message("junit.running.info.scroll.to.stacktrace.action.name"), + ExecutionBundle.message("junit.running.info.scroll.to.stacktrace.action.description"), + null, properties, TestConsoleProperties.SCROLL_TO_STACK_TRACE)); + scrollToGroup.addSeparator(); + scrollToGroup.add(new DumbAwareToggleInvertedBooleanProperty(ExecutionBundle.message("junit.running.info.scroll.to.top.action.name"), + ExecutionBundle.message("junit.running.info.scroll.to.top.action.description"), + null, properties, TestConsoleProperties.SCROLL_TO_BOTTOM)); + scrollToGroup.add(new DumbAwareToggleBooleanProperty(ExecutionBundle.message("junit.running.info.scroll.to.bottom.action.name"), + ExecutionBundle.message("junit.running.info.scroll.to.bottom.action.description"), + null, properties, TestConsoleProperties.SCROLL_TO_BOTTOM)); + secondaryGroup.add(scrollToGroup); secondaryGroup.add(new ToggleBooleanProperty(ExecutionBundle.message("junit.running.info.open.source.at.exception.action.name"), ExecutionBundle.message("junit.running.info.open.source.at.exception.action.description"), null, properties, TestConsoleProperties.OPEN_FAILURE_LINE)); @@ -195,7 +206,7 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab return myOccurenceNavigator.getActionUpdateThread(); } - public void setModel(final TestFrameworkRunningModel model) { + public void setModel(TestFrameworkRunningModel model) { TestFrameworkActions.installFilterAction(model); myScrollToSource.setModel(model); myTreeExpander.setModel(model); diff --git a/platform/testRunner/src/com/intellij/execution/testframework/ui/TestsOutputConsolePrinter.java b/platform/testRunner/src/com/intellij/execution/testframework/ui/TestsOutputConsolePrinter.java index a9b5d1164a3c..1a59d690521f 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/ui/TestsOutputConsolePrinter.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/ui/TestsOutputConsolePrinter.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.execution.testframework.ui; import com.intellij.execution.filters.HyperlinkInfo; @@ -137,6 +137,10 @@ public class TestsOutputConsolePrinter implements Printer, Disposable { } private void scrollToBeginning() { + if (TestConsoleProperties.SCROLL_TO_BOTTOM.value(myProperties) && + (!TestConsoleProperties.SCROLL_TO_STACK_TRACE.value(myProperties) || myMarkOffset == 0)) { + return; + } EdtInvocationManager.invokeLaterIfNeeded(() -> { if (!myDisposed) { myConsole.performWhenNoDeferredOutput(() -> {