Skip to content

Commit

Permalink
fix "IllegalArgumentException: Detected multithreaded access to Snaps…
Browse files Browse the repository at this point in the history
…hotStateObserver" in tests by workaround
  • Loading branch information
sunny-chung committed May 1, 2024
1 parent c5e62d8 commit 3a8848b
Showing 1 changed file with 34 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -380,24 +380,24 @@ fun ComposeUiTest.createProjectIfNeeded() {
if (onAllNodesWithTag(TestTag.FirstTimeCreateProjectButton.name).fetchSemanticsNodes().isNotEmpty()) {
// create first project
onNodeWithTag(TestTag.FirstTimeCreateProjectButton.name)
.performClick()
.performClickWithRetry(this)
waitUntilExactlyOneExists(hasTestTag(TestTag.ProjectNameAndSubprojectNameDialogTextField.name), 500L)
onNodeWithTag(TestTag.ProjectNameAndSubprojectNameDialogTextField.name)
.performTextInput("Test Project")
waitForIdle()
onNodeWithTag(TestTag.ProjectNameAndSubprojectNameDialogDoneButton.name)
.performClick()
.performClickWithRetry(this)

// create first subproject
waitUntilExactlyOneExists(hasTestTag(TestTag.FirstTimeCreateSubprojectButton.name), 500L)
onNodeWithTag(TestTag.FirstTimeCreateSubprojectButton.name)
.performClick()
.performClickWithRetry(this)
waitUntilExactlyOneExists(hasTestTag(TestTag.ProjectNameAndSubprojectNameDialogTextField.name), 500L)
onNodeWithTag(TestTag.ProjectNameAndSubprojectNameDialogTextField.name)
.performTextInput("Test Subproject")
waitForIdle()
onNodeWithTag(TestTag.ProjectNameAndSubprojectNameDialogDoneButton.name)
.performClick()
.performClickWithRetry(this)

println("created first project and subproject")
}
Expand All @@ -409,11 +409,11 @@ suspend fun ComposeUiTest.createAndSendHttpRequest(request: UserRequestTemplate,
val baseExample = request.examples.first()

onNodeWithTag(TestTag.CreateRequestOrFolderButton.name)
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performClickWithRetry(this)
waitUntilExactlyOneExists(hasTextExactly("Request", includeEditableText = false))
onNodeWithText("Request")
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performClickWithRetry(this)
waitUntilExactlyOneExists(hasTestTag(TestTag.RequestUrlTextField.name), 1000L)

Expand All @@ -422,33 +422,33 @@ suspend fun ComposeUiTest.createAndSendHttpRequest(request: UserRequestTemplate,
if (request.application == ProtocolApplication.Http && request.method != "GET") {
// TODO support custom method
onNodeWithTag(buildTestTag(TestTagPart.RequestMethodDropdown, TestTagPart.DropdownButton)!!)
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performClickWithRetry(this)

val nextTag = buildTestTag(TestTagPart.RequestMethodDropdown, TestTagPart.DropdownItem, request.method)!!
waitUntilExactlyOneExists(hasTestTag(nextTag))
onNodeWithTag(nextTag)
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performClickWithRetry(this)

delayShort()
}

onNodeWithTag(TestTag.RequestUrlTextField.name)
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performTextInput(request.url)

delayShort()

if (baseExample.contentType != ContentType.None) {
onNodeWithTag(buildTestTag(TestTagPart.RequestBodyTypeDropdown, TestTagPart.DropdownButton)!!)
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performClickWithRetry(this)

val nextTag = buildTestTag(TestTagPart.RequestBodyTypeDropdown, TestTagPart.DropdownItem, baseExample.contentType.displayText)!!
waitUntilExactlyOneExists(hasTestTag(nextTag))
onNodeWithTag(nextTag)
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performClickWithRetry(this)

delayShort()
Expand All @@ -458,7 +458,7 @@ suspend fun ComposeUiTest.createAndSendHttpRequest(request: UserRequestTemplate,
val body = (baseExample.body as StringBody).value
if (body.isNotEmpty()) {
onNodeWithTag(TestTag.RequestStringBodyTextField.name)
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performTextInput(body)
delayShort()
}
Expand All @@ -470,15 +470,15 @@ suspend fun ComposeUiTest.createAndSendHttpRequest(request: UserRequestTemplate,
waitUntilExactlyOneExists(hasTestTag(buildTestTag(TestTagPart.RequestBodyFormUrlEncodedForm, TestTagPart.Current, TestTagPart.Key, index)!!))
waitUntilExactlyOneExists(hasTestTag(buildTestTag(TestTagPart.RequestBodyFormUrlEncodedForm, TestTagPart.Current, TestTagPart.Value, index)!!))
onNode(hasTestTag(buildTestTag(TestTagPart.RequestBodyFormUrlEncodedForm, TestTagPart.Current, TestTagPart.Key, index)!!))
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performTextInput(it.key)
delayShort()

onNode(hasTestTag(buildTestTag(TestTagPart.RequestBodyFormUrlEncodedForm, TestTagPart.Current, TestTagPart.Key, index)!!))
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.assertTextEquals(it.key)
onNode(hasTestTag(buildTestTag(TestTagPart.RequestBodyFormUrlEncodedForm, TestTagPart.Current, TestTagPart.Value, index)!!))
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performTextInput(it.value)
delayShort()
}
Expand All @@ -491,39 +491,39 @@ suspend fun ComposeUiTest.createAndSendHttpRequest(request: UserRequestTemplate,

if (baseExample.queryParameters.isNotEmpty()) {
onNode(hasTestTag(TestTag.RequestParameterTypeTab.name).and(hasTextExactly("Query")))
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performClickWithRetry(this)

baseExample.queryParameters.forEachIndexed { index, it ->
waitUntilExactlyOneExists(hasTestTag(buildTestTag(TestTagPart.RequestQueryParameter, TestTagPart.Current, TestTagPart.Key, index)!!))
waitUntilExactlyOneExists(hasTestTag(buildTestTag(TestTagPart.RequestQueryParameter, TestTagPart.Current, TestTagPart.Value, index)!!))
onNode(hasTestTag(buildTestTag(TestTagPart.RequestQueryParameter, TestTagPart.Current, TestTagPart.Key, index)!!))
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performTextInput(it.key)
delayShort()
onNode(hasTestTag(buildTestTag(TestTagPart.RequestQueryParameter, TestTagPart.Current, TestTagPart.Key, index)!!))
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.assertTextEquals(it.key)
onNode(hasTestTag(buildTestTag(TestTagPart.RequestQueryParameter, TestTagPart.Current, TestTagPart.Value, index)!!))
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performTextInput(it.value)
delayShort()
}
}

if (baseExample.headers.isNotEmpty()) {
onNode(hasTestTag(TestTag.RequestParameterTypeTab.name).and(hasTextExactly("Header")))
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performClickWithRetry(this)
baseExample.headers.forEachIndexed { index, it ->
waitUntilExactlyOneExists(hasTestTag(buildTestTag(TestTagPart.RequestHeader, TestTagPart.Current, TestTagPart.Key, index)!!))
waitUntilExactlyOneExists(hasTestTag(buildTestTag(TestTagPart.RequestHeader, TestTagPart.Current, TestTagPart.Value, index)!!))
onNode(hasTestTag(buildTestTag(TestTagPart.RequestHeader, TestTagPart.Current, TestTagPart.Key, index)!!))
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performTextInput(it.key)
delayShort()
onNode(hasTestTag(buildTestTag(TestTagPart.RequestHeader, TestTagPart.Current, TestTagPart.Value, index)!!))
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performTextInput(it.value)
delayShort()
}
Expand All @@ -535,7 +535,7 @@ suspend fun ComposeUiTest.createAndSendHttpRequest(request: UserRequestTemplate,
waitForIdle()

onNodeWithTag(TestTag.RequestFireOrDisconnectButton.name)
.assertIsDisplayed()
.assertIsDisplayedWithRetry(this)
.performClickWithRetry(this)
waitForIdle()

Expand Down Expand Up @@ -602,6 +602,17 @@ fun SemanticsNodeInteraction.performClickWithRetry(host: ComposeUiTest): Semanti
}
}

fun SemanticsNodeInteraction.assertIsDisplayedWithRetry(host: ComposeUiTest): SemanticsNodeInteraction {
while (true) {
try {
assertIsDisplayed()
return this
} catch (e: IllegalArgumentException) {
host.waitForIdle()
}
}
}

fun SemanticsNode.getTexts(): List<String> {
val actual = mutableListOf<String>()
config.getOrNull(SemanticsProperties.EditableText)
Expand Down

0 comments on commit 3a8848b

Please sign in to comment.