Browse Source
1) The PR adds a support test resources in Compose multiplatform projects. 2) The PR adds a support multi-module resources in JVM-only projects. Fixes https://youtrack.jetbrains.com/issue/CMP-1470 Fixes https://youtrack.jetbrains.com/issue/CMP-5963 ## Release Notes ### Features - Resources - Added support of test resources in Compose Multiplatform projects - Added support of multi-module resources in JVM-only projectsrelease/1.7.0-beta01
Konstantin
3 months ago
committed by
GitHub
25 changed files with 518 additions and 206 deletions
@ -0,0 +1,56 @@ |
|||||||
|
package org.jetbrains.compose.resources |
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask |
||||||
|
import org.gradle.api.file.ConfigurableFileCollection |
||||||
|
import org.gradle.api.file.DirectoryProperty |
||||||
|
import org.gradle.api.file.DuplicatesStrategy |
||||||
|
import org.gradle.api.file.FileSystemOperations |
||||||
|
import org.gradle.api.provider.Property |
||||||
|
import org.gradle.api.tasks.Input |
||||||
|
import org.gradle.api.tasks.InputFiles |
||||||
|
import org.gradle.api.tasks.OutputDirectory |
||||||
|
import org.gradle.api.tasks.PathSensitive |
||||||
|
import org.gradle.api.tasks.PathSensitivity |
||||||
|
import org.gradle.api.tasks.TaskAction |
||||||
|
import org.gradle.work.DisableCachingByDefault |
||||||
|
import java.io.File |
||||||
|
import javax.inject.Inject |
||||||
|
|
||||||
|
@DisableCachingByDefault(because = "There is no logic, just copy files") |
||||||
|
internal abstract class AssembleTargetResourcesTask : DefaultTask() { |
||||||
|
|
||||||
|
@get:Inject |
||||||
|
abstract val fileSystem: FileSystemOperations |
||||||
|
|
||||||
|
@get:InputFiles |
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE) |
||||||
|
abstract val resourceDirectories: ConfigurableFileCollection |
||||||
|
|
||||||
|
@get:Input |
||||||
|
abstract val relativeResourcePlacement: Property<File> |
||||||
|
|
||||||
|
@get:OutputDirectory |
||||||
|
abstract val outputDirectory: DirectoryProperty |
||||||
|
|
||||||
|
@TaskAction |
||||||
|
fun action() { |
||||||
|
val outputDirectoryFile = outputDirectory.get().asFile |
||||||
|
if (outputDirectoryFile.exists()) { |
||||||
|
outputDirectoryFile.deleteRecursively() |
||||||
|
} |
||||||
|
outputDirectoryFile.mkdirs() |
||||||
|
|
||||||
|
fileSystem.copy { copy -> |
||||||
|
resourceDirectories.files.forEach { dir -> |
||||||
|
copy.from(dir) |
||||||
|
} |
||||||
|
copy.into(outputDirectoryFile.resolve(relativeResourcePlacement.get())) |
||||||
|
copy.duplicatesStrategy = DuplicatesStrategy.INCLUDE |
||||||
|
} |
||||||
|
|
||||||
|
if (outputDirectoryFile.listFiles()?.isEmpty() != false) { |
||||||
|
// Output an empty directory for the zip task |
||||||
|
outputDirectoryFile.resolve(relativeResourcePlacement.get()).mkdirs() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,95 +0,0 @@ |
|||||||
package org.jetbrains.compose.resources |
|
||||||
|
|
||||||
import org.gradle.api.Project |
|
||||||
import org.gradle.api.provider.Provider |
|
||||||
import org.jetbrains.kotlin.gradle.ComposeKotlinGradlePluginApi |
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension |
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension |
|
||||||
import org.jetbrains.kotlin.gradle.plugin.* |
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.* |
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.resources.KotlinTargetResourcesPublication |
|
||||||
import java.io.File |
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ComposeKotlinGradlePluginApi::class) |
|
||||||
internal fun Project.configureKmpResources( |
|
||||||
kotlinExtension: KotlinProjectExtension, |
|
||||||
kmpResources: Any, |
|
||||||
config: Provider<ResourcesExtension> |
|
||||||
) { |
|
||||||
kotlinExtension as KotlinMultiplatformExtension |
|
||||||
kmpResources as KotlinTargetResourcesPublication |
|
||||||
|
|
||||||
logger.info("Configure KMP resources") |
|
||||||
|
|
||||||
val commonMain = KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME |
|
||||||
configureComposeResourcesGeneration(kotlinExtension, commonMain, config, true) |
|
||||||
|
|
||||||
//configure KMP resources publishing for each supported target |
|
||||||
kotlinExtension.targets |
|
||||||
.matching { target -> kmpResources.canPublishResources(target) } |
|
||||||
.all { target -> |
|
||||||
logger.info("Configure resources publication for '${target.targetName}' target") |
|
||||||
val packedResourceDir = config.getModuleResourcesDir(project) |
|
||||||
|
|
||||||
if (target !is KotlinAndroidTarget) { |
|
||||||
kmpResources.publishResourcesAsKotlinComponent( |
|
||||||
target, |
|
||||||
{ sourceSet -> |
|
||||||
KotlinTargetResourcesPublication.ResourceRoot( |
|
||||||
getPreparedComposeResourcesDir(sourceSet), |
|
||||||
emptyList(), |
|
||||||
emptyList() |
|
||||||
) |
|
||||||
}, |
|
||||||
packedResourceDir |
|
||||||
) |
|
||||||
} else { |
|
||||||
//for android target publish resources in assets |
|
||||||
kmpResources.publishInAndroidAssets( |
|
||||||
target, |
|
||||||
{ sourceSet -> |
|
||||||
KotlinTargetResourcesPublication.ResourceRoot( |
|
||||||
getPreparedComposeResourcesDir(sourceSet), |
|
||||||
emptyList(), |
|
||||||
emptyList() |
|
||||||
) |
|
||||||
}, |
|
||||||
packedResourceDir |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//add all resolved resources for browser and native compilations |
|
||||||
val platformsForSetupCompilation = listOf(KotlinPlatformType.native, KotlinPlatformType.js, KotlinPlatformType.wasm) |
|
||||||
kotlinExtension.targets |
|
||||||
.matching { target -> target.platformType in platformsForSetupCompilation } |
|
||||||
.all { target: KotlinTarget -> |
|
||||||
val allResources = kmpResources.resolveResources(target) |
|
||||||
target.compilations.all { compilation -> |
|
||||||
if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) { |
|
||||||
configureResourcesForCompilation(compilation, allResources) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add resolved resources to a kotlin compilation to include it into a resulting platform artefact |
|
||||||
* It is required for JS and Native targets. |
|
||||||
* For JVM and Android it works automatically via jar files |
|
||||||
*/ |
|
||||||
private fun Project.configureResourcesForCompilation( |
|
||||||
compilation: KotlinCompilation<*>, |
|
||||||
directoryWithAllResourcesForCompilation: Provider<File> |
|
||||||
) { |
|
||||||
logger.info("Add all resolved resources to '${compilation.target.targetName}' target '${compilation.name}' compilation") |
|
||||||
compilation.defaultSourceSet.resources.srcDir(directoryWithAllResourcesForCompilation) |
|
||||||
|
|
||||||
//JS packaging requires explicit dependency |
|
||||||
if (compilation is KotlinJsCompilation) { |
|
||||||
tasks.named(compilation.processResourcesTaskName).configure { processResourcesTask -> |
|
||||||
processResourcesTask.dependsOn(directoryWithAllResourcesForCompilation) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,144 @@ |
|||||||
|
package org.jetbrains.compose.resources |
||||||
|
|
||||||
|
import org.gradle.api.Project |
||||||
|
import org.gradle.api.provider.Provider |
||||||
|
import org.gradle.api.tasks.SourceSet |
||||||
|
import org.jetbrains.compose.internal.utils.registerTask |
||||||
|
import org.jetbrains.compose.internal.utils.uppercaseFirstChar |
||||||
|
import org.jetbrains.kotlin.gradle.ComposeKotlinGradlePluginApi |
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension |
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension |
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation |
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType |
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet |
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget |
||||||
|
import org.jetbrains.kotlin.gradle.plugin.extraProperties |
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation |
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.resources.KotlinTargetResourcesPublication |
||||||
|
import java.io.File |
||||||
|
|
||||||
|
//configure multi-module resources (with publishing and module isolation) |
||||||
|
internal fun Project.configureMultimoduleResources( |
||||||
|
kotlinExtension: KotlinMultiplatformExtension, |
||||||
|
config: Provider<ResourcesExtension> |
||||||
|
) { |
||||||
|
logger.info("Configure multi-module compose resources") |
||||||
|
|
||||||
|
val commonMain = KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME |
||||||
|
configureComposeResourcesGeneration(kotlinExtension, commonMain, config, true) |
||||||
|
|
||||||
|
val moduleIsolationDirectory = config.getModuleResourcesDir(project) |
||||||
|
|
||||||
|
val platformsForSkip = listOf( |
||||||
|
KotlinPlatformType.common, KotlinPlatformType.androidJvm |
||||||
|
) |
||||||
|
kotlinExtension.targets |
||||||
|
.matching { target -> target.platformType !in platformsForSkip } |
||||||
|
.all { target -> configureTargetResources(target, moduleIsolationDirectory) } |
||||||
|
|
||||||
|
//configure ANDROID resources |
||||||
|
onAgpApplied { |
||||||
|
configureAndroidComposeResources(moduleIsolationDirectory) |
||||||
|
fixAndroidLintTaskDependencies() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//configure java multi-module resources (with module isolation) |
||||||
|
internal fun Project.configureJvmOnlyResources( |
||||||
|
kotlinExtension: KotlinJvmProjectExtension, |
||||||
|
config: Provider<ResourcesExtension> |
||||||
|
) { |
||||||
|
logger.info("Configure java-only compose resources") |
||||||
|
|
||||||
|
val main = SourceSet.MAIN_SOURCE_SET_NAME |
||||||
|
configureComposeResourcesGeneration(kotlinExtension, main, config, true) |
||||||
|
|
||||||
|
val moduleIsolationDirectory = config.getModuleResourcesDir(project) |
||||||
|
val javaTarget = kotlinExtension.target |
||||||
|
|
||||||
|
configureTargetResources(javaTarget, moduleIsolationDirectory) |
||||||
|
} |
||||||
|
|
||||||
|
private fun Project.configureTargetResources( |
||||||
|
target: KotlinTarget, |
||||||
|
moduleIsolationDirectory: Provider<File> |
||||||
|
) { |
||||||
|
target.compilations.all { compilation -> |
||||||
|
logger.info("Configure ${compilation.name} resources for '${target.targetName}' target") |
||||||
|
val compilationResources = files({ |
||||||
|
compilation.allKotlinSourceSets.map { sourceSet -> getPreparedComposeResourcesDir(sourceSet) } |
||||||
|
}) |
||||||
|
val assembleResTask = registerTask<AssembleTargetResourcesTask>( |
||||||
|
name = "assemble${target.targetName.uppercaseFirstChar()}${compilation.name.uppercaseFirstChar()}Resources" |
||||||
|
) { |
||||||
|
resourceDirectories.setFrom(compilationResources) |
||||||
|
relativeResourcePlacement.set(moduleIsolationDirectory) |
||||||
|
outputDirectory.set( |
||||||
|
layout.buildDirectory.dir( |
||||||
|
"$RES_GEN_DIR/assembledResources/${target.targetName}${compilation.name.uppercaseFirstChar()}" |
||||||
|
) |
||||||
|
) |
||||||
|
} |
||||||
|
val allCompilationResources = assembleResTask.flatMap { it.outputDirectory.asFile } |
||||||
|
|
||||||
|
if ( |
||||||
|
target.platformType in platformsForSetupKmpResources |
||||||
|
&& compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME |
||||||
|
) { |
||||||
|
configureKmpResources(compilation, allCompilationResources) |
||||||
|
} else { |
||||||
|
configureResourcesForCompilation(compilation, allCompilationResources) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private val platformsForSetupKmpResources = listOf( |
||||||
|
KotlinPlatformType.native, KotlinPlatformType.js, KotlinPlatformType.wasm |
||||||
|
) |
||||||
|
|
||||||
|
@OptIn(ComposeKotlinGradlePluginApi::class) |
||||||
|
private fun Project.configureKmpResources( |
||||||
|
compilation: KotlinCompilation<*>, |
||||||
|
allCompilationResources: Provider<File> |
||||||
|
) { |
||||||
|
require(compilation.platformType in platformsForSetupKmpResources) |
||||||
|
val kmpResources = extraProperties.get(KMP_RES_EXT) as KotlinTargetResourcesPublication |
||||||
|
|
||||||
|
//For Native/Js/Wasm main resources: |
||||||
|
// 1) we have to configure new Kotlin component publication |
||||||
|
// 2) we have to collect all transitive main resources |
||||||
|
|
||||||
|
//TODO temporary API misuse. will be changed on the KMP side |
||||||
|
//https://youtrack.jetbrains.com/issue/KT-70909 |
||||||
|
val target = compilation.target |
||||||
|
val kmpResourceRoot = KotlinTargetResourcesPublication.ResourceRoot( |
||||||
|
allCompilationResources, |
||||||
|
emptyList(), |
||||||
|
emptyList() |
||||||
|
) |
||||||
|
val kmpEmptyPath = provider { File("") } |
||||||
|
logger.info("Configure KMP component publication for '${compilation.target.targetName}'") |
||||||
|
kmpResources.publishResourcesAsKotlinComponent( |
||||||
|
target, |
||||||
|
{ kmpResourceRoot }, |
||||||
|
kmpEmptyPath |
||||||
|
) |
||||||
|
|
||||||
|
val allResources = kmpResources.resolveResources(target) |
||||||
|
logger.info("Collect resolved ${compilation.name} resources for '${compilation.target.targetName}'") |
||||||
|
configureResourcesForCompilation(compilation, allResources) |
||||||
|
} |
||||||
|
|
||||||
|
private fun Project.configureResourcesForCompilation( |
||||||
|
compilation: KotlinCompilation<*>, |
||||||
|
directoryWithAllResourcesForCompilation: Provider<File> |
||||||
|
) { |
||||||
|
compilation.defaultSourceSet.resources.srcDir(directoryWithAllResourcesForCompilation) |
||||||
|
|
||||||
|
//JS packaging requires explicit dependency |
||||||
|
if (compilation is KotlinJsCompilation) { |
||||||
|
tasks.named(compilation.processResourcesTaskName).configure { processResourcesTask -> |
||||||
|
processResourcesTask.dependsOn(directoryWithAllResourcesForCompilation) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package org.jetbrains.compose.resources |
||||||
|
|
||||||
|
import org.gradle.api.Project |
||||||
|
import org.gradle.api.provider.Provider |
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension |
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet |
||||||
|
|
||||||
|
//configure single-module resources (no publishing, no module isolation) |
||||||
|
internal fun Project.configureSinglemoduleResources( |
||||||
|
kotlinExtension: KotlinMultiplatformExtension, |
||||||
|
config: Provider<ResourcesExtension> |
||||||
|
) { |
||||||
|
logger.info("Configure single-module compose resources") |
||||||
|
val commonMain = KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME |
||||||
|
configureComposeResourcesGeneration(kotlinExtension, commonMain, config, false) |
||||||
|
|
||||||
|
// mark prepared resources as sourceSet.resources |
||||||
|
// 1) it automatically packs the resources to JVM jars |
||||||
|
// 2) it configures the webpack to use the resources |
||||||
|
// 3) for native targets we will use source set resources to pack them into the final app. see IosResources.kt |
||||||
|
// 4) for the android it DOESN'T pack resources! we copy resources to assets in AndroidResources.kt |
||||||
|
kotlinExtension.sourceSets.all { sourceSet -> |
||||||
|
// the HACK is here because KGP copy androidMain java resources to Android target |
||||||
|
// if the resources were registered in the androidMain source set before the target declaration |
||||||
|
afterEvaluate { |
||||||
|
sourceSet.resources.srcDirs(getPreparedComposeResourcesDir(sourceSet)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
onAgpApplied { |
||||||
|
configureAndroidComposeResources() |
||||||
|
fixAndroidLintTaskDependencies() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
import org.jetbrains.compose.ExperimentalComposeLibrary |
||||||
|
|
||||||
|
plugins { |
||||||
|
kotlin("multiplatform") |
||||||
|
kotlin("plugin.compose") |
||||||
|
id("org.jetbrains.compose") |
||||||
|
} |
||||||
|
|
||||||
|
group = "app.group" |
||||||
|
|
||||||
|
kotlin { |
||||||
|
jvm("desktop") |
||||||
|
|
||||||
|
iosX64() |
||||||
|
iosArm64() |
||||||
|
iosSimulatorArm64() |
||||||
|
|
||||||
|
sourceSets { |
||||||
|
commonMain { |
||||||
|
dependencies { |
||||||
|
implementation(compose.runtime) |
||||||
|
implementation(compose.material) |
||||||
|
implementation(compose.components.resources) |
||||||
|
} |
||||||
|
} |
||||||
|
commonTest { |
||||||
|
dependencies { |
||||||
|
implementation(kotlin("test")) |
||||||
|
@OptIn(ExperimentalComposeLibrary::class) |
||||||
|
implementation(compose.uiTest) |
||||||
|
} |
||||||
|
} |
||||||
|
val desktopMain by getting { |
||||||
|
dependencies { |
||||||
|
implementation(compose.desktop.currentOs) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
org.gradle.jvmargs=-Xmx8096M |
||||||
|
android.useAndroidX=true |
||||||
|
org.jetbrains.compose.experimental.jscanvas.enabled=true |
@ -0,0 +1,24 @@ |
|||||||
|
rootProject.name = "Resources-Test" |
||||||
|
pluginManagement { |
||||||
|
repositories { |
||||||
|
mavenLocal() |
||||||
|
gradlePluginPortal() |
||||||
|
google() |
||||||
|
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") |
||||||
|
} |
||||||
|
plugins { |
||||||
|
id("com.android.application").version("AGP_VERSION_PLACEHOLDER") |
||||||
|
id("org.jetbrains.kotlin.multiplatform").version("KOTLIN_VERSION_PLACEHOLDER") |
||||||
|
id("org.jetbrains.kotlin.plugin.compose").version("KOTLIN_VERSION_PLACEHOLDER") |
||||||
|
id("org.jetbrains.compose").version("COMPOSE_GRADLE_PLUGIN_VERSION_PLACEHOLDER") |
||||||
|
} |
||||||
|
} |
||||||
|
dependencyResolutionManagement { |
||||||
|
repositories { |
||||||
|
mavenLocal() |
||||||
|
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") |
||||||
|
mavenCentral() |
||||||
|
gradlePluginPortal() |
||||||
|
google() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
common 777 |
@ -0,0 +1,3 @@ |
|||||||
|
<resources> |
||||||
|
<string name="app_name">Compose Resources App</string> |
||||||
|
</resources> |
@ -0,0 +1,7 @@ |
|||||||
|
import androidx.compose.material.Text |
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
|
||||||
|
@Composable |
||||||
|
fun App() { |
||||||
|
Text("app") |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
1234567890 |
@ -0,0 +1,3 @@ |
|||||||
|
<resources> |
||||||
|
<string name="test_string">Common test</string> |
||||||
|
</resources> |
@ -0,0 +1,34 @@ |
|||||||
|
import androidx.compose.ui.test.ExperimentalTestApi |
||||||
|
import androidx.compose.ui.test.runComposeUiTest |
||||||
|
import app.group.resources_test.generated.resources.Res |
||||||
|
import app.group.resources_test.generated.resources.app_name |
||||||
|
import app.group.resources_test.generated.resources.test_string |
||||||
|
import kotlinx.coroutines.test.runTest |
||||||
|
import org.jetbrains.compose.resources.ExperimentalResourceApi |
||||||
|
import org.jetbrains.compose.resources.stringResource |
||||||
|
import kotlin.test.Test |
||||||
|
import kotlin.test.assertEquals |
||||||
|
import kotlin.test.assertNotEquals |
||||||
|
|
||||||
|
@OptIn(ExperimentalTestApi::class, ExperimentalResourceApi::class) |
||||||
|
class CommonUiTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
fun checkTestResources() = runComposeUiTest { |
||||||
|
setContent { |
||||||
|
val mainStr = stringResource(Res.string.app_name) |
||||||
|
val testStr = stringResource(Res.string.test_string) |
||||||
|
assertEquals("Compose Resources App", mainStr) |
||||||
|
assertEquals("Common test", testStr) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun checkTestFileResource() = runTest { |
||||||
|
val commonFile = Res.readBytes("files/common.txt").decodeToString() |
||||||
|
assertEquals("common 777", commonFile) |
||||||
|
val testFile = Res.readBytes("files/data.txt").decodeToString() |
||||||
|
assertEquals("1234567890", testFile) |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
<resources> |
||||||
|
<string name="desktop_str">Desktop string</string> |
||||||
|
</resources> |
@ -0,0 +1,3 @@ |
|||||||
|
<resources> |
||||||
|
<string name="desktop_test_str">Desktop test string</string> |
||||||
|
</resources> |
@ -0,0 +1,29 @@ |
|||||||
|
import androidx.compose.ui.test.ExperimentalTestApi |
||||||
|
import androidx.compose.ui.test.runComposeUiTest |
||||||
|
import app.group.resources_test.generated.resources.Res |
||||||
|
import app.group.resources_test.generated.resources.app_name |
||||||
|
import app.group.resources_test.generated.resources.desktop_str |
||||||
|
import app.group.resources_test.generated.resources.desktop_test_str |
||||||
|
import app.group.resources_test.generated.resources.test_string |
||||||
|
import org.jetbrains.compose.resources.stringResource |
||||||
|
import kotlin.test.Test |
||||||
|
import kotlin.test.assertEquals |
||||||
|
|
||||||
|
@OptIn(ExperimentalTestApi::class) |
||||||
|
class DesktopUiTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
fun checkTestResources() = runComposeUiTest { |
||||||
|
setContent { |
||||||
|
val mainStr = stringResource(Res.string.app_name) |
||||||
|
val testStr = stringResource(Res.string.test_string) |
||||||
|
val desktopMainStr = stringResource(Res.string.desktop_str) |
||||||
|
val desktopTestStr = stringResource(Res.string.desktop_test_str) |
||||||
|
assertEquals("Compose Resources App", mainStr) |
||||||
|
assertEquals("Common test", testStr) |
||||||
|
assertEquals("Desktop string", desktopMainStr) |
||||||
|
assertEquals("Desktop test string", desktopTestStr) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue