Search code examples
javafxkotlintestfxtornadofx

TornadoFX with TestFX close the View after every TestCase


I am trying to test a basic loginscreen (created using tornadofx) with the testfx framework.

I have added 3 test cases which runs fine but the problem is they use the previous stage rather than creating a new one. I want the testcases to run independently.

I am testing a View() and not an App(). If I use MyMainApp().start(stage) and then MyMainApp().stop(), I get the required behaviour.
But how to do this for Views and Fragments.

Below is the code:

class LoginScreenFeatureTest : ApplicationTest() {

    override fun init() {
        FxToolkit.registerStage { Stage() }
    }

    override fun start(stage: Stage) {
        LoginScreen().openWindow()
        //MyMainApp().start(stage)
    }

    override fun stop() {
        FxToolkit.cleanupStages()
        //FxToolkit.toolkitContext().registeredStage.close()
        //MyMainApp().stop()
    }

    @Test fun should_contain_button() {
        // expect:
        verifyThat("#submitBut", hasText("SUBMIT"))
    }

    @Test fun should_click_on_button_and_pass_login() {
        //init
        //Why do I always need to erase text. I want a new stage for every test case.
        clickOn("#username").eraseText(10).write("validUser")
        clickOn("#password").eraseText(10).write("validPwd")
        clickOn("#orgId").eraseText(10).write("validOrg")

        // when:
        clickOn("#submitBut")

        // then:
        //verify success 
    }

    @Test fun should_click_on_button_and_fail_login() {
        //init
        clickOn("#username").eraseText(10).write("anyuser")
        clickOn("#password").eraseText(10).write("anypwd")
        clickOn("#orgId").eraseText(10).write("anyorg")

        // when:
        clickOn("#submitBut")

        // then:
        //verify fail 
    }
}

Solution

  • You can add property which you can edit at any time at you App() class.

    class MyMainApp: App() {
        override val primaryView: KClass<out View> = primaryViewMyApp
    
        companion object {
            var primaryViewMyApp: KClass<out View> = MyMainAppView::class
        }
    
        init {
            importStylesheet(<your stylesheet>)
        }
    
        override fun start(stage: Stage) {
            super.start(stage)
        }
    
        override fun stop() {
            super.stop()
        }
    }
    

    and in the test you can than use any view you want to use. I didnt try to implement something for Fragment so far...

        override fun init() {
            FxToolkit.registerStage { Stage() }
        }
    
        override fun start(stage: Stage) {
            MyMainApp.primaryViewGoApp = <your view>::class
            MyMainApp().start(stage)
        }
    
        override fun stop() {
            FxToolkit.cleanupStages()
            MyMainApp().stop()
        }