Skip to content

Commit 32eeb76

Browse files
chore: improvements on flakiness of UI tests INTELLIJ-107 (#78)
1 parent 212a300 commit 32eeb76

File tree

21 files changed

+864
-324
lines changed

21 files changed

+864
-324
lines changed

.github/workflows/quality-check.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ jobs:
213213
path: |
214214
**/build/reports/**/*.html
215215
**/build/reports/**/*.log
216-
**/build/reports/*/*.png
216+
**/build/reports/**/*.png
217217
**/build/idea-sandbox/system/**/*.log
218218
**/build/idea-sandbox/system-test/**/*.log
219219
**/video/**/*.avi

packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/editor/inputs/DataSourceComboBox.kt

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package com.mongodb.jbplugin.editor.inputs
22

33
import com.intellij.database.dataSource.LocalDataSource
4+
import com.intellij.openapi.application.ApplicationManager
5+
import com.intellij.openapi.application.ModalityState
46
import com.intellij.openapi.project.Project
57
import com.intellij.openapi.ui.ComboBox
68
import com.intellij.openapi.ui.asSequence
79
import com.intellij.sql.indexOf
810
import com.intellij.ui.AnimatedIcon.ANIMATION_IN_RENDERER_ALLOWED
911
import com.intellij.ui.components.JBLabel
1012
import com.mongodb.jbplugin.accessadapter.datagrip.adapter.isConnected
13+
import com.mongodb.jbplugin.editor.models.ToolbarState
1114
import com.mongodb.jbplugin.editor.models.getToolbarModel
1215
import com.mongodb.jbplugin.i18n.Icons
1316
import com.mongodb.jbplugin.i18n.Icons.scaledToText
@@ -98,15 +101,10 @@ class DataSourceComboBox(
98101
var isFirstInit = true
99102
coroutineScope.launch {
100103
project.getToolbarModel().toolbarState.collect { state ->
101-
withoutSelectionChangedListener {
102-
selectedDataSourceConnecting = state.selectedDataSourceConnecting
103-
selectedDataSourceFailedConnecting = state.selectedDataSourceConnectionFailed
104-
if (isFirstInit || state.dataSources != dataSources) {
105-
isFirstInit = false
106-
populateComboBoxWithDataSources(state.dataSources)
107-
}
108-
selectDataSourceByUniqueId(state.selectedDataSource?.uniqueId)
109-
}
104+
ApplicationManager.getApplication().invokeLater({
105+
updateComboBoxState(state, isFirstInit)
106+
isFirstInit = false
107+
}, ModalityState.stateForComponent(comboBoxComponent))
110108
}
111109
}
112110
}
@@ -120,11 +118,28 @@ class DataSourceComboBox(
120118
}
121119
}
122120

