diff --git a/CHANGELOG.md b/CHANGELOG.md index f1d1a930..12aacbd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Change Log ========== +## Unreleased + +* Fix bug #264 +* Clean up internal utils + ## Version 3.1.0 (2026-01-18) * Fix bug #255 by ensuring that "stemProvider" dependencies are not transitive. diff --git a/demo-app/app/build.gradle.kts b/demo-app/app/build.gradle.kts index a1c4ba52..e46332e8 100644 --- a/demo-app/app/build.gradle.kts +++ b/demo-app/app/build.gradle.kts @@ -1,6 +1,5 @@ plugins { alias(libs.plugins.android.application) - alias(libs.plugins.kotlin) id("com.likethesalad.stem") } @@ -14,6 +13,9 @@ android { targetSdk = 34 versionCode = 1 versionName = "1.0" + buildFeatures { + resValues = true + } resValue("string", "generated_string", "My generated string") } diff --git a/demo-app/gradle/libs.versions.toml b/demo-app/gradle/libs.versions.toml index 01f583ac..52814a66 100644 --- a/demo-app/gradle/libs.versions.toml +++ b/demo-app/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] project-utilities = "3.1.0" -android = "8.13.2" +android = "9.0.0" [libraries] robolectric = "org.robolectric:robolectric:4.16" @@ -8,5 +8,4 @@ unitTesting = { module = "com.likethesalad.tools:unit-testing", version.ref = "p [plugins] android-application = { id = "com.android.application", version.ref = "android" } -android-library = { id = "com.android.library", version.ref = "android" } -kotlin = { id = "org.jetbrains.kotlin.android", version = "2.3.0" } \ No newline at end of file +android-library = { id = "com.android.library", version.ref = "android" } \ No newline at end of file diff --git a/demo-app/my-library/build.gradle.kts b/demo-app/my-library/build.gradle.kts index acdd60d0..fcf892fe 100644 --- a/demo-app/my-library/build.gradle.kts +++ b/demo-app/my-library/build.gradle.kts @@ -1,6 +1,5 @@ plugins { alias(libs.plugins.android.library) - alias(libs.plugins.kotlin) } android { diff --git a/gradle.properties b/gradle.properties index 7229751a..5fee380f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ #Sun Jan 18 14:49:20 UTC 2026 kotlin.code.style=official -version=3.2.0 +version=3.1.1 group=com.likethesalad.android diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 013692e1..d1f28b4e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,5 @@ [versions] -project-utilities = "3.1.0" -android = "8.13.2" +android = "9.0.0" [libraries] android-plugin = { module = "com.android.tools.build:gradle", version.ref = "android" } @@ -20,7 +19,6 @@ junit = ["junit-jupiter", "junit-launcher", "junit-engine"] [plugins] artifactPublisher = { id = "com.likethesalad.artifact-publisher", version = "3.5.0" } -androidTestTools = { id = "com.likethesalad.tools.android-compilation-testing", version.ref = "project-utilities" } android-application = { id = "com.android.application", version.ref = "android" } wire = { id = "com.squareup.wire", version = "5.5.0" } kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.3.0" } diff --git a/settings.gradle.kts b/settings.gradle.kts index ece91719..2c3a18e2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,6 @@ pluginManagement { repositories { + mavenLocal() gradlePluginPortal() mavenCentral() google() @@ -10,12 +11,6 @@ pluginManagement { if (pluginId == "com.likethesalad.artifact-publisher") { useModule("com.likethesalad.tools:artifact-publisher:${requested.version}") } - if (pluginId == "plugin-metadata-producer") { - useModule("com.likethesalad.tools:plugin-metadata-producer:1.0.0") - } - if (requested.id.namespace == "com.likethesalad.tools") { - useModule("com.likethesalad.tools:plugin-tools:${requested.version}") - } } } } diff --git a/stem-plugin/build.gradle.kts b/stem-plugin/build.gradle.kts index 0b4a453b..1ed61240 100644 --- a/stem-plugin/build.gradle.kts +++ b/stem-plugin/build.gradle.kts @@ -3,10 +3,19 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinVersion plugins { alias(libs.plugins.kotlin) id("java-gradle-plugin") - alias(libs.plugins.androidTestTools) alias(libs.plugins.wire) } +val testPluginDependency: Configuration by configurations.creating +val testPluginClasspath: Configuration = configurations.create("testPluginClasspath") { + extendsFrom(testPluginDependency) + isCanBeConsumed = false + isCanBeResolved = true +} +tasks.withType { + pluginClasspath.from(testPluginClasspath) +} + dependencies { implementation(libs.gson) compileOnly(libs.android.plugin) @@ -16,7 +25,7 @@ dependencies { testImplementation(libs.android.plugin) testImplementation(libs.assertj) testImplementation(libs.mockk) - testPluginDependency("com.android.tools.build:gradle:8.13.2") + testPluginDependency("com.android.tools.build:gradle:9.0.0") } kotlin { diff --git a/stem-plugin/src/main/java/com/likethesalad/stem/StemPlugin.kt b/stem-plugin/src/main/java/com/likethesalad/stem/StemPlugin.kt index d7f57604..ceb2220f 100644 --- a/stem-plugin/src/main/java/com/likethesalad/stem/StemPlugin.kt +++ b/stem-plugin/src/main/java/com/likethesalad/stem/StemPlugin.kt @@ -1,5 +1,6 @@ package com.likethesalad.stem +import com.android.build.api.AndroidPluginVersion import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.likethesalad.stem.configuration.StemConfiguration import com.likethesalad.stem.modules.collector.task.RawStringCollectorTask @@ -28,6 +29,7 @@ class StemPlugin : Plugin { companion object { private const val EXTENSION_NAME = "androidStem" private val artifactTypeAttr = Attribute.of("artifactType", String::class.java) + private val AGP_MIN_SUPPORTED_VERSION = AndroidPluginVersion(8, 4, 0) } override fun apply(project: Project) { @@ -102,11 +104,11 @@ class StemPlugin : Plugin { val components = project.extensions.getByType(ApplicationAndroidComponentsExtension::class.java) val pluginVersion = components.pluginVersion - if (pluginVersion.major >= 8 && pluginVersion.minor >= 4) { - return components + if (pluginVersion < AGP_MIN_SUPPORTED_VERSION) { + throw IllegalStateException("Android Stem requires a minimum Android Gradle Plugin version of 8.4.0. The current version is: $pluginVersion") } - throw IllegalStateException("Android Stem requires a minimum Android Gradle Plugin version of 8.4.0. The current version is: $pluginVersion") + return components } private fun copyAttribute(key: Attribute, from: AttributeContainer, into: AttributeContainer) { diff --git a/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/CheckOutputsTest.kt b/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/CheckOutputsTest.kt index ce83a8a9..f42ec6e5 100644 --- a/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/CheckOutputsTest.kt +++ b/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/CheckOutputsTest.kt @@ -4,19 +4,19 @@ import com.likethesalad.stem.functionaltest.testtools.BasePluginTest import com.likethesalad.stem.functionaltest.testtools.PlaceholderBlock import com.likethesalad.stem.functionaltest.testtools.StemConfigBlock import com.likethesalad.stem.testutils.upperFirst -import com.likethesalad.tools.functional.testing.AndroidTestProject -import com.likethesalad.tools.functional.testing.android.blocks.AndroidBlockItem -import com.likethesalad.tools.functional.testing.android.blocks.DefaultConfigAndroidBlockItem -import com.likethesalad.tools.functional.testing.android.blocks.FlavorAndroidBlockItem -import com.likethesalad.tools.functional.testing.android.descriptor.AndroidAppProjectDescriptor -import com.likethesalad.tools.functional.testing.android.descriptor.AndroidLibProjectDescriptor -import com.likethesalad.tools.functional.testing.blocks.GradleBlockItem -import com.likethesalad.tools.functional.testing.blocks.impl.plugins.GradlePluginDeclaration -import com.likethesalad.tools.functional.testing.utils.TestAssetsProvider +import com.likethesalad.tools.AndroidTestProject +import com.likethesalad.tools.android.blocks.AndroidBlockItem +import com.likethesalad.tools.android.blocks.DefaultConfigAndroidBlockItem +import com.likethesalad.tools.android.blocks.FlavorAndroidBlockItem +import com.likethesalad.tools.android.descriptor.AndroidAppProjectDescriptor +import com.likethesalad.tools.android.descriptor.AndroidLibProjectDescriptor +import com.likethesalad.tools.blocks.GradleBlockItem +import com.likethesalad.tools.blocks.impl.plugins.GradlePluginDeclaration +import com.likethesalad.tools.utils.TestAssetsProvider import java.io.File -import junit.framework.TestCase.fail import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +import org.junit.jupiter.api.fail import org.xmlunit.builder.DiffBuilder.compare import org.xmlunit.builder.Input diff --git a/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/BasePluginTest.kt b/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/BasePluginTest.kt index e8e18f61..ce1f4c06 100644 --- a/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/BasePluginTest.kt +++ b/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/BasePluginTest.kt @@ -1,7 +1,7 @@ package com.likethesalad.stem.functionaltest.testtools -import com.likethesalad.tools.functional.testing.AndroidTestProject -import com.likethesalad.tools.functional.testing.descriptor.ProjectDescriptor +import com.likethesalad.tools.AndroidTestProject +import com.likethesalad.tools.descriptor.ProjectDescriptor import java.io.File import org.assertj.core.api.Assertions.assertThat import org.gradle.testkit.runner.BuildResult diff --git a/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/PlaceholderBlock.kt b/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/PlaceholderBlock.kt index 66106313..dd601dd5 100644 --- a/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/PlaceholderBlock.kt +++ b/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/PlaceholderBlock.kt @@ -1,6 +1,6 @@ package com.likethesalad.stem.functionaltest.testtools -import com.likethesalad.tools.functional.testing.blocks.GradleBlockItem +import com.likethesalad.tools.blocks.GradleBlockItem class PlaceholderBlock(private val start: String?=null, private val end: String?=null) : GradleBlockItem { diff --git a/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/StemConfigBlock.kt b/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/StemConfigBlock.kt index feb0adaf..2e4fca23 100644 --- a/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/StemConfigBlock.kt +++ b/stem-plugin/src/test/java/com/likethesalad/stem/functionaltest/testtools/StemConfigBlock.kt @@ -1,6 +1,6 @@ package com.likethesalad.stem.functionaltest.testtools -import com.likethesalad.tools.functional.testing.blocks.GradleBlockItem +import com.likethesalad.tools.blocks.GradleBlockItem class StemConfigBlock( private val includeLocalizedOnlyTemplates: Boolean? = null, diff --git a/stem-plugin/src/test/java/com/likethesalad/stem/modules/resolveStrings/resolver/RecursiveLevelDetectorTest.kt b/stem-plugin/src/test/java/com/likethesalad/stem/modules/resolveStrings/resolver/RecursiveLevelDetectorTest.kt index 0ab92213..96e91b27 100644 --- a/stem-plugin/src/test/java/com/likethesalad/stem/modules/resolveStrings/resolver/RecursiveLevelDetectorTest.kt +++ b/stem-plugin/src/test/java/com/likethesalad/stem/modules/resolveStrings/resolver/RecursiveLevelDetectorTest.kt @@ -5,8 +5,8 @@ import com.likethesalad.stem.configuration.StemConfiguration import com.likethesalad.stem.testutils.createForTest import com.likethesalad.stem.testutils.named import com.likethesalad.stem.tools.extensions.name -import junit.framework.TestCase.fail import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Assertions.fail import org.junit.jupiter.api.Test class RecursiveLevelDetectorTest { diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/AndroidTestProject.kt b/stem-plugin/src/test/java/com/likethesalad/tools/AndroidTestProject.kt new file mode 100644 index 00000000..d1ffaebd --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/AndroidTestProject.kt @@ -0,0 +1,138 @@ +package com.likethesalad.tools + +import com.likethesalad.tools.descriptor.ProjectDescriptor +import java.io.File +import org.gradle.testkit.runner.BuildResult +import org.gradle.testkit.runner.GradleRunner + +class AndroidTestProject(val rootDir: File) { + private lateinit var rootGradleFile: File + private lateinit var settingsFile: File + + companion object { + private const val BUILD_GRADLE_FILE_NAME = "build.gradle" + private const val ANDROID_MANIFEST_FILE_NAME = "AndroidManifest.xml" + private const val SETTINGS_GRADLE_FILE_NAME = "settings.gradle" + } + + init { + setUpRootProject() + } + + fun runGradle( + forProjectName: String, + command: String, + withInfo: Boolean = false + ): BuildResult { + return runGradle(forProjectName, listOf(command), withInfo) + } + + fun runGradleAndFail( + forProjectName: String, + command: String, + withInfo: Boolean = false + ): BuildResult { + return runGradleAndFail(forProjectName, listOf(command), withInfo) + } + + fun runGradle( + forProjectName: String, + commands: List, + withInfo: Boolean = false + ): BuildResult { + val extraArgs = mutableListOf("--stacktrace") + if (withInfo) { + extraArgs.add("--info") + } + return createGradleRunner() + .withArguments(commands.map { ":$forProjectName:$it" }.plus(extraArgs)) + .build() + } + + fun runGradleAndFail( + forProjectName: String, + commands: List, + withInfo: Boolean = false + ): BuildResult { + val extraArgs = mutableListOf("--stacktrace") + if (withInfo) { + extraArgs.add("--info") + } + return createGradleRunner() + .withArguments(commands.map { ":$forProjectName:$it" }.plus(extraArgs)) + .buildAndFail() + } + + fun addSubproject(descriptor: ProjectDescriptor) { + val name = descriptor.projectName + val projectDir = File(rootDir, name) + + projectDir.mkdirs() + + createProjectBuildGradleFile(descriptor.getBuildGradleContents(), projectDir) + createProjectManifestFile(projectDir) + descriptor.projectDirBuilder.buildDirectory(projectDir) + + settingsFile.appendText( + """ + + include '$name' + """.trimIndent() + ) + } + + private fun createGradleRunner(): GradleRunner { + return GradleRunner.create() + .withProjectDir(rootDir) + .withPluginClasspath() + } + + private fun createProjectBuildGradleFile(buildGradleContent: String, parentDir: File) { + val buildGradle = File(parentDir, BUILD_GRADLE_FILE_NAME) + buildGradle.writeText(buildGradleContent) + } + + private fun createProjectManifestFile(parentDir: File) { + val mainDir = File(parentDir, "src/main") + if (!mainDir.exists()) { + mainDir.mkdirs() + } + val androidManifest = File(mainDir, ANDROID_MANIFEST_FILE_NAME) + androidManifest.writeText( + """ + + """.trimIndent() + ) + } + + private fun setUpRootProject() { + rootGradleFile = File(rootDir, BUILD_GRADLE_FILE_NAME) + settingsFile = File(rootDir, SETTINGS_GRADLE_FILE_NAME) + + rootGradleFile.writeText( + """ + """.trimIndent() + ) + + settingsFile.writeText( + """ + pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + google() + } + } + dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + mavenCentral() + google() + gradlePluginPortal() + } + } + rootProject.name = "sample-project" + """.trimIndent() + ) + } +} \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/android/blocks/AndroidBlockItem.kt b/stem-plugin/src/test/java/com/likethesalad/tools/android/blocks/AndroidBlockItem.kt new file mode 100644 index 00000000..079af291 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/android/blocks/AndroidBlockItem.kt @@ -0,0 +1,5 @@ +package com.likethesalad.tools.android.blocks + +import com.likethesalad.tools.blocks.GradleBlockItem + +interface AndroidBlockItem : GradleBlockItem \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/android/blocks/DefaultConfigAndroidBlockItem.kt b/stem-plugin/src/test/java/com/likethesalad/tools/android/blocks/DefaultConfigAndroidBlockItem.kt new file mode 100644 index 00000000..e5b165d0 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/android/blocks/DefaultConfigAndroidBlockItem.kt @@ -0,0 +1,30 @@ +package com.likethesalad.tools.android.blocks + +class DefaultConfigAndroidBlockItem(private val strings: Map) : AndroidBlockItem { + + override fun getItemText(): String { + return """ + defaultConfig { + buildFeatures { + resValues = true + } + ${getGradleStrings()} + } + """.trimIndent() + } + + private fun getGradleStrings(): String { + val stringLines = mutableListOf() + strings.forEach { (name, value) -> + stringLines.add(getGradleStringGenDeclaration(name, value)) + } + + return stringLines.fold("") { accumulated, current -> + "$accumulated\n$current" + } + } + + private fun getGradleStringGenDeclaration(stringName: String, stringValue: String): String { + return "resValue \"string\", \"$stringName\", \"\\\"$stringValue\\\"\"" + } +} \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/android/blocks/FlavorAndroidBlockItem.kt b/stem-plugin/src/test/java/com/likethesalad/tools/android/blocks/FlavorAndroidBlockItem.kt new file mode 100644 index 00000000..369ccf71 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/android/blocks/FlavorAndroidBlockItem.kt @@ -0,0 +1,42 @@ +package com.likethesalad.tools.android.blocks + +class FlavorAndroidBlockItem(private val flavors: List) : AndroidBlockItem { + + override fun getItemText(): String { + return """ + flavorDimensions ${getFlavorDimensionsQuotedAndCommaSeparated()} + + productFlavors { + ${getProductFlavorsBlockItems()} + } + """.trimIndent() + } + + private fun getFlavorDimensionsQuotedAndCommaSeparated(): String { + return flavors.map { "\"${it.dimension}\"" }.fold("") { accumulated, current -> + if (accumulated.isEmpty()) current else "$accumulated, $current" + } + } + + private fun getProductFlavorsBlockItems(): String { + var flavorsList = "" + for (descriptor in flavors) { + val dimension = descriptor.dimension + for (flavorName in descriptor.flavorNames) { + flavorsList += "\n${getProductFlavorDefinition(dimension, flavorName)}" + } + } + + return flavorsList + } + + private fun getProductFlavorDefinition(dimension: String, flavorName: String): String { + return """ + $flavorName { + dimension = "$dimension" + } + """.trimIndent() + } + + data class FlavorDescriptor(val dimension: String, val flavorNames: List) +} \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/android/descriptor/AndroidAppProjectDescriptor.kt b/stem-plugin/src/test/java/com/likethesalad/tools/android/descriptor/AndroidAppProjectDescriptor.kt new file mode 100644 index 00000000..57bcd4e5 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/android/descriptor/AndroidAppProjectDescriptor.kt @@ -0,0 +1,12 @@ +package com.likethesalad.tools.android.descriptor + +import com.likethesalad.tools.blocks.GradleBlockItem +import java.io.File + +class AndroidAppProjectDescriptor( + name: String, + inputDir: File, + blockItems: List = emptyList(), + namespace: String = "some.localpackage.localname.forlocal.$name", + compileSdkVersion: Int = 28 +) : AndroidProjectDescriptor(name, inputDir, "com.android.application", blockItems, namespace, compileSdkVersion) \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/android/descriptor/AndroidLibProjectDescriptor.kt b/stem-plugin/src/test/java/com/likethesalad/tools/android/descriptor/AndroidLibProjectDescriptor.kt new file mode 100644 index 00000000..3f8d6345 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/android/descriptor/AndroidLibProjectDescriptor.kt @@ -0,0 +1,12 @@ +package com.likethesalad.tools.android.descriptor + +import com.likethesalad.tools.blocks.GradleBlockItem +import java.io.File + +class AndroidLibProjectDescriptor( + name: String, + inputDir: File, + blockItems: List = emptyList(), + namespace: String = "some.localpackage.localname.forlocal.$name", + compileSdkVersion: Int = 28 +) : AndroidProjectDescriptor(name, inputDir, "com.android.library", blockItems, namespace, compileSdkVersion) \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/android/descriptor/AndroidProjectDescriptor.kt b/stem-plugin/src/test/java/com/likethesalad/tools/android/descriptor/AndroidProjectDescriptor.kt new file mode 100644 index 00000000..a38c3998 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/android/descriptor/AndroidProjectDescriptor.kt @@ -0,0 +1,41 @@ +package com.likethesalad.tools.android.descriptor + +import com.likethesalad.tools.android.blocks.AndroidBlockItem +import com.likethesalad.tools.blocks.GradleBlockItem +import com.likethesalad.tools.blocks.impl.plugins.GradlePluginDeclaration +import com.likethesalad.tools.descriptor.ProjectDescriptor +import java.io.File + +open class AndroidProjectDescriptor( + name: String, + inputDir: File, + pluginId: String, + private val blockItems: List = emptyList(), + private val namespace: String = "some.localpackage.localname.forlocal.$name", + private val compileSdkVersion: Int = 28 +) : ProjectDescriptor(name, inputDir) { + + private val androidBlockItems by lazy { blockItems.filterIsInstance() } + private val gradleBlockItems by lazy { blockItems.filter { it !in androidBlockItems } } + + init { + pluginsBlock.addPlugin(GradlePluginDeclaration(pluginId)) + } + + override fun getBuildGradleContents(): String { + return """ + ${pluginsBlock.getItemText()} + + android { + namespace = "$namespace" + compileSdk $compileSdkVersion + + ${placeBlockItems(androidBlockItems)} + } + + ${placeBlockItems(gradleBlockItems)} + + ${dependenciesBlock.getItemText()} + """.trimIndent() + } +} \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/blocks/GradleBlockItem.kt b/stem-plugin/src/test/java/com/likethesalad/tools/blocks/GradleBlockItem.kt new file mode 100644 index 00000000..3e0428d5 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/blocks/GradleBlockItem.kt @@ -0,0 +1,5 @@ +package com.likethesalad.tools.blocks + +interface GradleBlockItem { + fun getItemText(): String +} \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/blocks/impl/GradleDependenciesBlockItem.kt b/stem-plugin/src/test/java/com/likethesalad/tools/blocks/impl/GradleDependenciesBlockItem.kt new file mode 100644 index 00000000..c1d1b8be --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/blocks/impl/GradleDependenciesBlockItem.kt @@ -0,0 +1,20 @@ +package com.likethesalad.tools.blocks.impl + +import com.likethesalad.tools.blocks.GradleBlockItem + +class GradleDependenciesBlockItem : GradleBlockItem { + + private val dependencies = mutableListOf() + + override fun getItemText(): String { + return """ + dependencies { + ${dependencies.joinToString("\n")} + } + """.trimIndent() + } + + fun addDependency(dependencyDeclaration: String) { + dependencies.add(dependencyDeclaration) + } +} \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/blocks/impl/plugins/GradlePluginDeclaration.kt b/stem-plugin/src/test/java/com/likethesalad/tools/blocks/impl/plugins/GradlePluginDeclaration.kt new file mode 100644 index 00000000..474ef735 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/blocks/impl/plugins/GradlePluginDeclaration.kt @@ -0,0 +1,3 @@ +package com.likethesalad.tools.blocks.impl.plugins + +data class GradlePluginDeclaration(val id: String, val version: String? = null) \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/blocks/impl/plugins/GradlePluginsBlockItem.kt b/stem-plugin/src/test/java/com/likethesalad/tools/blocks/impl/plugins/GradlePluginsBlockItem.kt new file mode 100644 index 00000000..d88641f9 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/blocks/impl/plugins/GradlePluginsBlockItem.kt @@ -0,0 +1,28 @@ +package com.likethesalad.tools.blocks.impl.plugins + +import com.likethesalad.tools.blocks.GradleBlockItem + +class GradlePluginsBlockItem : GradleBlockItem { + + private val plugins = mutableListOf() + + override fun getItemText(): String { + return """ + plugins { + ${plugins.joinToString("\n") { convertToStringDeclaration(it) }} + } + """.trimIndent() + } + + private fun convertToStringDeclaration(declaration: GradlePluginDeclaration): String { + var result = "id '${declaration.id}'" + declaration.version?.let { version -> + result += " version '$version'" + } + return result + } + + fun addPlugin(plugin: GradlePluginDeclaration) { + plugins.add(plugin) + } +} \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/content/ProjectDirBuilder.kt b/stem-plugin/src/test/java/com/likethesalad/tools/content/ProjectDirBuilder.kt new file mode 100644 index 00000000..16b26d5f --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/content/ProjectDirBuilder.kt @@ -0,0 +1,37 @@ +package com.likethesalad.tools.content + +import java.io.File + +class ProjectDirBuilder(private val inputDir: File) { + + private val createdFiles = mutableListOf() + + fun buildDirectory(projectDir: File) { + val dir = File(projectDir, "src") + if (!dir.exists()) { + dir.mkdirs() + } + + onDirReady(dir) + } + + fun clearFilesCreated() { + return createdFiles.forEach { it.deleteRecursively() } + } + + private fun onDirReady(dir: File) { + moveFilesToDir(inputDir.listFiles(), dir) + } + + private fun moveFilesToDir(files: Array?, destinationDir: File) { + files?.forEach { + if (it.isDirectory) { + moveFilesToDir(it.listFiles(), File(destinationDir, it.name)) + } else { + val target = File(destinationDir, it.name) + createdFiles.add(target) + it.copyTo(target) + } + } + } +} \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/descriptor/ProjectDescriptor.kt b/stem-plugin/src/test/java/com/likethesalad/tools/descriptor/ProjectDescriptor.kt new file mode 100644 index 00000000..38df41f1 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/descriptor/ProjectDescriptor.kt @@ -0,0 +1,24 @@ +package com.likethesalad.tools.descriptor + +import com.likethesalad.tools.blocks.GradleBlockItem +import com.likethesalad.tools.blocks.impl.GradleDependenciesBlockItem +import com.likethesalad.tools.blocks.impl.plugins.GradlePluginsBlockItem +import com.likethesalad.tools.content.ProjectDirBuilder +import java.io.File + +abstract class ProjectDescriptor(val projectName: String, inputDir: File) { + + val projectDirBuilder = ProjectDirBuilder(inputDir) + val pluginsBlock = GradlePluginsBlockItem() + val dependenciesBlock = GradleDependenciesBlockItem() + + abstract fun getBuildGradleContents(): String + + protected fun placeBlockItems(blockItems: List): String { + if (blockItems.isEmpty()) { + return "" + } + + return blockItems.joinToString("\n") { it.getItemText() } + } +} \ No newline at end of file diff --git a/stem-plugin/src/test/java/com/likethesalad/tools/utils/TestAssetsProvider.kt b/stem-plugin/src/test/java/com/likethesalad/tools/utils/TestAssetsProvider.kt new file mode 100644 index 00000000..1719adb6 --- /dev/null +++ b/stem-plugin/src/test/java/com/likethesalad/tools/utils/TestAssetsProvider.kt @@ -0,0 +1,28 @@ +package com.likethesalad.tools.utils + +import java.io.File +import java.nio.file.Paths + +class TestAssetsProvider( + private val assetsFolderName: String +) { + private var testsDirName: String = "test" + + private val functionalAssetsDir: File by lazy { + Paths.get("src", testsDirName, "assets", assetsFolderName).toFile() + } + + fun withTestsDirName(testsDirName: String): TestAssetsProvider { + this.testsDirName = testsDirName + return this + } + + fun getFile(relativePath: String): File { + val asset = File(functionalAssetsDir, relativePath) + if (!asset.exists()) { + throw IllegalArgumentException("Asset '$asset' not found in '$assetsFolderName'") + } + + return asset + } +} \ No newline at end of file