diff --git a/gradle.properties b/gradle.properties index b98344daf..7b457e0ab 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group=com.fwdekker -# TODO: Also remove `beta` from `TemplateSettings` storage file! +# TODO: Also remove `beta` from `PersistentSettings' annotation`! version=3.0.0-beta.3 # Compatibility diff --git a/src/main/kotlin/com/fwdekker/randomness/affix/AffixDecoratorEditor.kt b/src/main/kotlin/com/fwdekker/randomness/affix/AffixDecoratorEditor.kt index a48ed14f0..bc7835623 100644 --- a/src/main/kotlin/com/fwdekker/randomness/affix/AffixDecoratorEditor.kt +++ b/src/main/kotlin/com/fwdekker/randomness/affix/AffixDecoratorEditor.kt @@ -64,5 +64,5 @@ class AffixDecoratorEditor( * @return the camelCase concatenation of [prefix] and [name] */ private fun camelConcat(prefix: String, name: String) = - if (prefix != "") "${prefix}${name[0].uppercase(Locale.getDefault())}${name.drop(1)}" - else name + if (prefix == "") name + else "${prefix}${name[0].uppercase(Locale.getDefault())}${name.drop(1)}" diff --git a/src/test/kotlin/com/fwdekker/randomness/AssertJHelper.kt b/src/test/kotlin/com/fwdekker/randomness/AssertJHelper.kt index d46eeafc0..f4f186b7a 100644 --- a/src/test/kotlin/com/fwdekker/randomness/AssertJHelper.kt +++ b/src/test/kotlin/com/fwdekker/randomness/AssertJHelper.kt @@ -9,7 +9,9 @@ import io.kotest.core.spec.BeforeAny import io.kotest.core.spec.style.scopes.ContainerScope import io.kotest.core.test.TestType import org.assertj.swing.core.GenericTypeMatcher +import org.assertj.swing.driver.ComponentDriver import org.assertj.swing.edt.GuiActionRunner +import org.assertj.swing.fixture.AbstractComponentFixture import org.assertj.swing.fixture.AbstractTwoStateButtonFixture import org.assertj.swing.fixture.FrameFixture import org.assertj.swing.fixture.JComboBoxFixture @@ -73,6 +75,11 @@ fun FrameFixture.getActionButton(accessibleName: String): ActionButton = find(matcher(ActionButton::class.java) { it.accessibleContext.accessibleName == accessibleName }) +fun AbstractComponentFixture.requireEnabledIs(enabled: Boolean) = + if (enabled) this.requireEnabled() + else this.requireDisabled() + + // TODO: Document these functions! @Suppress("UNCHECKED_CAST") fun KMutableProperty0.prop(): MutableProperty = MutableProperty({ get() }, { set(it as T) }) diff --git a/src/test/kotlin/com/fwdekker/randomness/Matchers.kt b/src/test/kotlin/com/fwdekker/randomness/Matchers.kt index 612de250f..b4124464a 100644 --- a/src/test/kotlin/com/fwdekker/randomness/Matchers.kt +++ b/src/test/kotlin/com/fwdekker/randomness/Matchers.kt @@ -9,6 +9,8 @@ import io.kotest.matchers.nulls.beNull import io.kotest.matchers.should +// TODO: Merge this file with `AssertJHelper`? + /** * @see beEmptyArray */ diff --git a/src/test/kotlin/com/fwdekker/randomness/affix/AffixDecoratorEditorTest.kt b/src/test/kotlin/com/fwdekker/randomness/affix/AffixDecoratorEditorTest.kt index ad58eb95d..cbbff9012 100644 --- a/src/test/kotlin/com/fwdekker/randomness/affix/AffixDecoratorEditorTest.kt +++ b/src/test/kotlin/com/fwdekker/randomness/affix/AffixDecoratorEditorTest.kt @@ -1,17 +1,149 @@ package com.fwdekker.randomness.affix +import com.fwdekker.randomness.afterNonContainer +import com.fwdekker.randomness.beforeNonContainer +import com.fwdekker.randomness.editorApplyTestFactory +import com.fwdekker.randomness.editorFieldsTestFactory +import com.fwdekker.randomness.guiGet +import com.fwdekker.randomness.guiRun +import com.fwdekker.randomness.prop +import com.fwdekker.randomness.requireEnabledIs +import com.fwdekker.randomness.textProp +import com.intellij.testFramework.fixtures.IdeaTestFixture +import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory +import com.intellij.ui.layout.selected +import io.kotest.assertions.throwables.shouldNotThrowAny import io.kotest.core.NamedTag import io.kotest.core.spec.style.FunSpec +import io.kotest.data.row +import io.kotest.datatest.withData +import io.kotest.matchers.shouldBe +import io.kotest.matchers.shouldNotBe +import org.assertj.swing.edt.FailOnThreadViolationRepaintManager +import org.assertj.swing.fixture.Containers +import org.assertj.swing.fixture.FrameFixture +import javax.swing.JCheckBox /** * Unit tests for [AffixDecoratorEditor]. */ object AffixDecoratorEditorTest : FunSpec({ - tags(NamedTag("TODO")) // TODO + tags(NamedTag("Editor"), NamedTag("IdeaFixture"), NamedTag("Swing")) - xcontext("TODO") { - // TODO: Add these tests + lateinit var ideaFixture: IdeaTestFixture + lateinit var frame: FrameFixture + + lateinit var scheme: AffixDecorator + lateinit var editor: AffixDecoratorEditor + + + beforeContainer { + FailOnThreadViolationRepaintManager.install() + } + + beforeNonContainer { + ideaFixture = IdeaTestFixtureFactory.getFixtureFactory().createBareFixture() + ideaFixture.setUp() + + scheme = AffixDecorator(enabled = true) + editor = guiGet { AffixDecoratorEditor(scheme, presets = listOf("a", "b", "c")) } + frame = Containers.showInFrame(editor.rootComponent) + } + + afterNonContainer { + frame.cleanUp() + ideaFixture.tearDown() } + + + context("constructor") { + context("enableMnemonic") { + test("enables mnemonics if true") { + frame.checkBox("affixEnabled").target().mnemonic shouldNotBe 0 + } + + test("disables mnemonics if false") { + frame.cleanUp() + editor = guiGet { AffixDecoratorEditor(scheme, presets = listOf("."), enableMnemonic = false) } + frame = Containers.showInFrame(editor.rootComponent) + + frame.checkBox("affixEnabled").target().mnemonic shouldBe 0 + } + } + + context("namePrefix") { + test("does not prefix component names if the prefix is an empty string") { + shouldNotThrowAny { frame.checkBox("affixEnabled") } + shouldNotThrowAny { frame.comboBox("affixDescriptor") } + } + + test("prefixes component names by the given prefix and retains camel case") { + frame.cleanUp() + editor = guiGet { AffixDecoratorEditor(scheme, presets = listOf("."), namePrefix = "prefix") } + frame = Containers.showInFrame(editor.rootComponent) + + shouldNotThrowAny { frame.checkBox("prefixAffixEnabled") } + shouldNotThrowAny { frame.comboBox("prefixAffixDescriptor") } + } + } + } + + + context("input handling") { + context("ifEnabled and affixEnabled") { + lateinit var toggle: JCheckBox + + + beforeNonContainer { + toggle = guiGet { JCheckBox().also { it.isSelected = false } } + } + + + @Suppress("BooleanLiteralArgument") // Argument names are clear from lambda later on + withData( + nameFn = { "enabledIf=${it.a}, checkboxChecked=${it.b}" }, + listOf( + row(null, false, true, false), + row(null, true, true, true), + row(false, false, false, false), + row(false, true, false, false), + row(true, false, true, false), + row(true, true, true, true), + ) + ) { (predicateState, checkboxState, expectedCheckboxEnabled, expectedDescriptorEnabled) -> + val predicate = if (predicateState == null) null else toggle.selected + + frame.cleanUp() + editor = guiGet { AffixDecoratorEditor(scheme, presets = listOf("."), enabledIf = predicate) } + frame = Containers.showInFrame(editor.rootComponent) + + guiRun { + if (predicateState != null) toggle.isSelected = predicateState + frame.checkBox().target().isSelected = checkboxState + } + + frame.checkBox().requireEnabledIs(expectedCheckboxEnabled) + frame.comboBox().requireEnabledIs(expectedDescriptorEnabled) + } + } + } + + + include(editorApplyTestFactory { editor }) + + include( + editorFieldsTestFactory( + { editor }, + mapOf( + "descriptor" to + row( + { frame.comboBox("affixDescriptor").textProp() }, + { editor.scheme::descriptor.prop() }, + "non-preset string", + ), + ) + ) + ) }) diff --git a/src/test/kotlin/com/fwdekker/randomness/array/ArrayDecoratorEditorTest.kt b/src/test/kotlin/com/fwdekker/randomness/array/ArrayDecoratorEditorTest.kt index ee05edf77..5bcaece39 100644 --- a/src/test/kotlin/com/fwdekker/randomness/array/ArrayDecoratorEditorTest.kt +++ b/src/test/kotlin/com/fwdekker/randomness/array/ArrayDecoratorEditorTest.kt @@ -56,17 +56,19 @@ object ArrayDecoratorEditorTest : FunSpec({ } - context("embedded") { - test("shows the titled separator if the editor is not embedded") { - frame.panel(matcher(TitledSeparator::class.java)).requireVisible() - } + context("constructor") { + context("embedded") { + test("shows the titled separator if the editor is not embedded") { + frame.panel(matcher(TitledSeparator::class.java)).requireVisible() + } - test("hides the titled separator if the editor is embedded") { - frame.cleanUp() - editor = guiGet { ArrayDecoratorEditor(scheme, embedded = true) } - frame = showInFrame(editor.rootComponent) + test("hides the titled separator if the editor is embedded") { + frame.cleanUp() + editor = guiGet { ArrayDecoratorEditor(scheme, embedded = true) } + frame = showInFrame(editor.rootComponent) - frame.panel(matcher(TitledSeparator::class.java)).requireNotVisible() + frame.panel(matcher(TitledSeparator::class.java)).requireNotVisible() + } } } diff --git a/src/test/kotlin/com/fwdekker/randomness/integer/IntegerSchemeEditorTest.kt b/src/test/kotlin/com/fwdekker/randomness/integer/IntegerSchemeEditorTest.kt index f454b7463..a4a94d265 100644 --- a/src/test/kotlin/com/fwdekker/randomness/integer/IntegerSchemeEditorTest.kt +++ b/src/test/kotlin/com/fwdekker/randomness/integer/IntegerSchemeEditorTest.kt @@ -8,6 +8,7 @@ import com.fwdekker.randomness.guiGet import com.fwdekker.randomness.guiRun import com.fwdekker.randomness.isSelectedProp import com.fwdekker.randomness.prop +import com.fwdekker.randomness.requireEnabledIs import com.fwdekker.randomness.textProp import com.fwdekker.randomness.valueProp import com.intellij.testFramework.fixtures.IdeaTestFixture @@ -86,7 +87,7 @@ object IntegerSchemeEditorTest : FunSpec({ } context("toggles the grouping separator depending on base value and checkbox state") { - @Suppress("BooleanLiteralArgument") // Argument names clear from lambda later on + @Suppress("BooleanLiteralArgument") // Argument names are clear from lambda later on withData( row(8, false, false, false), row(8, true, false, false), @@ -100,10 +101,8 @@ object IntegerSchemeEditorTest : FunSpec({ frame.checkBox("groupingSeparatorEnabled").target().isSelected = checkBoxChecked } - frame.checkBox("groupingSeparatorEnabled") - .let { if (expectedCheckBoxEnabled) it.requireEnabled() else it.requireDisabled() } - frame.comboBox("groupingSeparator") - .let { if (expectedInputEnabled) it.requireEnabled() else it.requireDisabled() } + frame.checkBox("groupingSeparatorEnabled").requireEnabledIs(expectedCheckBoxEnabled) + frame.comboBox("groupingSeparator").requireEnabledIs(expectedInputEnabled) } } } diff --git a/src/test/kotlin/com/fwdekker/randomness/template/TemplateJTreeTest.kt b/src/test/kotlin/com/fwdekker/randomness/template/TemplateJTreeTest.kt index dcc8af2b9..db5c759ce 100644 --- a/src/test/kotlin/com/fwdekker/randomness/template/TemplateJTreeTest.kt +++ b/src/test/kotlin/com/fwdekker/randomness/template/TemplateJTreeTest.kt @@ -461,7 +461,7 @@ object TemplateJTreeTest : FunSpec({ } context("canMoveSchemeByOnePosition") { - @Suppress("BooleanLiteralArgument") // Argument names clear from lambda later on + @Suppress("BooleanLiteralArgument") // Argument names are clear from lambda later on withData( mapOf Scheme, Boolean, Boolean>>( "first template" to row({ tree.myModel.list.templates[0] }, false, false),