123-
private fun populateComboBoxWithDataSources(dataSources: List<LocalDataSource>) {
124-
comboBoxModel.removeAllElements()
125-
// First item is purposely a null to render "Detach data source label"
126-
comboBoxModel.addElement(null)
127-
comboBoxModel.addAll(dataSources)
121+
private fun updateComboBoxState(state: ToolbarState, isFirstInit: Boolean) = withoutSelectionChangedListener {
122+
selectedDataSourceConnecting = state.selectedDataSourceConnecting
123+
selectedDataSourceFailedConnecting = state.selectedDataSourceConnectionFailed
124+
if (isFirstInit || state.dataSources != dataSources) {
125+
populateComboBoxWithDataSources(state.dataSources.toSet())
126+
}
127+
selectDataSourceByUniqueId(state.selectedDataSource?.uniqueId)
128+
}
129+
130+
private fun populateComboBoxWithDataSources(newDataSources: Set<LocalDataSource>) {
131+
val oldDataSources = dataSources.toSet()
132+
133+
val dataSourcesToAdd = newDataSources - oldDataSources
134+
val dataSourcesToRemove = oldDataSources - newDataSources
135+
136+
dataSourcesToAdd.forEach { comboBoxModel.addElement(it) }
137+
dataSourcesToRemove.forEach { comboBoxModel.removeElement(it) }
138+
139+
if (comboBoxModel.getIndexOf(null) != 0) {
140+
comboBoxModel.removeElement(null)
141+
comboBoxModel.insertElementAt(null, 0)
142+
}
128143
}
129144

130145
private fun selectDataSourceByUniqueId(uniqueId: String?) {

packages/jetbrains-plugin/src/main/kotlin/com/mongodb/jbplugin/editor/inputs/DatabaseComboBox.kt

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package com.mongodb.jbplugin.editor.inputs
22

3+
import com.intellij.openapi.application.ApplicationManager
4+
import com.intellij.openapi.application.ModalityState
35
import com.intellij.openapi.project.Project
46
import com.intellij.openapi.ui.ComboBox
57
import com.intellij.openapi.ui.asSequence
68
import com.intellij.ui.AnimatedIcon.ANIMATION_IN_RENDERER_ALLOWED
79
import com.intellij.ui.components.JBLabel
10+
import com.mongodb.jbplugin.editor.models.ToolbarState
811
import com.mongodb.jbplugin.editor.models.getToolbarModel
912
import com.mongodb.jbplugin.i18n.Icons
1013
import com.mongodb.jbplugin.i18n.Icons.scaledToText
@@ -78,14 +81,10 @@ class DatabaseComboBox(
7881
var isFirstInit = true
7982
coroutineScope.launch {
8083
project.getToolbarModel().toolbarState.collect { state ->
81-
withoutSelectionChangedListener {
82-
loadingDatabases = state.databasesLoadingForSelectedDataSource
83-
if (isFirstInit || state.databases != databases) {
84-
isFirstInit = false
85-
populateComboBoxWithDatabases(state.databases)
86-
}
87-
selectDatabaseAndNotify(state.selectedDatabase)
88-
}
84+
ApplicationManager.getApplication().invokeLater({
85+
updateComboBoxState(state, isFirstInit)
86+
isFirstInit = false
87+
}, ModalityState.stateForComponent(comboBoxComponent))
8988
}
9089
}
9190
}
@@ -99,11 +98,27 @@ class DatabaseComboBox(
9998
}
10099
}
101100

102-
private fun populateComboBoxWithDatabases(databases: List<String>) {
103-
comboBoxModel.removeAllElements()
104-
// First item is purposely a null to render "Detach data source label"
105-
comboBoxModel.addElement(null)
106-
comboBoxModel.addAll(databases)
101+
private fun updateComboBoxState(state: ToolbarState, isFirstInit: Boolean) = withoutSelectionChangedListener {
102+
loadingDatabases = state.databasesLoadingForSelectedDataSource
103+
if (isFirstInit || state.databases != databases) {
104+
populateComboBoxWithDatabases(state.databases.toSet())
105+
}
106+
selectDatabaseAndNotify(state.selectedDatabase)
107+
}
108+
109+
private fun populateComboBoxWithDatabases(newDatabases: Set<String>) {
110+
val oldDatabases = databases.toSet()
111+
112+
val databasesToAdd = newDatabases - oldDatabases
113+
val databasesToRemove = oldDatabases - newDatabases
114+
115+
databasesToAdd.forEach { comboBoxModel.addElement(it) }
116+
databasesToRemove.forEach { comboBoxModel.removeElement(it) }
117+
118+
if (comboBoxModel.getIndexOf(null) != 0) {
119+
comboBoxModel.removeElement(null)
120+
comboBoxModel.insertElementAt(null, 0)
121+
}
107122
}
108123

109124
private fun selectDatabaseAndNotify(database: String?) {

packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/codeActions/impl/MongoDbRunQueryActionUiTest.kt

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ package com.mongodb.jbplugin.codeActions.impl
22

33
import com.intellij.remoterobot.RemoteRobot
44
import com.mongodb.jbplugin.fixtures.*
5-
import com.mongodb.jbplugin.fixtures.components.findJavaEditorToolbar
6-
import com.mongodb.jbplugin.fixtures.components.findJavaEditorToolbarPopup
7-
import com.mongodb.jbplugin.fixtures.components.findRunQueryGutter
85
import com.mongodb.jbplugin.fixtures.components.idea.ideaFrame
6+
import com.mongodb.jbplugin.fixtures.components.openRunQueryPopup
97
import org.junit.jupiter.api.AfterEach
10-
import org.junit.jupiter.api.Assertions.assertTrue
8+
import org.junit.jupiter.api.Assertions.*
119
import org.junit.jupiter.api.BeforeEach
1210
import org.junit.jupiter.api.Test
1311
import kotlin.time.Duration.Companion.minutes
12+
import kotlin.time.Duration.Companion.seconds
13+
import kotlin.time.toJavaDuration
1414

1515
@UiTest
1616
@RequiresMongoDbCluster
@@ -20,6 +20,7 @@ class MongoDbRunQueryActionUiTest {
2020
remoteRobot: RemoteRobot,
2121
url: MongoDbServerUrl,
2222
) {
23+
remoteRobot.ideaFrame().cleanDataSources()
2324
remoteRobot.ideaFrame().addDataSourceWithUrl(javaClass.simpleName, url)
2425
}
2526

@@ -34,8 +35,7 @@ class MongoDbRunQueryActionUiTest {
3435
remoteRobot.ideaFrame().openFile(
3536
"/src/main/java/alt/mongodb/javadriver/JavaDriverRepository.java"
3637
)
37-
remoteRobot.findRunQueryGutter(atLine = 24)!!.click()
38-
val popup = remoteRobot.findJavaEditorToolbarPopup()
38+
val popup = remoteRobot.openRunQueryPopup(atLine = 24)
3939
popup.cancel()
4040
}
4141

@@ -45,16 +45,11 @@ class MongoDbRunQueryActionUiTest {
4545
remoteRobot.ideaFrame().openFile(
4646
"/src/main/java/alt/mongodb/javadriver/JavaDriverRepository.java"
4747
)
48-
remoteRobot.findJavaEditorToolbar().detachDataSource()
49-
remoteRobot.findRunQueryGutter(atLine = 24)!!.click()
50-
// because we are disconnected, we should now try to connect
51-
val popup = remoteRobot.findJavaEditorToolbarPopup()
52-
popup.dataSources.selectItem(
53-
javaClass.simpleName
54-
)
48+
val popup = remoteRobot.openRunQueryPopup(atLine = 24)
49+
popup.selectDataSource(javaClass.simpleName)
5550
popup.ok("Run Query", timeout = 1.minutes)
5651
// check that we open a console
57-
eventually {
52+
eventually(30.seconds.toJavaDuration()) {
5853
val currentEditor = remoteRobot.ideaFrame().currentTab()
5954
assertTrue(currentEditor.editor.fileName.startsWith("console"))
6055
}

packages/jetbrains-plugin/src/test/kotlin/com/mongodb/jbplugin/editor/javaEditor/JavaDriverToolbarVisibilityUiTest.kt

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ import com.mongodb.jbplugin.fixtures.components.findJavaEditorToolbar
66
import com.mongodb.jbplugin.fixtures.components.idea.ideaFrame
77
import com.mongodb.jbplugin.fixtures.components.isJavaEditorToolbarHidden
88
import org.junit.jupiter.api.AfterEach
9-
import org.junit.jupiter.api.Assertions.assertFalse
10-
import org.junit.jupiter.api.Assertions.assertTrue
9+
import org.junit.jupiter.api.Assertions.*
1110
import org.junit.jupiter.api.BeforeEach
1211
import org.junit.jupiter.api.Test
1312
import kotlin.time.Duration.Companion.minutes
@@ -21,6 +20,7 @@ class JavaDriverToolbarVisibilityUiTest {
2120
remoteRobot: RemoteRobot,
2221
url: MongoDbServerUrl,
2322
) {
23+
remoteRobot.ideaFrame().cleanDataSources()
2424
remoteRobot.ideaFrame().addDataSourceWithUrl(javaClass.simpleName, url)
2525
}
2626

@@ -30,7 +30,7 @@ class JavaDriverToolbarVisibilityUiTest {
3030
}
3131

3232
@Test
33-
@RequiresProject("basic-java-project-with-mongodb")
33+
@RequiresProject("basic-java-project-with-mongodb", smartMode = true)
3434
fun `shows the toolbar in a java file with references to the driver`(remoteRobot: RemoteRobot) {
3535
remoteRobot.ideaFrame().openFile(
3636
"/src/main/java/alt/mongodb/javadriver/JavaDriverRepository.java"
@@ -40,7 +40,7 @@ class JavaDriverToolbarVisibilityUiTest {
4040
}
4141

4242
@Test
43-
@RequiresProject("basic-java-project-with-mongodb")
43+
@RequiresProject("basic-java-project-with-mongodb", smartMode = true)
4444
fun `shows the toolbar in all the java files with references to the driver`(
4545
remoteRobot: RemoteRobot
4646
) {
@@ -63,7 +63,7 @@ class JavaDriverToolbarVisibilityUiTest {
6363
}
6464

6565
@Test
66-
@RequiresProject("basic-java-project-with-mongodb")
66+
@RequiresProject("basic-java-project-with-mongodb", smartMode = true)
6767
fun `does not show the toolbar in a java file without references to the driver`(
6868
remoteRobot: RemoteRobot
6969
) {
@@ -74,7 +74,7 @@ class JavaDriverToolbarVisibilityUiTest {
7474
}
7575

7676
@Test
77-
@RequiresProject("basic-java-project-with-mongodb")
77+
@RequiresProject("basic-java-project-with-mongodb", smartMode = true)
7878
fun `does show existing data sources in the combo box`(
7979
remoteRobot: RemoteRobot,
8080
url: MongoDbServerUrl,
@@ -88,7 +88,7 @@ class JavaDriverToolbarVisibilityUiTest {
8888
}
8989

9090
@Test
91-
@RequiresProject("basic-java-project-with-mongodb")
91+
@RequiresProject("basic-java-project-with-mongodb", smartMode = true)
9292
fun `does not show the database select on a java driver file`(
9393
remoteRobot: RemoteRobot,
9494
url: MongoDbServerUrl,
@@ -102,7 +102,7 @@ class JavaDriverToolbarVisibilityUiTest {
102102
}
103103

104104
@Test
105-
@RequiresProject("basic-java-project-with-mongodb")
105+
@RequiresProject("basic-java-project-with-mongodb", smartMode = true)
106106
fun `does show the database select on a spring criteria file`(
107107
remoteRobot: RemoteRobot,
108108
url: MongoDbServerUrl,
@@ -114,34 +114,31 @@ class JavaDriverToolbarVisibilityUiTest {
114114
val toolbar = remoteRobot.findJavaEditorToolbar()
115115
assertTrue(toolbar.hasDatabasesComboBox)
116116

117-
eventually(1.minutes.toJavaDuration()) {
118-
// when we select a cluster, it will connect asynchronously
119-
toolbar.dataSources.selectItem(javaClass.simpleName)
120-
}
117+
toolbar.selectDataSource(javaClass.simpleName)
118+
121119
eventually(1.minutes.toJavaDuration()) {
122120
// it can take a few seconds, we will retry every few milliseconds
123121
// but wait at least for a minute if we can't select a database
124-
toolbar.databases.selectItem("admin")
122+
toolbar.selectDatabase("admin")
125123
}
126124
}
127125

128126
@Test
129-
@RequiresProject("basic-java-project-with-mongodb")
127+
@RequiresProject("basic-java-project-with-mongodb", smartMode = true)
130128
fun `shows the toolbar when a reference to the driver is added`(
131129
remoteRobot: RemoteRobot,
132130
url: MongoDbServerUrl,
133131
) {
134-
assertTrue(remoteRobot.isJavaEditorToolbarHidden())
135-
136132
remoteRobot.ideaFrame().openFile(
137133
"/src/main/java/alt/mongodb/javadriver/NoDriverReference.java"
138134
)
135+
assertTrue(remoteRobot.isJavaEditorToolbarHidden())
139136
val editor = remoteRobot.ideaFrame().currentTab().editor
140137
val textBeforeChanges = editor.text
141138

142139
editor.insertTextAtLine(1, 0, "import com.mongodb.client.MongoClient;")
143-
144-
remoteRobot.findJavaEditorToolbar()
145-
editor.text = textBeforeChanges.replace("\n", "\\\n")
140+
assertTrue(remoteRobot.findJavaEditorToolbar().isShowing)
141+
editor.replaceText("import com.mongodb.client.MongoClient;", "")
142+
assertTrue(remoteRobot.isJavaEditorToolbarHidden())
146143
}
147144
}

0 commit comments

Comments
 (0)