Merge pull request #3947 from element-hq/renovate/com.lemonappdev-konsist-0.x
Update dependency com.lemonappdev:konsist to v0.17.0
This commit is contained in:
@@ -52,6 +52,10 @@ allprojects {
|
||||
detektPlugins("io.nlopez.compose.rules:detekt:0.4.19")
|
||||
}
|
||||
|
||||
tasks.withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
|
||||
exclude("io/element/android/tests/konsist/failures/**")
|
||||
}
|
||||
|
||||
// KtLint
|
||||
apply {
|
||||
plugin("org.jlleitschuh.gradle.ktlint")
|
||||
@@ -75,6 +79,7 @@ allprojects {
|
||||
val generatedPath = "${layout.buildDirectory.asFile.get()}/generated/"
|
||||
filter {
|
||||
exclude { element -> element.file.path.contains(generatedPath) }
|
||||
exclude("io/element/android/tests/konsist/failures/**")
|
||||
}
|
||||
}
|
||||
// Dependency check
|
||||
|
||||
@@ -150,7 +150,7 @@ test_arch_core = "androidx.arch.core:core-testing:2.2.0"
|
||||
test_junit = "junit:junit:4.13.2"
|
||||
test_runner = "androidx.test:runner:1.6.2"
|
||||
test_mockk = "io.mockk:mockk:1.13.13"
|
||||
test_konsist = "com.lemonappdev:konsist:0.16.1"
|
||||
test_konsist = "com.lemonappdev:konsist:0.17.0"
|
||||
test_turbine = "app.cash.turbine:turbine:1.2.0"
|
||||
test_truth = "com.google.truth:truth:1.4.4"
|
||||
test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.18"
|
||||
|
||||
@@ -98,6 +98,8 @@ fun Project.setupKover() {
|
||||
"io.element.android.libraries.designsystem.theme.components.bottomsheet.*",
|
||||
// Test presenters
|
||||
"io.element.android.features.leaveroom.fake.FakeLeaveRoomPresenter",
|
||||
// Konsist code to make test fails
|
||||
"io.element.android.tests.konsist.failures",
|
||||
)
|
||||
annotatedBy(
|
||||
"androidx.compose.ui.tooling.preview.Preview",
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.tests.konsist.failures
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
// Make test `Sealed interface used in Composable MUST be Immutable or Stable` fails
|
||||
|
||||
sealed interface SealedInterface
|
||||
|
||||
@Composable
|
||||
fun FailingComposableWithNonImmutableSealedInterface(
|
||||
sealedInterface: SealedInterface
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.tests.konsist.failures
|
||||
|
||||
// Make test `Fake classes must be named using Fake and the interface it fakes` fails
|
||||
|
||||
interface MyInterface
|
||||
|
||||
// This class should be named FakeMyInterface
|
||||
class FakeWrongClassName : MyInterface
|
||||
|
||||
class MyClass {
|
||||
interface MyFactory
|
||||
}
|
||||
|
||||
// This class should be named FakeMyClassMyFactory
|
||||
class FakeWrongClassSubInterfaceName : MyClass.MyFactory
|
||||
@@ -22,6 +22,7 @@ import com.lemonappdev.konsist.api.ext.list.withoutName
|
||||
import com.lemonappdev.konsist.api.ext.list.withoutParents
|
||||
import com.lemonappdev.konsist.api.verify.assertEmpty
|
||||
import com.lemonappdev.konsist.api.verify.assertTrue
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class KonsistArchitectureTest {
|
||||
@@ -66,34 +67,44 @@ class KonsistArchitectureTest {
|
||||
|
||||
@Test
|
||||
fun `Sealed interface used in Composable MUST be Immutable or Stable`() {
|
||||
var failingTestFound = false
|
||||
// List all sealed interface without Immutable nor Stable annotation in the project
|
||||
val forbiddenInterfacesForComposableParameter = Konsist.scopeFromProject()
|
||||
.interfaces()
|
||||
.withSealedModifier()
|
||||
.withoutAnnotationOf(Immutable::class, Stable::class)
|
||||
.map { it.fullyQualifiedName }
|
||||
|
||||
Konsist.scopeFromProject()
|
||||
.functions()
|
||||
.withAnnotationOf(Composable::class)
|
||||
.assertTrue(additionalMessage = "Consider adding the @Immutable or @Stable annotation to the sealed interface") {
|
||||
it.parameters.all { param ->
|
||||
val result = it.parameters.all { param ->
|
||||
val type = param.type.text
|
||||
return@all if (type.startsWith("@") || type.startsWith("(") || type.startsWith("suspend")) {
|
||||
return@all if (type.startsWith("@") || type.contains("->") || type.startsWith("suspend")) {
|
||||
true
|
||||
} else {
|
||||
var typePackage = param.type.declaration.packagee?.name
|
||||
if (typePackage == type) {
|
||||
// Workaround, now that packagee.fullyQualifiedName is not available anymore
|
||||
// It seems that when the type in in the same package as the function,
|
||||
// the package is equal to the type (which is wrong).
|
||||
// So in this case, use the package of the function
|
||||
typePackage = it.packagee?.name
|
||||
val typePackage = param.type.sourceDeclaration?.let { declaration ->
|
||||
declaration.asTypeParameterDeclaration()?.packagee
|
||||
?: declaration.asExternalDeclaration()?.packagee
|
||||
?: declaration.asClassOrInterfaceDeclaration()?.packagee
|
||||
?: declaration.asKotlinTypeDeclaration()?.packagee
|
||||
?: declaration.asObjectDeclaration()?.packagee
|
||||
}?.name
|
||||
if (typePackage == null) {
|
||||
false
|
||||
} else {
|
||||
val fullyQualifiedName = "$typePackage.$type"
|
||||
fullyQualifiedName !in forbiddenInterfacesForComposableParameter
|
||||
}
|
||||
val fullyQualifiedName = "$typePackage.$type"
|
||||
fullyQualifiedName !in forbiddenInterfacesForComposableParameter
|
||||
}
|
||||
}
|
||||
if (!result && !failingTestFound && it.name == "FailingComposableWithNonImmutableSealedInterface") {
|
||||
failingTestFound = true
|
||||
true
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
assertTrue("FailingComposableWithNonImmutableSealedInterface should make this test fail.", failingTestFound)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,11 @@ class KonsistClassNameTest {
|
||||
|
||||
@Test
|
||||
fun `Fake classes must be named using Fake and the interface it fakes`() {
|
||||
var failingCases = 0
|
||||
val failingCasesList = listOf(
|
||||
"FakeWrongClassName",
|
||||
"FakeWrongClassSubInterfaceName",
|
||||
)
|
||||
Konsist.scopeFromProject()
|
||||
.classes()
|
||||
.withNameContaining("Fake")
|
||||
@@ -84,16 +89,19 @@ class KonsistClassNameTest {
|
||||
val interfaceName = it.name
|
||||
.replace("FakeRust", "")
|
||||
.replace("Fake", "")
|
||||
(it.name.startsWith("Fake") || it.name.startsWith("FakeRust")) &&
|
||||
val result = (it.name.startsWith("Fake") || it.name.startsWith("FakeRust")) &&
|
||||
it.parents().any { parent ->
|
||||
// Workaround to get the parent name. For instance:
|
||||
// parent.name used to return `UserListPresenter.Factory` but is now returning `Factory`.
|
||||
// So we need to retrieve the name of the parent class differently.
|
||||
val packageName = parent.packagee!!.name
|
||||
val parentName = parent.fullyQualifiedName!!.substringAfter("$packageName.").replace(".", "")
|
||||
val parentName = parent.name.replace(".", "")
|
||||
parentName == interfaceName
|
||||
}
|
||||
if (!result && it.name in failingCasesList) {
|
||||
failingCases++
|
||||
true
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
assertThat(failingCases).isEqualTo(failingCasesList.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user