Skip to content

Commit 71dfccf

Browse files
committed
Introduce test for invoking composeCompatibilityBrowserDistribution in heavily reconfigured project (#5380)
CompatibilityDistributionTest::testWebJsWasmReconfigured makes sure that composeCompatibilityBrowserDistribution task can be reconfigured to be used with arbitrary set of input tasks ## Testing Pipeline ## Release Notes N/A
1 parent db964f1 commit 71dfccf

File tree

13 files changed

+318
-66
lines changed

13 files changed

+318
-66
lines changed

gradle-plugins/compose/src/test/kotlin/org/jetbrains/compose/test/tests/integration/CompatibilityDistributionTest.kt

Lines changed: 0 additions & 66 deletions
This file was deleted.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package org.jetbrains.compose.test.tests.integration
2+
3+
import org.jetbrains.compose.test.utils.GradlePluginTestBase
4+
import org.jetbrains.compose.test.utils.TestProject
5+
import org.jetbrains.compose.test.utils.checkExists
6+
import org.jetbrains.compose.test.utils.checks
7+
import org.junit.jupiter.api.Test
8+
import kotlin.test.assertEquals
9+
import kotlin.test.assertTrue
10+
11+
class WebCompatibilityDistributionTest : GradlePluginTestBase() {
12+
private val defaultDistDir = "./composeApp/build/dist/composeWebCompatibility/productionExecutable"
13+
14+
private fun TestProject.assertCompatibilityDistribution(
15+
dirPath: String,
16+
expectedFileNames: Set<String>
17+
) {
18+
file(dirPath).apply {
19+
checkExists()
20+
assertTrue(isDirectory, "Expected $dirPath to be a directory")
21+
22+
val listed = listFiles()
23+
?: error("Expected to list files in $dirPath but got null")
24+
val distributionNames = listed.map { it.name }
25+
26+
assertTrue(
27+
distributionNames.any { it.endsWith(".wasm") },
28+
"Expected at least one .wasm file in $dirPath, found: $distributionNames"
29+
)
30+
31+
val actualFiles = distributionNames.filterNot { it.endsWith(".wasm") }.toSet()
32+
assertEquals(expectedFileNames, actualFiles, "files mismatch in $dirPath")
33+
}
34+
}
35+
36+
private fun runCompatibilityTest(
37+
projectPath: String,
38+
successfulTasks: List<String>,
39+
distDir: String = defaultDistDir,
40+
expectedFiles: Set<String>
41+
) = with(
42+
testProject(
43+
projectPath,
44+
testEnvironment = defaultTestEnvironment.copy()
45+
)
46+
) {
47+
gradle(":composeApp:composeCompatibilityBrowserDistribution").checks {
48+
check.taskSuccessful(":composeApp:composeCompatibilityBrowserDistribution")
49+
successfulTasks.forEach { check.taskSuccessful(it) }
50+
assertCompatibilityDistribution(dirPath = distDir, expectedFileNames = expectedFiles)
51+
}
52+
}
53+
54+
@Test
55+
fun testWebJsWasm() = runCompatibilityTest(
56+
projectPath = "application/webJsWasm",
57+
successfulTasks = listOf(
58+
":composeApp:jsBrowserDistribution",
59+
":composeApp:wasmJsBrowserDistribution"
60+
),
61+
expectedFiles = setOf(
62+
"composeApp.js",
63+
"composeResources",
64+
"index.html",
65+
"originJsComposeApp.js",
66+
"originJsComposeApp.js.map",
67+
"originWasmComposeApp.js",
68+
"originWasmComposeApp.js.map",
69+
"styles.css"
70+
)
71+
)
72+
73+
@Test
74+
fun testWebJsWasmNonStandard() = runCompatibilityTest(
75+
projectPath = "application/webJsWasmNonStandard",
76+
successfulTasks = listOf(
77+
":composeApp:webJsBrowserDistribution",
78+
":composeApp:webWasmBrowserDistribution"
79+
),
80+
expectedFiles = setOf(
81+
"composeApp.js",
82+
"composeResources",
83+
"index.html",
84+
"originJsComposeApp.js",
85+
"originJsComposeApp.js.map",
86+
"originWasmComposeApp.js",
87+
"originWasmComposeApp.js.map",
88+
"styles.css"
89+
)
90+
)
91+
92+
@Test
93+
fun testWebJsWasmReconfigured() = runCompatibilityTest(
94+
projectPath = "application/webJsWasmReconfigured",
95+
successfulTasks = listOf(
96+
":composeApp:wasmRepack",
97+
":composeApp:jsRepack"
98+
),
99+
expectedFiles = setOf(
100+
"composeResources",
101+
"index.html",
102+
"originJsRepackedApp.js",
103+
"originJsRepackedApp.js.map",
104+
"originWasmRepackedApp.js",
105+
"originWasmRepackedApp.js.map",
106+
"repackedApp.js",
107+
"styles.css"
108+
)
109+
)
110+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
plugins {
2+
// this is necessary to avoid the plugins to be loaded multiple times
3+
// in each subproject's classloader
4+
id("org.jetbrains.kotlin.multiplatform") apply false
5+
id("org.jetbrains.compose") apply false
6+
id("org.jetbrains.kotlin.plugin.compose") apply false
7+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
2+
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
3+
4+
plugins {
5+
id("org.jetbrains.kotlin.multiplatform")
6+
id("org.jetbrains.compose")
7+
id("org.jetbrains.kotlin.plugin.compose")
8+
}
9+
10+
kotlin {
11+
js(name = "webJs", IR) {
12+
outputModuleName.set("composeApp")
13+
browser {
14+
commonWebpackConfig {
15+
outputFileName = "composeApp.js"
16+
}
17+
}
18+
binaries.executable()
19+
}
20+
21+
@OptIn(ExperimentalWasmDsl::class)
22+
wasmJs(name = "webWasm") {
23+
outputModuleName.set("composeApp")
24+
browser {
25+
val rootDirPath = project.rootDir.path
26+
val projectDirPath = project.projectDir.path
27+
commonWebpackConfig {
28+
outputFileName = "composeApp.js"
29+
}
30+
}
31+
binaries.executable()
32+
}
33+
34+
// Simple task that prints "Hello World" to the console
35+
36+
sourceSets {
37+
commonMain.dependencies {
38+
implementation(compose.runtime)
39+
}
40+
41+
val webMain by creating {
42+
resources.setSrcDirs(resources.srcDirs)
43+
dependsOn(commonMain.get())
44+
}
45+
46+
val webJsMain by getting {
47+
dependsOn(webMain)
48+
}
49+
50+
val webWasmMain by getting {
51+
dependsOn(webMain)
52+
}
53+
}
54+
}
55+
56+
57+
val wasmRepack = tasks.register<RepackTask>("wasmRepack") {
58+
sourceFiles.from(project.tasks.named("webWasmBrowserDistribution").map { it.outputs.files })
59+
outputDir.set(project.layout.buildDirectory.dir("dist/repackedWasm"))
60+
}
61+
62+
val jsRepack = tasks.register<RepackTask>("jsRepack") {
63+
sourceFiles.from(project.tasks.named("webJsBrowserDistribution").map { it.outputs.files })
64+
outputDir.set(project.layout.buildDirectory.dir("dist/repackedJs"))
65+
}
66+
67+
project.tasks.withType<org.jetbrains.compose.web.tasks.WebCompatibilityTask>().configureEach {
68+
jsOutputName.set("repackedApp.js")
69+
wasmOutputName.set("repackedApp.js")
70+
jsDistFiles.setFrom(jsRepack)
71+
wasmDistFiles.setFrom(wasmRepack)
72+
}
73+
74+
abstract class RepackTask : DefaultTask() {
75+
@get:Inject
76+
internal abstract val fileOperations: FileSystemOperations
77+
78+
@get:InputFiles
79+
abstract val sourceFiles: ConfigurableFileCollection
80+
81+
@get:OutputDirectory
82+
abstract val outputDir: DirectoryProperty
83+
84+
@TaskAction
85+
fun run() {
86+
fileOperations.copy {
87+
from(sourceFiles) {
88+
this.rename { name ->
89+
when (name) {
90+
"composeApp.js" -> "repackedApp.js"
91+
"composeApp.js.map" -> "repackedApp.js.map"
92+
else -> name
93+
}
94+
}
95+
}
96+
into(outputDir)
97+
}
98+
}
99+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.example.project
2+
3+
private class JsPlatform : Platform {
4+
override val name: String = "Web with Kotlin/JS"
5+
}
6+
7+
actual fun getPlatform(): Platform = JsPlatform()
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.example.project
2+
3+
class Greeting {
4+
private val platform = getPlatform()
5+
6+
fun greet(): String {
7+
return "Hello, ${platform.name}!"
8+
}
9+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.example.project
2+
3+
interface Platform {
4+
val name: String
5+
}
6+
7+
expect fun getPlatform(): Platform
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.example.project
2+
3+
fun main() {
4+
println(Greeting().greet())
5+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>KotlinProject</title>
7+
<link type="text/css" rel="stylesheet" href="styles.css">
8+
</head>
9+
<body>
10+
</body>
11+
<script type="application/javascript" src="composeApp.js"></script>
12+
13+
</html>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
html, body {
2+
width: 100%;
3+
height: 100%;
4+
margin: 0;
5+
padding: 0;
6+
overflow: hidden;
7+
}

0 commit comments

Comments
 (0)