3

Given some simple content:

@Composable
fun MyContent() {
    var showThing by remember { mutableStateOf(false) }
    if (showThing) {
        Box(Modifier.testTag("thing")) {
            Text("The Thing")
        }
    }
}

If I try to test whether the thing has been displayed:

@OptIn(ExperimentalTestApi::class)
class Scratch {
    @get:Rule
    val compose = createComposeRule()

    @Test
    fun test() {
        runBlocking(Dispatchers.Main) {
            compose.setContent {
                MyContent()
            }
            compose.awaitIdle()

            compose.onNodeWithTag("thing").assertIsNotDisplayed()
        }
    }
}

I get this:

An operation is not implemented.
kotlin.NotImplementedError: An operation is not implemented.
    at androidx.compose.ui.test.DesktopAssertions_desktopKt.checkIsDisplayed(DesktopAssertions.desktop.kt:23)
    at androidx.compose.ui.test.AssertionsKt.assertIsNotDisplayed(Assertions.kt:49)
    at Scratch$test$1.invokeSuspend(Scratch.kt:44)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    ...

I thought testing whether something was displayed or not would be the most basic thing to test, but it isn't supported by the framework yet. The test framework is experimental, so I was expecting to find things missing, but not like this.

Is there another way to do this which I'm missing? All the tutorials out there talk about assertIsDisplayed() being the way, but maybe there is an alternative?

Hakanai
  • 12,010
  • 10
  • 62
  • 132
  • Which version of Compose are you using? – Pstr May 13 '22 at 16:07
  • @Pstr would have been whatever was cutting edge at the time the question was asked. Every time I open the project to try and get more stuff to work, I update everything to see whether I get a working system yet. – Hakanai May 16 '22 at 23:50

1 Answers1

6

It's not a direct substitute, but unfortunately, JB Compose Desktop has these limitations in the UI test suite. Aside from using only JUnit 4, and not being compatible with the newer version, many assertion methods and also screen interaction methods are not implemented, such as the .assertIsNotDisplayed() that you tried to use, and also actions like .performTextInput().

An alternative for your problem would be using other methods like .assertDoesNotExist() and .assertExists().

It's not going to tell you if the element is in the boundaries of the screen and visible, but at least will tell you that your node exists and is instantiated, which is something, and it's better than nothing.

Until JetBrains implement the complete desktop test suite, we need to work with what we have, or maybe try implementing some things as a workaround.

In your case, this will work:

@OptIn(ExperimentalTestApi::class)
class Scratch {
    @get:Rule
    val compose = createComposeRule()

@Test
fun test() {
    runBlocking(Dispatchers.Main) {
        compose.setContent {
            MyContent()
        }
        compose.awaitIdle()

        compose.onNodeWithTag("thing").assertDoesNotExist()
    }
}
Pstr
  • 777
  • 1
  • 8
  • 17
  • That is kind of interesting. I guess it works for this particular test because the component I'm testing will always be on the screen if it was created at all. At some point in some later test, I imagine it probably won't work, but the existence of this alternative assertion suggests that a lot of tutorials out there might just be giving the wrong info on which one to use. – Hakanai May 16 '22 at 23:49
  • That's partially correct. "exists" is indeed very different from "displayed", they are right on the tutorials but are they Desktop tutorials? If so they are just copying from Android hehe, as an existing object may not be displayed if it's hidden. The problem is with Compose Desktop, that didn't implement many testing features in version 1.1.0. For Android, it works like a charm. You could maybe use Semantics operations to check if the object in question is on screen, but I'm not so sure `compose.onNodeWithTag("thing").assert(SemanticsMatcher.keyIsDefined(SemanticsProperties.InvisibleToUser))` – Pstr May 19 '22 at 15:10
  • A **lot** of the UI testing methods are just not implemented yet in Compose for Desktop and not even included for the 1.1.2 or 1.2.0 milestones. I would advise against trying workarounds like this one and simply forget about this for now. Personally, I'm UI testing in Android and doing manual exploratory testing in desktop. – Serandel Jun 29 '22 at 04:34
  • 2
    Why forgetting about this? Testing is important in any way possible. If you can assert that your elements exist and are instantiated, why not? – Pstr Jul 01 '22 at 03:46