@granite-js/screen 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/GraniteScreen.podspec +25 -0
- package/LICENSE +202 -0
- package/android/CMakeLists.txt +62 -0
- package/android/build.gradle +63 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/BundleEvaluator.cpp +27 -0
- package/android/src/main/cpp/BundleEvaluator.h +17 -0
- package/android/src/main/cpp/onLoad.cpp +6 -0
- package/android/src/main/kotlin/run/granite/BundleEvaluator.kt +50 -0
- package/android/src/main/kotlin/run/granite/BundleLoader.kt +40 -0
- package/android/src/main/kotlin/run/granite/DefaultBundleLoader.kt +20 -0
- package/android/src/main/kotlin/run/granite/DefaultErrorView.kt +58 -0
- package/android/src/main/kotlin/run/granite/DefaultLoadingView.kt +51 -0
- package/android/src/main/kotlin/run/granite/GraniteReactDelegate.kt +76 -0
- package/android/src/main/kotlin/run/granite/GraniteReactDelegateImpl.kt +448 -0
- package/android/src/main/kotlin/run/granite/GraniteReactHost.kt +113 -0
- package/android/src/main/kotlin/run/granite/ReactHostFactory.kt +106 -0
- package/gradle-plugin/LICENSE +201 -0
- package/gradle-plugin/README.md +578 -0
- package/gradle-plugin/build.gradle.kts +97 -0
- package/gradle-plugin/gradle/libs.versions.toml +17 -0
- package/gradle-plugin/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle-plugin/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/gradle-plugin/gradle.properties +12 -0
- package/gradle-plugin/gradlew +248 -0
- package/gradle-plugin/gradlew.bat +93 -0
- package/gradle-plugin/settings.gradle.kts +1 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GraniteExtension.kt +225 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GranitePlugin.kt +784 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GraniteRootExtension.kt +107 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GraniteRootProjectPlugin.kt +290 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/BuildConfigConfigurator.kt +69 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/DependencyConfigurator.kt +232 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/DependencyCoordinates.kt +29 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/DevServerResourceConfigurator.kt +101 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/JniPackagingConfigurator.kt +160 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/NdkConfigurator.kt +135 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/RepositoryConfigurator.kt +148 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/ResourceConfigurator.kt +56 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/generators/CMakeGenerator.kt +105 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/generators/CppAutolinkingGenerator.kt +152 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/generators/EntryPointGenerator.kt +100 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/AndroidDependencyConfig.kt +23 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/AutolinkingConfig.kt +89 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/CMakeEntry.kt +47 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/NativeModule.kt +177 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/AssetPackagingTask.kt +194 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/AutolinkingTask.kt +431 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/BundleTask.kt +275 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/CodegenArtifactsTask.kt +218 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/CodegenSchemaTask.kt +186 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/AutolinkingParser.kt +128 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/ConflictDetector.kt +121 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/JdkValidator.kt +73 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/NodeExecutableFinder.kt +43 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/ReactNativeVersionReader.kt +329 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/TaskDependencyValidator.kt +198 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/GraniteExtensionTest.kt +191 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/GranitePluginTest.kt +156 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/GraniteRootProjectPluginTest.kt +87 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/BuildConfigConfiguratorTest.kt +115 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/DependencyConfiguratorTest.kt +338 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/DevServerResourceConfiguratorTest.kt +205 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/ResourceConfiguratorTest.kt +131 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/fixtures/NativeModuleFixtures.kt +67 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/CMakeGeneratorTest.kt +71 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/CppAutolinkingGeneratorTest.kt +344 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/EntryPointGeneratorTest.kt +40 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/models/AutolinkingConfigTest.kt +350 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/models/CMakeEntryTest.kt +200 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/models/NativeModuleTest.kt +562 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/AssetPackagingTaskTest.kt +318 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/AutolinkingTaskTest.kt +89 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/BundleTaskTest.kt +68 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/CodegenTasksTest.kt +410 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/AutolinkingParserTest.kt +335 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/ConflictDetectorTest.kt +75 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/JdkValidatorTest.kt +88 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/ReactNativeVersionReaderTest.kt +585 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/TaskDependencyValidatorTest.kt +123 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/TaskTestUtils.kt +88 -0
- package/gradle-plugin/src/test/resources/fixtures/sample-rn-config.json +45 -0
- package/ios/BundleLoader/BundleEvaluator.h +16 -0
- package/ios/BundleLoader/BundleEvaluator.mm +76 -0
- package/ios/BundleLoader/BundleLoadable.swift +91 -0
- package/ios/GraniteBundleLoaderTypes.swift +7 -0
- package/ios/GraniteScreen.h +12 -0
- package/ios/ReactNativeHosting/DefaultViews.swift +138 -0
- package/ios/ReactNativeHosting/GraniteDefaultModuleProvider.h +24 -0
- package/ios/ReactNativeHosting/GraniteDefaultModuleProvider.mm +22 -0
- package/ios/ReactNativeHosting/GraniteHostingHelper.swift +103 -0
- package/ios/ReactNativeHosting/GraniteNativeFactory.swift +35 -0
- package/ios/ReactNativeHosting/GraniteNativeFactoryDelegateImpl.swift +30 -0
- package/ios/ReactNativeHosting/GraniteNativeFactoryImpl.swift +24 -0
- package/ios/ReactNativeHosting/GraniteReactHost.swift +39 -0
- package/ios/ReactNativeHosting/GraniteScreen-Bridging-Header.h +12 -0
- package/package.json +59 -0
- package/react-native.config.js +8 -0
package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/ReactNativeVersionReaderTest.kt
ADDED
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
package run.granite.gradle.utils
|
|
2
|
+
|
|
3
|
+
import org.junit.jupiter.api.Test
|
|
4
|
+
import org.junit.jupiter.api.assertThrows
|
|
5
|
+
import org.junit.jupiter.api.io.TempDir
|
|
6
|
+
import run.granite.gradle.config.DependencyCoordinates
|
|
7
|
+
import java.io.File
|
|
8
|
+
import kotlin.test.assertEquals
|
|
9
|
+
import kotlin.test.assertTrue
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Unit tests for ReactNativeVersionReader.
|
|
13
|
+
*/
|
|
14
|
+
class ReactNativeVersionReaderTest {
|
|
15
|
+
|
|
16
|
+
@TempDir
|
|
17
|
+
lateinit var tempDir: File
|
|
18
|
+
|
|
19
|
+
@Test
|
|
20
|
+
fun `readVersion reads version from package json`() {
|
|
21
|
+
// Given
|
|
22
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
23
|
+
reactNativeDir.mkdirs()
|
|
24
|
+
|
|
25
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
26
|
+
packageJson.writeText("""{"version":"0.81.6"}""")
|
|
27
|
+
|
|
28
|
+
// When
|
|
29
|
+
val version = ReactNativeVersionReader.readVersion(reactNativeDir)
|
|
30
|
+
|
|
31
|
+
// Then
|
|
32
|
+
assertEquals("0.81.6", version)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@Test
|
|
36
|
+
fun `readVersion handles version with pre-release suffix`() {
|
|
37
|
+
// Given
|
|
38
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
39
|
+
reactNativeDir.mkdirs()
|
|
40
|
+
|
|
41
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
42
|
+
packageJson.writeText("""{"version":"0.82.0-rc.0"}""")
|
|
43
|
+
|
|
44
|
+
// When
|
|
45
|
+
val version = ReactNativeVersionReader.readVersion(reactNativeDir)
|
|
46
|
+
|
|
47
|
+
// Then
|
|
48
|
+
assertEquals("0.82.0-rc.0", version)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Test
|
|
52
|
+
fun `readVersion throws error when package json not found`() {
|
|
53
|
+
// Given
|
|
54
|
+
val reactNativeDir = File(tempDir, "nonexistent")
|
|
55
|
+
|
|
56
|
+
// When/Then
|
|
57
|
+
val exception = assertThrows<IllegalStateException> {
|
|
58
|
+
ReactNativeVersionReader.readVersion(reactNativeDir)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
assertTrue(exception.message?.contains("package.json not found") == true)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@Test
|
|
65
|
+
fun `readVersion throws error when version field missing`() {
|
|
66
|
+
// Given
|
|
67
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
68
|
+
reactNativeDir.mkdirs()
|
|
69
|
+
|
|
70
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
71
|
+
packageJson.writeText("""{"name":"react-native"}""")
|
|
72
|
+
|
|
73
|
+
// When/Then
|
|
74
|
+
val exception = assertThrows<IllegalStateException> {
|
|
75
|
+
ReactNativeVersionReader.readVersion(reactNativeDir)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
assertTrue(exception.message?.contains("version") == true)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@Test
|
|
82
|
+
fun `validateVersion succeeds for supported versions`() {
|
|
83
|
+
// Given
|
|
84
|
+
val supportedVersions = listOf("0.81.0", "0.81.6", "0.82.0", "1.0.0")
|
|
85
|
+
|
|
86
|
+
// When/Then - Should not throw
|
|
87
|
+
for (version in supportedVersions) {
|
|
88
|
+
ReactNativeVersionReader.validateVersion(version)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@Test
|
|
93
|
+
fun `validateVersion fails for unsupported versions`() {
|
|
94
|
+
// Given
|
|
95
|
+
val unsupportedVersions = listOf("0.80.9", "0.70.0", "0.60.0")
|
|
96
|
+
|
|
97
|
+
// When/Then
|
|
98
|
+
for (version in unsupportedVersions) {
|
|
99
|
+
val exception = assertThrows<IllegalStateException> {
|
|
100
|
+
ReactNativeVersionReader.validateVersion(version)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
assertTrue(exception.message?.contains("not supported") == true)
|
|
104
|
+
assertTrue(exception.message?.contains("0.81.0") == true)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Test
|
|
109
|
+
fun `getMinimumVersion returns correct minimum`() {
|
|
110
|
+
// When
|
|
111
|
+
val minVersion = ReactNativeVersionReader.getMinimumVersion()
|
|
112
|
+
|
|
113
|
+
// Then
|
|
114
|
+
assertEquals("0.81.0", minVersion)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@Test
|
|
118
|
+
fun `version comparison handles major version correctly`() {
|
|
119
|
+
// Test that 1.0.0 > 0.81.0
|
|
120
|
+
ReactNativeVersionReader.validateVersion("1.0.0")
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@Test
|
|
124
|
+
fun `version comparison handles minor version correctly`() {
|
|
125
|
+
// Test that 0.82.0 > 0.81.0
|
|
126
|
+
ReactNativeVersionReader.validateVersion("0.82.0")
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@Test
|
|
130
|
+
fun `version comparison handles patch version correctly`() {
|
|
131
|
+
// Test that 0.81.1 > 0.81.0
|
|
132
|
+
ReactNativeVersionReader.validateVersion("0.81.1")
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@Test
|
|
136
|
+
fun `version comparison handles exact minimum version`() {
|
|
137
|
+
// Test that 0.81.0 == 0.81.0
|
|
138
|
+
ReactNativeVersionReader.validateVersion("0.81.0")
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@Test
|
|
142
|
+
fun `readVersion handles malformed JSON gracefully`() {
|
|
143
|
+
// Given
|
|
144
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
145
|
+
reactNativeDir.mkdirs()
|
|
146
|
+
|
|
147
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
148
|
+
packageJson.writeText("""not valid json""")
|
|
149
|
+
|
|
150
|
+
// When/Then
|
|
151
|
+
assertThrows<IllegalStateException> {
|
|
152
|
+
ReactNativeVersionReader.readVersion(reactNativeDir)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@Test
|
|
157
|
+
fun `readVersionAndGroup reads from gradle properties`() {
|
|
158
|
+
// Given
|
|
159
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
160
|
+
reactNativeDir.mkdirs()
|
|
161
|
+
|
|
162
|
+
val reactAndroidDir = File(reactNativeDir, "ReactAndroid")
|
|
163
|
+
reactAndroidDir.mkdirs()
|
|
164
|
+
|
|
165
|
+
val gradleProperties = File(reactAndroidDir, "gradle.properties")
|
|
166
|
+
gradleProperties.writeText(
|
|
167
|
+
"""
|
|
168
|
+
VERSION_NAME=0.81.1
|
|
169
|
+
react.internal.publishingGroup=com.facebook.react
|
|
170
|
+
""".trimIndent(),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
174
|
+
packageJson.writeText("""{"version":"0.81.1"}""")
|
|
175
|
+
|
|
176
|
+
// When
|
|
177
|
+
val (version, group) = ReactNativeVersionReader.readVersionAndGroup(reactNativeDir)
|
|
178
|
+
|
|
179
|
+
// Then
|
|
180
|
+
assertEquals("0.81.1", version)
|
|
181
|
+
assertEquals("com.facebook.react", group)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@Test
|
|
185
|
+
fun `readVersionAndGroup returns default group when publishingGroup is missing`() {
|
|
186
|
+
// Given
|
|
187
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
188
|
+
reactNativeDir.mkdirs()
|
|
189
|
+
|
|
190
|
+
val reactAndroidDir = File(reactNativeDir, "ReactAndroid")
|
|
191
|
+
reactAndroidDir.mkdirs()
|
|
192
|
+
|
|
193
|
+
val gradleProperties = File(reactAndroidDir, "gradle.properties")
|
|
194
|
+
gradleProperties.writeText(
|
|
195
|
+
"""
|
|
196
|
+
VERSION_NAME=0.81.1
|
|
197
|
+
""".trimIndent(),
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
201
|
+
packageJson.writeText("""{"version":"0.81.1"}""")
|
|
202
|
+
|
|
203
|
+
// When
|
|
204
|
+
val (version, group) = ReactNativeVersionReader.readVersionAndGroup(reactNativeDir)
|
|
205
|
+
|
|
206
|
+
// Then
|
|
207
|
+
assertEquals("0.81.1", version)
|
|
208
|
+
assertEquals("com.facebook.react", group)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
@Test
|
|
212
|
+
fun `readVersionAndGroup handles custom publishingGroup`() {
|
|
213
|
+
// Given
|
|
214
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
215
|
+
reactNativeDir.mkdirs()
|
|
216
|
+
|
|
217
|
+
val reactAndroidDir = File(reactNativeDir, "ReactAndroid")
|
|
218
|
+
reactAndroidDir.mkdirs()
|
|
219
|
+
|
|
220
|
+
val gradleProperties = File(reactAndroidDir, "gradle.properties")
|
|
221
|
+
gradleProperties.writeText(
|
|
222
|
+
"""
|
|
223
|
+
VERSION_NAME=0.81.1-nightly-20250123
|
|
224
|
+
react.internal.publishingGroup=com.custom.react
|
|
225
|
+
""".trimIndent(),
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
229
|
+
packageJson.writeText("""{"version":"0.81.1-nightly-20250123"}""")
|
|
230
|
+
|
|
231
|
+
// When
|
|
232
|
+
val (version, group) = ReactNativeVersionReader.readVersionAndGroup(reactNativeDir)
|
|
233
|
+
|
|
234
|
+
// Then
|
|
235
|
+
assertEquals("0.81.1-nightly-20250123-SNAPSHOT", version)
|
|
236
|
+
assertEquals("com.custom.react", group)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
@Test
|
|
240
|
+
fun `readVersionAndGroup adds SNAPSHOT suffix for nightly versions starting with 0_0_0`() {
|
|
241
|
+
// Given
|
|
242
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
243
|
+
reactNativeDir.mkdirs()
|
|
244
|
+
|
|
245
|
+
val reactAndroidDir = File(reactNativeDir, "ReactAndroid")
|
|
246
|
+
reactAndroidDir.mkdirs()
|
|
247
|
+
|
|
248
|
+
val gradleProperties = File(reactAndroidDir, "gradle.properties")
|
|
249
|
+
gradleProperties.writeText(
|
|
250
|
+
"""
|
|
251
|
+
VERSION_NAME=0.0.0-20250123-1234-abc123
|
|
252
|
+
react.internal.publishingGroup=com.facebook.react
|
|
253
|
+
""".trimIndent(),
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
257
|
+
packageJson.writeText("""{"version":"0.0.0-20250123-1234-abc123"}""")
|
|
258
|
+
|
|
259
|
+
// When
|
|
260
|
+
val (version, _) = ReactNativeVersionReader.readVersionAndGroup(reactNativeDir)
|
|
261
|
+
|
|
262
|
+
// Then
|
|
263
|
+
assertEquals("0.0.0-20250123-1234-abc123-SNAPSHOT", version)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@Test
|
|
267
|
+
fun `readVersionAndGroup adds SNAPSHOT suffix for nightly versions containing nightly`() {
|
|
268
|
+
// Given
|
|
269
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
270
|
+
reactNativeDir.mkdirs()
|
|
271
|
+
|
|
272
|
+
val reactAndroidDir = File(reactNativeDir, "ReactAndroid")
|
|
273
|
+
reactAndroidDir.mkdirs()
|
|
274
|
+
|
|
275
|
+
val gradleProperties = File(reactAndroidDir, "gradle.properties")
|
|
276
|
+
gradleProperties.writeText(
|
|
277
|
+
"""
|
|
278
|
+
VERSION_NAME=0.81.0-nightly-20250123-abc123
|
|
279
|
+
react.internal.publishingGroup=com.facebook.react
|
|
280
|
+
""".trimIndent(),
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
284
|
+
packageJson.writeText("""{"version":"0.81.0-nightly-20250123-abc123"}""")
|
|
285
|
+
|
|
286
|
+
// When
|
|
287
|
+
val (version, _) = ReactNativeVersionReader.readVersionAndGroup(reactNativeDir)
|
|
288
|
+
|
|
289
|
+
// Then
|
|
290
|
+
assertEquals("0.81.0-nightly-20250123-abc123-SNAPSHOT", version)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
@Test
|
|
294
|
+
fun `readVersionAndGroup does NOT add SNAPSHOT for stable releases`() {
|
|
295
|
+
// Given
|
|
296
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
297
|
+
reactNativeDir.mkdirs()
|
|
298
|
+
|
|
299
|
+
val reactAndroidDir = File(reactNativeDir, "ReactAndroid")
|
|
300
|
+
reactAndroidDir.mkdirs()
|
|
301
|
+
|
|
302
|
+
val gradleProperties = File(reactAndroidDir, "gradle.properties")
|
|
303
|
+
gradleProperties.writeText(
|
|
304
|
+
"""
|
|
305
|
+
VERSION_NAME=0.81.6
|
|
306
|
+
react.internal.publishingGroup=com.facebook.react
|
|
307
|
+
""".trimIndent(),
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
311
|
+
packageJson.writeText("""{"version":"0.81.6"}""")
|
|
312
|
+
|
|
313
|
+
// When
|
|
314
|
+
val (version, _) = ReactNativeVersionReader.readVersionAndGroup(reactNativeDir)
|
|
315
|
+
|
|
316
|
+
// Then
|
|
317
|
+
assertEquals("0.81.6", version)
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
@Test
|
|
321
|
+
fun `readVersionAndGroup does NOT add SNAPSHOT for rc versions`() {
|
|
322
|
+
// Given
|
|
323
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
324
|
+
reactNativeDir.mkdirs()
|
|
325
|
+
|
|
326
|
+
val reactAndroidDir = File(reactNativeDir, "ReactAndroid")
|
|
327
|
+
reactAndroidDir.mkdirs()
|
|
328
|
+
|
|
329
|
+
val gradleProperties = File(reactAndroidDir, "gradle.properties")
|
|
330
|
+
gradleProperties.writeText(
|
|
331
|
+
"""
|
|
332
|
+
VERSION_NAME=0.82.0-rc.0
|
|
333
|
+
react.internal.publishingGroup=com.facebook.react
|
|
334
|
+
""".trimIndent(),
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
338
|
+
packageJson.writeText("""{"version":"0.82.0-rc.0"}""")
|
|
339
|
+
|
|
340
|
+
// When
|
|
341
|
+
val (version, _) = ReactNativeVersionReader.readVersionAndGroup(reactNativeDir)
|
|
342
|
+
|
|
343
|
+
// Then
|
|
344
|
+
assertEquals("0.82.0-rc.0", version)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
@Test
|
|
348
|
+
fun `readVersionAndGroup falls back to package json when gradle properties missing`() {
|
|
349
|
+
// Given
|
|
350
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
351
|
+
reactNativeDir.mkdirs()
|
|
352
|
+
// No ReactAndroid/gradle.properties - fallback to package.json
|
|
353
|
+
|
|
354
|
+
val packageJson = File(reactNativeDir, "package.json")
|
|
355
|
+
packageJson.writeText("""{"version":"0.81.6"}""")
|
|
356
|
+
|
|
357
|
+
// When
|
|
358
|
+
val (version, group) = ReactNativeVersionReader.readVersionAndGroup(reactNativeDir)
|
|
359
|
+
|
|
360
|
+
// Then
|
|
361
|
+
assertEquals("0.81.6", version)
|
|
362
|
+
assertEquals("com.facebook.react", group)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
@Test
|
|
366
|
+
fun `readVersionAndGroup throws error when VERSION_NAME empty and no package json`() {
|
|
367
|
+
// Given
|
|
368
|
+
val reactNativeDir = File(tempDir, "react-native")
|
|
369
|
+
reactNativeDir.mkdirs()
|
|
370
|
+
|
|
371
|
+
val reactAndroidDir = File(reactNativeDir, "ReactAndroid")
|
|
372
|
+
reactAndroidDir.mkdirs()
|
|
373
|
+
|
|
374
|
+
val gradleProperties = File(reactAndroidDir, "gradle.properties")
|
|
375
|
+
gradleProperties.writeText(
|
|
376
|
+
"""
|
|
377
|
+
react.internal.publishingGroup=com.custom.react
|
|
378
|
+
""".trimIndent(),
|
|
379
|
+
)
|
|
380
|
+
// No VERSION_NAME - error expected
|
|
381
|
+
|
|
382
|
+
// When/Then
|
|
383
|
+
val exception = assertThrows<IllegalStateException> {
|
|
384
|
+
ReactNativeVersionReader.readVersionAndGroup(reactNativeDir)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
assertTrue(exception.message?.contains("VERSION_NAME") == true)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// === readCoordinates tests ===
|
|
391
|
+
|
|
392
|
+
@Test
|
|
393
|
+
fun `readCoordinates reads all version info from both files`() {
|
|
394
|
+
// Given
|
|
395
|
+
val reactNativeDir = setupReactNativeDirForCoordinates(
|
|
396
|
+
gradleProperties = """
|
|
397
|
+
VERSION_NAME=0.84.0-rc.4
|
|
398
|
+
react.internal.publishingGroup=com.facebook.react
|
|
399
|
+
react.internal.hermesPublishingGroup=com.facebook.hermes
|
|
400
|
+
""".trimIndent(),
|
|
401
|
+
hermesVersionProperties = """
|
|
402
|
+
HERMES_VERSION_NAME=0.15.0
|
|
403
|
+
HERMES_V1_VERSION_NAME=250829098.0.6
|
|
404
|
+
""".trimIndent(),
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
// When
|
|
408
|
+
val coordinates = ReactNativeVersionReader.readCoordinates(reactNativeDir)
|
|
409
|
+
|
|
410
|
+
// Then
|
|
411
|
+
assertEquals("0.84.0-rc.4", coordinates.reactVersion)
|
|
412
|
+
assertEquals("0.15.0", coordinates.hermesVersion)
|
|
413
|
+
assertEquals("250829098.0.6", coordinates.hermesV1Version)
|
|
414
|
+
assertEquals("com.facebook.react", coordinates.reactGroup)
|
|
415
|
+
assertEquals("com.facebook.hermes", coordinates.hermesGroup)
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@Test
|
|
419
|
+
fun `readCoordinates uses default hermes group when not specified`() {
|
|
420
|
+
// Given
|
|
421
|
+
val reactNativeDir = setupReactNativeDirForCoordinates(
|
|
422
|
+
gradleProperties = """
|
|
423
|
+
VERSION_NAME=0.84.0
|
|
424
|
+
react.internal.publishingGroup=com.facebook.react
|
|
425
|
+
""".trimIndent(),
|
|
426
|
+
hermesVersionProperties = """
|
|
427
|
+
HERMES_VERSION_NAME=0.15.0
|
|
428
|
+
HERMES_V1_VERSION_NAME=250829098.0.6
|
|
429
|
+
""".trimIndent(),
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
// When
|
|
433
|
+
val coordinates = ReactNativeVersionReader.readCoordinates(reactNativeDir)
|
|
434
|
+
|
|
435
|
+
// Then
|
|
436
|
+
assertEquals("com.facebook.hermes", coordinates.hermesGroup)
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
@Test
|
|
440
|
+
fun `readCoordinates falls back to RN version when hermes version file missing`() {
|
|
441
|
+
// Given - RN 0.83 or lower scenario
|
|
442
|
+
val reactNativeDir = setupReactNativeDirForCoordinates(
|
|
443
|
+
gradleProperties = """
|
|
444
|
+
VERSION_NAME=0.83.0
|
|
445
|
+
react.internal.publishingGroup=com.facebook.react
|
|
446
|
+
""".trimIndent(),
|
|
447
|
+
hermesVersionProperties = null, // File doesn't exist
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
// When
|
|
451
|
+
val coordinates = ReactNativeVersionReader.readCoordinates(reactNativeDir)
|
|
452
|
+
|
|
453
|
+
// Then
|
|
454
|
+
assertEquals("0.83.0", coordinates.reactVersion)
|
|
455
|
+
assertEquals("0.83.0", coordinates.hermesVersion)
|
|
456
|
+
assertEquals("0.83.0", coordinates.hermesV1Version)
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
@Test
|
|
460
|
+
fun `readCoordinates handles nightly hermes version with SNAPSHOT suffix`() {
|
|
461
|
+
// Given
|
|
462
|
+
val reactNativeDir = setupReactNativeDirForCoordinates(
|
|
463
|
+
gradleProperties = """
|
|
464
|
+
VERSION_NAME=0.84.0
|
|
465
|
+
""".trimIndent(),
|
|
466
|
+
hermesVersionProperties = """
|
|
467
|
+
HERMES_VERSION_NAME=0.0.0-commitly-20250123-abc123
|
|
468
|
+
HERMES_V1_VERSION_NAME=250829098.0.0
|
|
469
|
+
""".trimIndent(),
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
// When
|
|
473
|
+
val coordinates = ReactNativeVersionReader.readCoordinates(reactNativeDir)
|
|
474
|
+
|
|
475
|
+
// Then
|
|
476
|
+
assertEquals("0.0.0-commitly-20250123-abc123-SNAPSHOT", coordinates.hermesVersion)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
@Test
|
|
480
|
+
fun `readCoordinates returns V1 version from getEffectiveHermesVersion`() {
|
|
481
|
+
// Given
|
|
482
|
+
val reactNativeDir = setupReactNativeDirForCoordinates(
|
|
483
|
+
gradleProperties = """
|
|
484
|
+
VERSION_NAME=0.84.0
|
|
485
|
+
""".trimIndent(),
|
|
486
|
+
hermesVersionProperties = """
|
|
487
|
+
HERMES_VERSION_NAME=0.15.0
|
|
488
|
+
HERMES_V1_VERSION_NAME=250829098.0.6
|
|
489
|
+
""".trimIndent(),
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
// When
|
|
493
|
+
val coordinates = ReactNativeVersionReader.readCoordinates(reactNativeDir)
|
|
494
|
+
|
|
495
|
+
// Then
|
|
496
|
+
assertEquals("250829098.0.6", coordinates.getEffectiveHermesVersion())
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
@Test
|
|
500
|
+
fun `readCoordinates returns classic version when V1 empty`() {
|
|
501
|
+
// Given
|
|
502
|
+
val reactNativeDir = setupReactNativeDirForCoordinates(
|
|
503
|
+
gradleProperties = """
|
|
504
|
+
VERSION_NAME=0.84.0
|
|
505
|
+
""".trimIndent(),
|
|
506
|
+
hermesVersionProperties = """
|
|
507
|
+
HERMES_VERSION_NAME=0.15.0
|
|
508
|
+
HERMES_V1_VERSION_NAME=
|
|
509
|
+
""".trimIndent(),
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
// When
|
|
513
|
+
val coordinates = ReactNativeVersionReader.readCoordinates(reactNativeDir)
|
|
514
|
+
|
|
515
|
+
// Then
|
|
516
|
+
assertEquals("0.15.0", coordinates.getEffectiveHermesVersion())
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
@Test
|
|
520
|
+
fun `readCoordinates handles empty hermes version file gracefully`() {
|
|
521
|
+
// Given - Hermes version file exists but is empty
|
|
522
|
+
val reactNativeDir = setupReactNativeDirForCoordinates(
|
|
523
|
+
gradleProperties = """
|
|
524
|
+
VERSION_NAME=0.84.0
|
|
525
|
+
""".trimIndent(),
|
|
526
|
+
hermesVersionProperties = "", // Empty file
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
// When
|
|
530
|
+
val coordinates = ReactNativeVersionReader.readCoordinates(reactNativeDir)
|
|
531
|
+
|
|
532
|
+
// Then - Fallback to RN version
|
|
533
|
+
assertEquals("0.84.0", coordinates.hermesVersion)
|
|
534
|
+
assertEquals("0.84.0", coordinates.hermesV1Version)
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
@Test
|
|
538
|
+
fun `readCoordinates handles malformed hermes version file gracefully`() {
|
|
539
|
+
// Given - Hermes version file has invalid format
|
|
540
|
+
val reactNativeDir = setupReactNativeDirForCoordinates(
|
|
541
|
+
gradleProperties = """
|
|
542
|
+
VERSION_NAME=0.84.0
|
|
543
|
+
""".trimIndent(),
|
|
544
|
+
hermesVersionProperties = """
|
|
545
|
+
INVALID_KEY=some_value
|
|
546
|
+
ANOTHER_INVALID=123
|
|
547
|
+
""".trimIndent(),
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
// When
|
|
551
|
+
val coordinates = ReactNativeVersionReader.readCoordinates(reactNativeDir)
|
|
552
|
+
|
|
553
|
+
// Then - Fallback to RN version
|
|
554
|
+
assertEquals("0.84.0", coordinates.hermesVersion)
|
|
555
|
+
assertEquals("0.84.0", coordinates.hermesV1Version)
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// === Helper for readCoordinates tests ===
|
|
559
|
+
|
|
560
|
+
private fun setupReactNativeDirForCoordinates(
|
|
561
|
+
gradleProperties: String,
|
|
562
|
+
hermesVersionProperties: String?,
|
|
563
|
+
packageJsonVersion: String = "0.84.0",
|
|
564
|
+
): File {
|
|
565
|
+
val reactNativeDir = File(tempDir, "rn-coords-${System.nanoTime()}")
|
|
566
|
+
reactNativeDir.mkdirs()
|
|
567
|
+
|
|
568
|
+
// package.json (for fallback)
|
|
569
|
+
File(reactNativeDir, "package.json").writeText("""{"version":"$packageJsonVersion"}""")
|
|
570
|
+
|
|
571
|
+
// ReactAndroid/gradle.properties
|
|
572
|
+
val reactAndroidDir = File(reactNativeDir, "ReactAndroid")
|
|
573
|
+
reactAndroidDir.mkdirs()
|
|
574
|
+
File(reactAndroidDir, "gradle.properties").writeText(gradleProperties)
|
|
575
|
+
|
|
576
|
+
// sdks/hermes-engine/version.properties
|
|
577
|
+
if (hermesVersionProperties != null) {
|
|
578
|
+
val hermesDir = File(reactNativeDir, "sdks/hermes-engine")
|
|
579
|
+
hermesDir.mkdirs()
|
|
580
|
+
File(hermesDir, "version.properties").writeText(hermesVersionProperties)
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
return reactNativeDir
|
|
584
|
+
}
|
|
585
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
package run.granite.gradle.utils
|
|
2
|
+
|
|
3
|
+
import org.gradle.api.DefaultTask
|
|
4
|
+
import org.gradle.testfixtures.ProjectBuilder
|
|
5
|
+
import org.junit.jupiter.api.BeforeEach
|
|
6
|
+
import org.junit.jupiter.api.Test
|
|
7
|
+
import kotlin.test.assertEquals
|
|
8
|
+
import kotlin.test.assertTrue
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Unit tests for TaskDependencyValidator.
|
|
12
|
+
*/
|
|
13
|
+
class TaskDependencyValidatorTest {
|
|
14
|
+
|
|
15
|
+
private lateinit var project: org.gradle.api.Project
|
|
16
|
+
|
|
17
|
+
@BeforeEach
|
|
18
|
+
fun setup() {
|
|
19
|
+
project = ProjectBuilder.builder().build()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@Test
|
|
23
|
+
fun `validateRequiredTasks returns empty list when all tasks exist`() {
|
|
24
|
+
// Given
|
|
25
|
+
project.tasks.register("task1", DefaultTask::class.java)
|
|
26
|
+
project.tasks.register("task2", DefaultTask::class.java)
|
|
27
|
+
|
|
28
|
+
val requiredTasks = listOf("task1", "task2")
|
|
29
|
+
|
|
30
|
+
// When
|
|
31
|
+
val missingTasks = TaskDependencyValidator.validateRequiredTasks(project, requiredTasks)
|
|
32
|
+
|
|
33
|
+
// Then
|
|
34
|
+
assertTrue(missingTasks.isEmpty())
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@Test
|
|
38
|
+
fun `validateRequiredTasks returns missing task names`() {
|
|
39
|
+
// Given
|
|
40
|
+
project.tasks.register("task1", DefaultTask::class.java)
|
|
41
|
+
// task2 not registered
|
|
42
|
+
|
|
43
|
+
val requiredTasks = listOf("task1", "task2", "task3")
|
|
44
|
+
|
|
45
|
+
// When
|
|
46
|
+
val missingTasks = TaskDependencyValidator.validateRequiredTasks(project, requiredTasks)
|
|
47
|
+
|
|
48
|
+
// Then
|
|
49
|
+
assertEquals(2, missingTasks.size)
|
|
50
|
+
assertTrue(missingTasks.contains("task2"))
|
|
51
|
+
assertTrue(missingTasks.contains("task3"))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@Test
|
|
55
|
+
fun `validateRequiredTasks handles empty required tasks list`() {
|
|
56
|
+
// Given
|
|
57
|
+
val requiredTasks = emptyList<String>()
|
|
58
|
+
|
|
59
|
+
// When
|
|
60
|
+
val missingTasks = TaskDependencyValidator.validateRequiredTasks(project, requiredTasks)
|
|
61
|
+
|
|
62
|
+
// Then
|
|
63
|
+
assertTrue(missingTasks.isEmpty())
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@Test
|
|
67
|
+
fun `validateTaskInputsOutputs warns for tasks without inputs or outputs`() {
|
|
68
|
+
// Given
|
|
69
|
+
val task = project.tasks.register("testTask", DefaultTask::class.java).get()
|
|
70
|
+
|
|
71
|
+
// When/Then - Should not throw, just log warning
|
|
72
|
+
TaskDependencyValidator.validateTaskInputsOutputs(project, task)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@Test
|
|
76
|
+
fun `validateAutolinkingBeforeCodegen validates task dependency`() {
|
|
77
|
+
// Given
|
|
78
|
+
val autolinkingTask = project.tasks.register("autolinking", DefaultTask::class.java).get()
|
|
79
|
+
val codegenTask = project.tasks.register("codegen", DefaultTask::class.java).get()
|
|
80
|
+
|
|
81
|
+
// When/Then - Should not throw
|
|
82
|
+
TaskDependencyValidator.validateAutolinkingBeforeCodegen(project, autolinkingTask, codegenTask)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@Test
|
|
86
|
+
fun `validateCodegenBeforeCompilation validates task dependency`() {
|
|
87
|
+
// Given
|
|
88
|
+
val codegenTask = project.tasks.register("codegen", DefaultTask::class.java).get()
|
|
89
|
+
val compileTask = project.tasks.register("compile", DefaultTask::class.java).get()
|
|
90
|
+
|
|
91
|
+
// When/Then - Should not throw
|
|
92
|
+
TaskDependencyValidator.validateCodegenBeforeCompilation(project, codegenTask, compileTask)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@Test
|
|
96
|
+
fun `validateBundleBeforePackaging validates task dependency`() {
|
|
97
|
+
// Given
|
|
98
|
+
val bundleTask = project.tasks.register("bundle", DefaultTask::class.java).get()
|
|
99
|
+
val packageTask = project.tasks.register("package", DefaultTask::class.java).get()
|
|
100
|
+
|
|
101
|
+
// When/Then - Should not throw
|
|
102
|
+
TaskDependencyValidator.validateBundleBeforePackaging(project, bundleTask, packageTask)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@Test
|
|
106
|
+
fun `validateInfrastructureBeforeVariant validates task dependency`() {
|
|
107
|
+
// Given
|
|
108
|
+
val infrastructureTask = project.tasks.register("infrastructure", DefaultTask::class.java).get()
|
|
109
|
+
val variantTask = project.tasks.register("variant", DefaultTask::class.java).get()
|
|
110
|
+
|
|
111
|
+
// When/Then - Should not throw
|
|
112
|
+
TaskDependencyValidator.validateInfrastructureBeforeVariant(project, infrastructureTask, variantTask)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@Test
|
|
116
|
+
fun `logTaskDependencies logs task information`() {
|
|
117
|
+
// Given
|
|
118
|
+
val task = project.tasks.register("testTask", DefaultTask::class.java).get()
|
|
119
|
+
|
|
120
|
+
// When/Then - Should not throw
|
|
121
|
+
TaskDependencyValidator.logTaskDependencies(project, task)
|
|
122
|
+
}
|
|
123
|
+
}
|