From 2c84bad2561ab9b126913bfd5d2340c539039883 Mon Sep 17 00:00:00 2001 From: Hoang Lam Nguyen Date: Sun, 13 Oct 2024 18:30:34 +0200 Subject: [PATCH 1/3] implement undo test removal --- .../generatedTests/GenerateTestsTabHelper.kt | 50 +++++++++++---- .../GeneratedTestsTabBuilder.kt | 3 +- .../generatedTests/GeneratedTestsTabData.kt | 3 + .../generatedTests/TestCasePanelBuilder.kt | 63 ++++++++++++++++++- .../testspark/display/utils/ReportUpdater.kt | 11 ++++ 5 files changed, 114 insertions(+), 16 deletions(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GenerateTestsTabHelper.kt b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GenerateTestsTabHelper.kt index 859e16c1a..c79c8bc93 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GenerateTestsTabHelper.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GenerateTestsTabHelper.kt @@ -2,27 +2,53 @@ package org.jetbrains.research.testspark.display.generatedTests object GenerateTestsTabHelper { /** - * A helper method to remove a test case from the cache and from the UI. + * A helper method to remove a test case from the cache. * * @param testCaseName the name of the test */ fun removeTestCase(testCaseName: String, generatedTestsTabData: GeneratedTestsTabData) { - // Update the number of selected test cases if necessary - if (generatedTestsTabData.testCaseNameToSelectedCheckbox[testCaseName]!!.isSelected) { - generatedTestsTabData.testsSelected-- - } - - // Remove the test panel from the UI - generatedTestsTabData.allTestCasePanel.remove(generatedTestsTabData.testCaseNameToPanel[testCaseName]) - // Remove the test panel - generatedTestsTabData.testCaseNameToPanel.remove(testCaseName) + val panel = generatedTestsTabData.testCaseNameToPanel.remove(testCaseName) // Remove the selected checkbox - generatedTestsTabData.testCaseNameToSelectedCheckbox.remove(testCaseName) + val checkbox = generatedTestsTabData.testCaseNameToSelectedCheckbox.remove(testCaseName) // Remove the editorTextField - generatedTestsTabData.testCaseNameToEditorTextField.remove(testCaseName) + val editorTextField = generatedTestsTabData.testCaseNameToEditorTextField.remove(testCaseName) + + // Save data for possible restoration + val deletedTest = DeletedTest(panel!!, checkbox!!, editorTextField!!) + generatedTestsTabData.testCaseNameToDeletedTestData[testCaseName] = deletedTest + } + + /** + * A helper method to restore a previously deleted test case to the cache. + * + * @param testCaseName the name of the test + */ + fun restoreTestCase(testCaseName: String, generatedTestsTabData: GeneratedTestsTabData) { + // Retrieve information about previously deleted test + val deletedTest = generatedTestsTabData.testCaseNameToDeletedTestData.remove(testCaseName)!! + + // Re-add the test panel + generatedTestsTabData.testCaseNameToPanel[testCaseName] = deletedTest.panel + + // Re-add the selected checkbox + generatedTestsTabData.testCaseNameToSelectedCheckbox[testCaseName] = deletedTest.checkbox + + // Re-add the editorTextField + generatedTestsTabData.testCaseNameToEditorTextField[testCaseName] = deletedTest.editorTextField + } + + /** + * A helper method to remove all test cases from the cache and UI. + */ + fun clear(generatedTestsTabData: GeneratedTestsTabData) { + generatedTestsTabData.allTestCasePanel.removeAll() + generatedTestsTabData.testCaseNameToPanel.clear() + generatedTestsTabData.testCaseNameToSelectedCheckbox.clear() + generatedTestsTabData.testCaseNameToEditorTextField.clear() + generatedTestsTabData.testCaseNameToDeletedTestData.clear() } /** diff --git a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GeneratedTestsTabBuilder.kt b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GeneratedTestsTabBuilder.kt index bdde60d9b..835c454c7 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GeneratedTestsTabBuilder.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GeneratedTestsTabBuilder.kt @@ -245,8 +245,7 @@ class GeneratedTestsTabBuilder( * Clears all the generated test cases from the UI and the internal cache. */ fun clear() { - generatedTestsTabData.testCaseNameToPanel.toMap() - .forEach { GenerateTestsTabHelper.removeTestCase(it.key, generatedTestsTabData) } + GenerateTestsTabHelper.clear(generatedTestsTabData) generatedTestsTabData.testCasePanelFactories.clear() generatedTestsTabData.topButtonsPanelBuilder.clear(generatedTestsTabData) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GeneratedTestsTabData.kt b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GeneratedTestsTabData.kt index 97da647b9..59c14618f 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GeneratedTestsTabData.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/GeneratedTestsTabData.kt @@ -14,6 +14,7 @@ class GeneratedTestsTabData { val testCaseNameToPanel: HashMap = HashMap() val testCaseNameToSelectedCheckbox: HashMap = HashMap() val testCaseNameToEditorTextField: HashMap = HashMap() + val testCaseNameToDeletedTestData: HashMap = HashMap() var testsSelected: Int = 0 val unselectedTestCases: HashMap = HashMap() val testCasePanelFactories: ArrayList = arrayListOf() @@ -28,3 +29,5 @@ class GeneratedTestsTabData { var contentManager: ContentManager? = null var content: Content? = null } + +data class DeletedTest(val panel: JPanel, val checkbox: JCheckBox, val editorTextField: EditorTextField) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt index 09ad48f01..7e4acf6a5 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt @@ -52,6 +52,7 @@ import java.awt.Dimension import java.awt.Toolkit import java.awt.datatransfer.Clipboard import java.awt.datatransfer.StringSelection +import java.awt.event.MouseAdapter import java.util.Queue import javax.swing.Box import javax.swing.BoxLayout @@ -60,6 +61,7 @@ import javax.swing.JCheckBox import javax.swing.JLabel import javax.swing.JOptionPane import javax.swing.JPanel +import javax.swing.OverlayLayout import javax.swing.ScrollPaneConstants import javax.swing.SwingUtilities import javax.swing.border.Border @@ -302,7 +304,16 @@ class TestCasePanelBuilder( } resetButton.addActionListener { reset() } resetToLastRunButton.addActionListener { resetToLastRun() } - removeButton.addActionListener { remove() } + + val deletedTestPanel = createDeletedTestPanel() + removeButton.addActionListener { + enableLocalComponents(false) + deletedTestPanel.isVisible = true + languageTextField.isEnabled = false + checkbox.isSelected = false + checkbox.isEnabled = false + remove() + } sendButton.addActionListener { sendRequest() } @@ -313,7 +324,44 @@ class TestCasePanelBuilder( requestComboBox.preferredSize = Dimension(0, 0) requestComboBox.isEditable = true - return panel + val overlayPanel = object: JPanel() { + override fun isOptimizedDrawingEnabled() = false + }.apply { + layout = OverlayLayout(this) + add(deletedTestPanel) + add(panel) + } + + return overlayPanel + } + + /** + * Creates the panel that will be displayed as the bottom panel for a deleted test case. + */ + private fun createDeletedTestPanel(): JPanel { + val deletedTestPanel = JPanel().apply { + this.isVisible = false + this.addMouseListener(object: MouseAdapter() {}) + }; + + deletedTestPanel.add(Box.createRigidArea(Dimension(15, 0))) + deletedTestPanel.add( JLabel("This test case has been deleted.")) + deletedTestPanel.add(Box.createHorizontalGlue()) + + val undoButton = JButton("Undo") + deletedTestPanel.add(undoButton) + deletedTestPanel.add(Box.createRigidArea(Dimension(12, 0))) + + undoButton.addActionListener { + deletedTestPanel.isVisible = false + languageTextField.isEnabled = true + checkbox.isSelected = true + checkbox.isEnabled = true + enableLocalComponents(true) + restore() + } + + return deletedTestPanel } /** @@ -638,6 +686,17 @@ class TestCasePanelBuilder( GenerateTestsTabHelper.update(generatedTestsTabData) } + private fun restore() { + GenerateTestsTabHelper.restoreTestCase(testCase.testName, generatedTestsTabData) + + runTestButton.isEnabled = true + isRemoved = false + + ReportUpdater.restoreTestCase(report, testCase, coverageVisualisationTabBuilder, generatedTestsTabData) + + GenerateTestsTabHelper.update(generatedTestsTabData) + } + /** * Determines if the "Run" button is enabled. * diff --git a/src/main/kotlin/org/jetbrains/research/testspark/display/utils/ReportUpdater.kt b/src/main/kotlin/org/jetbrains/research/testspark/display/utils/ReportUpdater.kt index 5eea34f19..662cd6728 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/display/utils/ReportUpdater.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/display/utils/ReportUpdater.kt @@ -29,6 +29,17 @@ object ReportUpdater { coverageVisualisationTabBuilder.show(report, generatedTestsTabData) } + fun restoreTestCase( + report: Report, + testCase: TestCase, + coverageVisualisationTabBuilder: CoverageVisualisationTabBuilder, + generatedTestsTabData: GeneratedTestsTabData, + ) { + report.testCaseList[testCase.id] = testCase + report.normalized() + coverageVisualisationTabBuilder.show(report, generatedTestsTabData) + } + fun unselectTestCase( report: Report, unselectedTestCases: HashMap, From 1d580af4c56132a776d8803be66ae66678ffb9db Mon Sep 17 00:00:00 2001 From: Hoang Lam Nguyen Date: Sun, 13 Oct 2024 19:41:17 +0200 Subject: [PATCH 2/3] ktlint --- .../display/generatedTests/TestCasePanelBuilder.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt index 7e4acf6a5..71af5933b 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt @@ -324,8 +324,8 @@ class TestCasePanelBuilder( requestComboBox.preferredSize = Dimension(0, 0) requestComboBox.isEditable = true - val overlayPanel = object: JPanel() { - override fun isOptimizedDrawingEnabled() = false + val overlayPanel = object : JPanel() { + override fun isOptimizedDrawingEnabled() = false }.apply { layout = OverlayLayout(this) add(deletedTestPanel) @@ -341,11 +341,11 @@ class TestCasePanelBuilder( private fun createDeletedTestPanel(): JPanel { val deletedTestPanel = JPanel().apply { this.isVisible = false - this.addMouseListener(object: MouseAdapter() {}) - }; + this.addMouseListener(object : MouseAdapter() {}) + } deletedTestPanel.add(Box.createRigidArea(Dimension(15, 0))) - deletedTestPanel.add( JLabel("This test case has been deleted.")) + deletedTestPanel.add(JLabel("This test case has been deleted.")) deletedTestPanel.add(Box.createHorizontalGlue()) val undoButton = JButton("Undo") From 133cc89f366900e251636cbeee9d1d1f63c750a0 Mon Sep 17 00:00:00 2001 From: Hoang Lam Nguyen Date: Wed, 16 Oct 2024 23:04:45 +0200 Subject: [PATCH 3/3] refactor --- .../generatedTests/TestCasePanelBuilder.kt | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt index 71af5933b..cc40e4692 100644 --- a/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt +++ b/src/main/kotlin/org/jetbrains/research/testspark/display/generatedTests/TestCasePanelBuilder.kt @@ -307,11 +307,7 @@ class TestCasePanelBuilder( val deletedTestPanel = createDeletedTestPanel() removeButton.addActionListener { - enableLocalComponents(false) deletedTestPanel.isVisible = true - languageTextField.isEnabled = false - checkbox.isSelected = false - checkbox.isEnabled = false remove() } @@ -354,10 +350,6 @@ class TestCasePanelBuilder( undoButton.addActionListener { deletedTestPanel.isVisible = false - languageTextField.isEnabled = true - checkbox.isSelected = true - checkbox.isEnabled = true - enableLocalComponents(true) restore() } @@ -678,7 +670,13 @@ class TestCasePanelBuilder( // Remove the test case from the cache GenerateTestsTabHelper.removeTestCase(testCase.testName, generatedTestsTabData) + // Disable UI + enableLocalComponents(false) + languageTextField.isEnabled = false + checkbox.isSelected = false + checkbox.isEnabled = false runTestButton.isEnabled = false + isRemoved = true ReportUpdater.removeTestCase(report, testCase, coverageVisualisationTabBuilder, generatedTestsTabData) @@ -687,9 +685,16 @@ class TestCasePanelBuilder( } private fun restore() { + // Restore test case to cache GenerateTestsTabHelper.restoreTestCase(testCase.testName, generatedTestsTabData) + // Enable UI + enableLocalComponents(true) + languageTextField.isEnabled = true + checkbox.isSelected = true + checkbox.isEnabled = true runTestButton.isEnabled = true + isRemoved = false ReportUpdater.restoreTestCase(report, testCase, coverageVisualisationTabBuilder, generatedTestsTabData)