Skip to content
This repository has been archived by the owner on Apr 12, 2023. It is now read-only.

Commit

Permalink
Review windows management (#54)
Browse files Browse the repository at this point in the history
* Set cluster in schema registry title
* Set max width to cluster items
* Set default windows style to DECORATED
* Avoid reopen the same window
* Un-minified an already open window when required
* Close all windows when the primary is closed
* Add integration tests
* Run integration tests only on ubunutu
* Add test for close all windows when main is closed

Co-authored-by: darka91 <[email protected]>
  • Loading branch information
andrewinci and andrewinci authored Sep 20, 2020
1 parent 53efea3 commit 250751d
Show file tree
Hide file tree
Showing 19 changed files with 351 additions and 118 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ jobs:
- name: Run tests
run: "xvfb-run --auto-servernum ./gradlew check"

- name: Run integration tests
run: "xvfb-run --auto-servernum ./gradlew integrationTest"

build-win:
runs-on: windows-latest
steps:
Expand Down
11 changes: 7 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ apply plugin: 'org.openjfx.javafxplugin'
def arrow_version = "0.10.5"
def kotest_version = "4.1.3"
def koin_version = "2.1.6"
def testfx_version = "4.0.16-alpha"
def testcontainer_version = "1.14.3"

testSets { integrationTest }

dependencies {
implementation platform('org.jetbrains.kotlin:kotlin-bom')
Expand Down Expand Up @@ -68,12 +72,12 @@ dependencies {
testImplementation group: 'io.kotest', name: 'kotest-runner-console-jvm', version: "$kotest_version"
testImplementation group: 'io.kotest', name: 'kotest-assertions-arrow', version: "$kotest_version"

testCompile group: 'org.testfx', name: 'testfx-junit5', version: "4.0.16-alpha"
testCompile group: 'org.testfx', name: 'testfx-junit5', version: "$testfx_version"

testImplementation group: 'io.mockk', name: 'mockk', version: '1.10.0'
}

testSets { integrationTest }
integrationTestImplementation group: 'org.testcontainers', name: 'kafka', version: "$testcontainer_version"
}

tasks.withType(Test) { useJUnitPlatform() }

Expand Down Expand Up @@ -118,5 +122,4 @@ tasks.jacocoTestReport {
project.integrationTest { outputs.upToDateWhen { false } }

check.dependsOn test
check.dependsOn integrationTest
check.doLast { tasks.jacocoTestReport }
45 changes: 0 additions & 45 deletions src/integrationTest/kotlin/helper/TestHelpers.kt

This file was deleted.

48 changes: 0 additions & 48 deletions src/integrationTest/kotlin/insulator/InsulatorTest.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package insulator.integrationtest

import arrow.core.right
import insulator.Insulator
import insulator.integrationtest.helper.IntegrationTestContext
import insulator.lib.configuration.ConfigurationRepo
import insulator.lib.configuration.model.Configuration
import insulator.lib.helpers.runOnFXThread
import io.kotest.core.spec.style.FunSpec
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import javafx.stage.Stage
import javafx.stage.WindowEvent
import org.testfx.util.WaitForAsyncUtils.waitForFxEvents
import tornadofx.FX

class CloseAllWindowsTest : FunSpec({

test("Close application when the main one is closed") {
IntegrationTestContext().use { context ->
// arrange
val topicPrefix = "test-topic"
val topics = (1..10).map { "$topicPrefix-$it" }
topics.forEach { context.createTopics(it) }
context.configureDi(
ConfigurationRepo::class to mockk<ConfigurationRepo> {
every { addNewClusterCallback(any()) } just runs
every { getConfiguration() } returns
Configuration(clusters = listOf(context.clusterConfiguration)).right()
}
)

// act
context.startApp(Insulator::class.java)
// click on the local cluster to show the list of topics
context.clickOn("#cluster-${context.clusterConfiguration.guid}")
waitForFxEvents()

// open the test-topic-1 view
FX.primaryStage.runOnFXThread { toFront() }; waitForFxEvents()
context.doubleClickOn("#topic-$topicPrefix-1"); waitForFxEvents()

// open the test-topic-2 view
FX.primaryStage.runOnFXThread { toFront() }; waitForFxEvents()
context.doubleClickOn("#topic-$topicPrefix-2"); waitForFxEvents()

// close main window
(FX.primaryStage.scene.window as Stage).runOnFXThread {
fireEvent(WindowEvent(this, WindowEvent.WINDOW_CLOSE_REQUEST))
}; waitForFxEvents()

// assert
// FX.getApplication() shouldBe null
}
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package insulator.integrationtest

import arrow.core.right
import insulator.Insulator
import insulator.integrationtest.helper.IntegrationTestContext
import insulator.lib.configuration.ConfigurationRepo
import insulator.lib.configuration.model.Cluster
import insulator.lib.configuration.model.Configuration
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import javafx.stage.Stage
import org.testfx.api.FxAssert
import org.testfx.matcher.control.LabeledMatchers
import tornadofx.FX

class ListClusterTest : FunSpec({

test("Insulator start successfully showing the list of clusters") {
IntegrationTestContext(false).use {
// arrange
val cluster = Cluster.empty().copy(name = "Test cluster")
it.configureDi(
ConfigurationRepo::class to mockk<ConfigurationRepo> {
every { addNewClusterCallback(any()) } just runs
every { getConfiguration() } returns
Configuration(clusters = listOf(cluster)).right()
}
)

// act
it.startApp(Insulator::class.java)

// assert
(FX.primaryStage.scene.window as Stage).title shouldBe "Insulator"
FxAssert.verifyThat("#cluster-${cluster.guid} .label", LabeledMatchers.hasText(cluster.name))
}
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package insulator.integrationtest

import arrow.core.right
import insulator.Insulator
import insulator.integrationtest.helper.IntegrationTestContext
import insulator.lib.configuration.ConfigurationRepo
import insulator.lib.configuration.model.Configuration
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import javafx.scene.control.Label
import javafx.stage.Stage
import org.testfx.util.WaitForAsyncUtils.waitForFxEvents
import tornadofx.FX

class ListTopicTest : FunSpec({

test("Show the list of topic") {
IntegrationTestContext().use { context ->
// arrange
val topicPrefix = "test-topic"
val topics = (1..10).map { "$topicPrefix$it" }
topics.forEach { context.createTopics(it) }
context.configureDi(
ConfigurationRepo::class to mockk<ConfigurationRepo> {
every { addNewClusterCallback(any()) } just runs
every { getConfiguration() } returns
Configuration(clusters = listOf(context.clusterConfiguration)).right()
}
)

// act
context.startApp(Insulator::class.java)
// click on the local cluster to show the list of topics
context.clickOn("#cluster-${context.clusterConfiguration.guid}")
waitForFxEvents()

// assert
(FX.primaryStage.scene.window as Stage).title shouldBe context.clusterConfiguration.name
context.lookup<Label> { it.text.startsWith(topicPrefix) }.queryAll<Label>()
.map { it.text }.toSet() shouldBe topics.toSet()
}
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package insulator.integrationtest.helper

import insulator.lib.configuration.model.Cluster
import javafx.application.Application
import javafx.stage.Stage
import org.apache.kafka.clients.admin.AdminClient
import org.apache.kafka.clients.admin.AdminClientConfig
import org.apache.kafka.clients.admin.NewTopic
import org.koin.core.context.stopKoin
import org.testcontainers.containers.KafkaContainer
import org.testcontainers.containers.wait.strategy.Wait
import org.testfx.api.FxRobot
import org.testfx.api.FxToolkit
import tornadofx.* // ktlint-disable no-wildcard-imports
import java.io.Closeable
import kotlin.reflect.KClass

class IntegrationTestContext(createKafkaCluster: Boolean = true) : FxRobot(), Closeable {

private val kafka = KafkaContainer()
lateinit var clusterConfiguration: Cluster

init {
if (createKafkaCluster) {
kafka.start()
kafka.waitingFor(Wait.forListeningPort())
clusterConfiguration = Cluster.empty().copy(name = "Test local cluster", endpoint = kafka.bootstrapServers)
}
}

fun createTopics(vararg name: String) {
val admin = AdminClient.create(
mapOf(
AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG to kafka.bootstrapServers
).toProperties()
)
admin.createTopics(name.map { NewTopic(it, 3, 1) })
}

fun startApp(applicationClass: Class<out Application>) {
FxToolkit.registerPrimaryStage()
FxToolkit.setupApplication(applicationClass)
waitPrimaryStage()
}

fun configureDi(vararg dependencyMap: Pair<KClass<*>, Any>) {
if (FX.dicontainer != null) throw TestHelperError("DI already configured")
FX.dicontainer = object : DIContainer {
val main = insulator.di.DIContainer()

@Suppress("UNCHECKED_CAST", "IMPLICIT_CAST_TO_ANY")
override fun <T : Any> getInstance(type: KClass<T>): T =
dependencyMap.toMap()[type] as? T ?: main.getInstance(type)
}
}

private fun waitPrimaryStage(limit: Int = 20): Stage {
repeat(limit) {
val primaryStage = FX.getPrimaryStage()
if (primaryStage?.isShowing == true && primaryStage.isFocused) {
Thread.sleep(1000)
return primaryStage
}
Thread.sleep(1000)
}
throw TestHelperError("Timeout waiting for primary stage to show up")
}

override fun close() {
kafka.close()
kotlin.runCatching { FxToolkit.cleanupStages() }
kotlin.runCatching { FxToolkit.cleanupApplication(FX.application) }
FX.dicontainer = null
stopKoin()
}
}

class TestHelperError(message: String) : Throwable(message)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package insulator.integrationtest.helper

import tornadofx.* // ktlint-disable no-wildcard-imports
Loading

0 comments on commit 250751d

Please sign in to comment.