Skip to content

Commit

Permalink
also filter metrics, make tag filter editor nicer
Browse files Browse the repository at this point in the history
  • Loading branch information
jillesvangurp committed Nov 11, 2023
1 parent 96b41ad commit a9cbf5b
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/jsMain/kotlin/components/layout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fun RenderContext.rowCentered(content: HtmlTag<HTMLDivElement>.() -> Unit) {
div("flex flex-row flex-wrap gap-2 align-middle place-items-center mx-auto w-fit", content = content)
}
fun RenderContext.leftRightRow(content: HtmlTag<HTMLDivElement>.() -> Unit) {
div("flex flex-row flex-wrap w-full place-items-center justify-between", content = content)
div("flex flex-row w-full place-items-center justify-between", content = content)
}

fun RenderContext.border(content: HtmlTag<HTMLDivElement>.() -> Unit) {
Expand Down
39 changes: 26 additions & 13 deletions src/jsMain/kotlin/metrics/metrics.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ import pageLink
import testcases.RatedSearchesStore
import searchpluginconfig.ActiveSearchPluginConfigurationStore
import kotlinx.coroutines.Job
import testcases.TestCaseSearchFilterStore
import testcases.tagFilterEditor
import kotlin.math.pow
import kotlin.math.roundToLong

val metricsModule = module {
singleOf(::MetricsOutputStore)
}

fun Double.round(decimals:Int): Double {
fun Double.round(decimals: Int): Double {
if (decimals > 17) {
throw IllegalArgumentException("this probably doesn't do what you want; makes sense only for <= 17 decimals")
}
Expand All @@ -38,7 +40,7 @@ class MetricsOutputStore() : RootStore<List<MetricsOutput>?>(null, Job()) {
val ratedSearchesStore = koin.get<RatedSearchesStore>()
val pluginFactoryRegistry = koin.get<PluginFactoryRegistry>()
val activeSearchPluginConfigurationStore = koin.get<ActiveSearchPluginConfigurationStore>()

val testCaseSearchFilterStore = koin.get<TestCaseSearchFilterStore>()
val measure = handle {
runWithBusy({
ratedSearchesStore.current?.let { ratedSearches ->
Expand All @@ -49,16 +51,23 @@ class MetricsOutputStore() : RootStore<List<MetricsOutput>?>(null, Job()) {
} else {
console.log("Using ${pluginFactory::class.simpleName}")
}
val tags = testCaseSearchFilterStore.current?.tags.orEmpty()
pluginFactory?.let { pf ->
val plugin = pf.create(config)
console.info("measuring")
plugin.runMetrics(config, ratedSearches)
plugin.runMetrics(config, ratedSearches.filter { rs ->
if (tags.isEmpty()) {
true
} else {
tags.containsAll(rs.tags.orEmpty())
}
})
}
}
}
}) { results ->
update(results?.mapNotNull { r ->
if(r.isFailure) {
if (r.isFailure) {
console.error(r.exceptionOrNull())
null
} else {
Expand Down Expand Up @@ -146,6 +155,7 @@ fun RenderContext.metrics() {
""".trimIndent()
)
}
tagFilterEditor()
metricsOutputStore.data.render { metrics ->
div("w-full") {
metrics?.forEach { (_, metric, metricResult) ->
Expand Down Expand Up @@ -181,11 +191,15 @@ private fun RenderContext.metricResult(

div {
+"Metric: "
renderMetricsScore(metricResult.metric, metricConfiguration.expected?:0.75)
renderMetricsScore(metricResult.metric, metricConfiguration.expected ?: 0.75)
}
div {
metricResult.scores.stats.let {resultStats ->
+"min: ${resultStats.min.round(3)}, max: ${resultStats.max.round(3)}, median: ${resultStats.median.round(3)}, \u03C3: ${resultStats.standardDeviation.round(3)}, variance: ${resultStats.variance.round(3)}"
metricResult.scores.stats.let { resultStats ->
+"min: ${resultStats.min.round(3)}, max: ${resultStats.max.round(3)}, median: ${
resultStats.median.round(
3
)
}, \u03C3: ${resultStats.standardDeviation.round(3)}, variance: ${resultStats.variance.round(3)}"
}
}
para { +"SearchConfiguration: ${metricConfiguration.name}" }
Expand Down Expand Up @@ -226,7 +240,7 @@ private fun RenderContext.metricResult(
+rss[metricResult.id]!!.searchContext.toString()
}
div {
renderMetricsScore(metricResult.metric, metricConfiguration.expected?:0.75)
renderMetricsScore(metricResult.metric, metricConfiguration.expected ?: 0.75)
}
div("flex flex-row w-full hover:bg-blueBright-200") {
div("w-full flex flax-col") {
Expand Down Expand Up @@ -262,7 +276,7 @@ private fun RenderContext.metricResult(
showTooltip(doc.label ?: "-")
}
div("w-1/6 overflow-hidden") {
renderMetricsScore(score, metricConfiguration.expected?:0.75)
renderMetricsScore(score, metricConfiguration.expected ?: 0.75)
}
}
}
Expand Down Expand Up @@ -368,11 +382,10 @@ val Metric.explanation
)



fun RenderContext.renderMetricsScore(actual:Double, threshold: Double) {
if(actual < threshold) {
fun RenderContext.renderMetricsScore(actual: Double, threshold: Double) {
if (actual < threshold) {
span("text-red-600") { +actual.round(3).toString() }
} else {
span("text-green-600") { +actual.round(3).toString() }
span("text-green-600") { +actual.round(3).toString() }
}
}
46 changes: 46 additions & 0 deletions src/jsMain/kotlin/testcases/tag-control.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package testcases

import components.*
import dev.fritz2.core.RenderContext
import koin
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map

fun RenderContext.tagFilterEditor() {
val testCaseSearchFilterStore = koin.get<TestCaseSearchFilterStore>()
val ratedSearchesStore = koin.get<RatedSearchesStore>()

testCaseSearchFilterStore.data.filterNotNull().render { filter ->
leftRightRow {

row {
p {
+"tags"
}
filter.tags.forEach { tag ->
secondaryButton(iconSource = SvgIconSource.Delete, text = tag) {
clicks.map { tag } handledBy testCaseSearchFilterStore.removeTag
}
}
ratedSearchesStore.data.renderNotNull { testCases ->
val allTags = testCases.flatMap { it.tags.orEmpty() }.toSet().sorted()
allTags.filter { !filter.tags.contains(it) }.forEach { tag ->
primaryButton(iconSource = SvgIconSource.Plus, text = tag) {
clicks.map { tag } handledBy testCaseSearchFilterStore.addTag
}
}
}
}
infoPopup(
"Tag Filtering",
"""
Use tags to filter your test cases. You can add tags to your test cases to make it easier to
find them back, group them by search feature, etc.
When running metrics, the tag filter applies as well. You can usw this to group test
cases and evaluate the impact of changes on particular groups of test cases.
""".trimIndent()
)
}
}
}
16 changes: 4 additions & 12 deletions src/jsMain/kotlin/testcases/testcases.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import dev.fritz2.core.*
import dev.fritz2.headless.components.toast
import dev.fritz2.remote.http
import koin
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.*
import kotlinx.datetime.Clock
import kotlinx.serialization.Serializable
Expand All @@ -19,7 +18,6 @@ import org.koin.core.qualifier.named
import org.koin.dsl.module
import org.w3c.dom.HTMLDivElement
import org.w3c.dom.events.Event
import org.w3c.dom.events.InputEvent
import pageLink
import search.SearchResultsStore
import searchpluginconfig.ActiveSearchPluginConfigurationStore
Expand Down Expand Up @@ -114,6 +112,7 @@ fun RenderContext.testCases() {
val ratedSearchesStore = koin.get<RatedSearchesStore>()
val activeSearchPluginConfigurationStore = koin.get<ActiveSearchPluginConfigurationStore>()
val showDemoContentStore = koin.get<Store<Boolean>>(named("showDemo"))
val testCaseSearchFilterStore = koin.get<TestCaseSearchFilterStore>()

val showStore = storeOf<Map<String, Boolean>>(mapOf())
activeSearchPluginConfigurationStore.data.render { searchPluginConfiguration ->
Expand Down Expand Up @@ -184,17 +183,11 @@ fun RenderContext.testCases() {
}
}

val testCaseSearchFilterStore = koin.get<TestCaseSearchFilterStore>()
tagFilterEditor()
testCaseSearchFilterStore.data.filterNotNull().render { filter ->
row {
filter.tags.forEach { tag ->
secondaryButton(iconSource = SvgIconSource.Delete, text = tag) {
clicks.map { tag } handledBy testCaseSearchFilterStore.removeTag
}
}
}

ratedSearchesStore.data.filterNotNull().map {
if(filter.tags.isEmpty()) {
if (filter.tags.isEmpty()) {
it
} else {
it.filter { it.tags?.containsAll(filter.tags) == true }
Expand All @@ -211,7 +204,6 @@ fun RenderContext.testCases() {
}
}


fun RenderContext.testCase(showStore: Store<Map<String, Boolean>>, rsStore: Store<RatedSearch>) {
val ratedSearchesStore = koin.get<RatedSearchesStore>()
val testCaseSearchFilterStore = koin.get<TestCaseSearchFilterStore>()
Expand Down

0 comments on commit a9cbf5b

Please sign in to comment.