@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
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
package run.granite.gradle.utils
|
|
2
|
+
|
|
3
|
+
import org.assertj.core.api.Assertions.assertThat
|
|
4
|
+
import org.assertj.core.api.Assertions.assertThatThrownBy
|
|
5
|
+
import org.junit.jupiter.api.Test
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Unit tests for AutolinkingParser core parsing logic.
|
|
9
|
+
* Tests JSON parsing and error handling.
|
|
10
|
+
*/
|
|
11
|
+
class AutolinkingParserTest {
|
|
12
|
+
|
|
13
|
+
@Test
|
|
14
|
+
fun `parse valid JSON with complete configuration`() {
|
|
15
|
+
val json = """
|
|
16
|
+
{
|
|
17
|
+
"project": {
|
|
18
|
+
"name": "test-project",
|
|
19
|
+
"version": "1.0.0",
|
|
20
|
+
"android": {
|
|
21
|
+
"sourceDir": "android",
|
|
22
|
+
"manifestPath": "android/AndroidManifest.xml",
|
|
23
|
+
"packageName": "com.example.test"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"react-native-webview": {
|
|
28
|
+
"name": "react-native-webview",
|
|
29
|
+
"root": "/path/to/module",
|
|
30
|
+
"platforms": {
|
|
31
|
+
"android": {
|
|
32
|
+
"sourceDir": "android",
|
|
33
|
+
"packageImportPath": "com.example.Package",
|
|
34
|
+
"packageInstance": "new Package()",
|
|
35
|
+
"libraryName": "RNCWebView",
|
|
36
|
+
"componentDescriptors": ["Component1"],
|
|
37
|
+
"cmakeListsPath": "android/CMakeLists.txt"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
""".trimIndent()
|
|
44
|
+
|
|
45
|
+
val config = AutolinkingParser.parse(json)
|
|
46
|
+
|
|
47
|
+
// Verify project info
|
|
48
|
+
assertThat(config.project.name).isEqualTo("test-project")
|
|
49
|
+
assertThat(config.project.version).isEqualTo("1.0.0")
|
|
50
|
+
assertThat(config.project.android).isNotNull
|
|
51
|
+
assertThat(config.project.android?.packageName).isEqualTo("com.example.test")
|
|
52
|
+
|
|
53
|
+
// Verify dependencies
|
|
54
|
+
assertThat(config.dependencies).hasSize(1)
|
|
55
|
+
assertThat(config.dependencies).containsKey("react-native-webview")
|
|
56
|
+
|
|
57
|
+
// Verify Android dependency config
|
|
58
|
+
val androidModules = config.androidDependencies()
|
|
59
|
+
assertThat(androidModules).hasSize(1)
|
|
60
|
+
assertThat(androidModules[0].name).isEqualTo("react-native-webview")
|
|
61
|
+
assertThat(androidModules[0].packageImportPath).isEqualTo("com.example.Package")
|
|
62
|
+
assertThat(androidModules[0].libraryName).isEqualTo("RNCWebView")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@Test
|
|
66
|
+
fun `parse JSON with null fields treats them as absent`() {
|
|
67
|
+
// Null and missing fields treated identically
|
|
68
|
+
val json = """
|
|
69
|
+
{
|
|
70
|
+
"project": {
|
|
71
|
+
"name": "test-project",
|
|
72
|
+
"version": null,
|
|
73
|
+
"android": {
|
|
74
|
+
"sourceDir": "android",
|
|
75
|
+
"manifestPath": null,
|
|
76
|
+
"packageName": "com.example.test"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"dependencies": {
|
|
80
|
+
"test-module": {
|
|
81
|
+
"name": "test-module",
|
|
82
|
+
"root": "/path",
|
|
83
|
+
"platforms": {
|
|
84
|
+
"android": {
|
|
85
|
+
"sourceDir": "android",
|
|
86
|
+
"packageImportPath": null,
|
|
87
|
+
"packageInstance": null,
|
|
88
|
+
"libraryName": "testlib",
|
|
89
|
+
"componentDescriptors": null
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
""".trimIndent()
|
|
96
|
+
|
|
97
|
+
val config = AutolinkingParser.parse(json)
|
|
98
|
+
|
|
99
|
+
assertThat(config.project.version).isNull()
|
|
100
|
+
assertThat(config.project.android?.manifestPath).isNull()
|
|
101
|
+
|
|
102
|
+
val modules = config.androidDependencies()
|
|
103
|
+
assertThat(modules[0].packageImportPath).isNull()
|
|
104
|
+
assertThat(modules[0].packageInstance).isNull()
|
|
105
|
+
assertThat(modules[0].componentDescriptors).isEmpty()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Test
|
|
109
|
+
fun `parse JSON with missing dependencies field returns empty dependencies`() {
|
|
110
|
+
val json = """
|
|
111
|
+
{
|
|
112
|
+
"project": {
|
|
113
|
+
"name": "test-project"
|
|
114
|
+
},
|
|
115
|
+
"dependencies": {}
|
|
116
|
+
}
|
|
117
|
+
""".trimIndent()
|
|
118
|
+
|
|
119
|
+
val config = AutolinkingParser.parse(json)
|
|
120
|
+
|
|
121
|
+
assertThat(config.dependencies).isEmpty()
|
|
122
|
+
assertThat(config.androidDependencies()).isEmpty()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@Test
|
|
126
|
+
fun `parse JSON with JavaScript-only modules excludes them from androidDependencies`() {
|
|
127
|
+
val json = """
|
|
128
|
+
{
|
|
129
|
+
"project": {
|
|
130
|
+
"name": "test-project"
|
|
131
|
+
},
|
|
132
|
+
"dependencies": {
|
|
133
|
+
"js-only-module": {
|
|
134
|
+
"name": "js-only-module",
|
|
135
|
+
"root": "/path",
|
|
136
|
+
"platforms": {}
|
|
137
|
+
},
|
|
138
|
+
"ios-only-module": {
|
|
139
|
+
"name": "ios-only-module",
|
|
140
|
+
"root": "/path",
|
|
141
|
+
"platforms": {
|
|
142
|
+
"ios": {
|
|
143
|
+
"sourceDir": "ios"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
""".trimIndent()
|
|
150
|
+
|
|
151
|
+
val config = AutolinkingParser.parse(json)
|
|
152
|
+
|
|
153
|
+
assertThat(config.dependencies).hasSize(2)
|
|
154
|
+
assertThat(config.androidDependencies()).isEmpty() // No Android modules
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@Test
|
|
158
|
+
fun `throws IllegalArgumentException when JSON is malformed`() {
|
|
159
|
+
// Fail-fast with descriptive error
|
|
160
|
+
val malformedJson = "{ invalid json "
|
|
161
|
+
|
|
162
|
+
assertThatThrownBy {
|
|
163
|
+
AutolinkingParser.parse(malformedJson)
|
|
164
|
+
}
|
|
165
|
+
.isInstanceOf(IllegalArgumentException::class.java)
|
|
166
|
+
.hasMessageContaining("react-native config")
|
|
167
|
+
.hasMessageContaining("Failed to parse JSON")
|
|
168
|
+
.hasMessageContaining("syntax error")
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@Test
|
|
172
|
+
fun `throws IllegalArgumentException when project field missing`() {
|
|
173
|
+
// Fail-fast with descriptive error
|
|
174
|
+
val json = """
|
|
175
|
+
{
|
|
176
|
+
"dependencies": {}
|
|
177
|
+
}
|
|
178
|
+
""".trimIndent()
|
|
179
|
+
|
|
180
|
+
assertThatThrownBy {
|
|
181
|
+
AutolinkingParser.parse(json)
|
|
182
|
+
}
|
|
183
|
+
.isInstanceOf(IllegalArgumentException::class.java)
|
|
184
|
+
.hasMessageContaining("react-native config")
|
|
185
|
+
.hasMessageContaining("missing 'project' field")
|
|
186
|
+
.hasMessageContaining("Ensure react-native CLI is properly configured")
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@Test
|
|
190
|
+
fun `throws IllegalArgumentException when JSON has unexpected structure`() {
|
|
191
|
+
// Fail-fast with descriptive error
|
|
192
|
+
val json = """
|
|
193
|
+
{
|
|
194
|
+
"project": "invalid-should-be-object",
|
|
195
|
+
"dependencies": {}
|
|
196
|
+
}
|
|
197
|
+
""".trimIndent()
|
|
198
|
+
|
|
199
|
+
assertThatThrownBy {
|
|
200
|
+
AutolinkingParser.parse(json)
|
|
201
|
+
}
|
|
202
|
+
.isInstanceOf(IllegalArgumentException::class.java)
|
|
203
|
+
.hasMessageContaining("react-native config")
|
|
204
|
+
// ClassCastException wrapped in IllegalArgumentException
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@Test
|
|
208
|
+
fun `parse handles empty project android field`() {
|
|
209
|
+
val json = """
|
|
210
|
+
{
|
|
211
|
+
"project": {
|
|
212
|
+
"name": "test-project",
|
|
213
|
+
"android": null
|
|
214
|
+
},
|
|
215
|
+
"dependencies": {}
|
|
216
|
+
}
|
|
217
|
+
""".trimIndent()
|
|
218
|
+
|
|
219
|
+
val config = AutolinkingParser.parse(json)
|
|
220
|
+
|
|
221
|
+
assertThat(config.project.android).isNull()
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@Test
|
|
225
|
+
fun `parse handles all AndroidDependencyConfig fields`() {
|
|
226
|
+
val json = """
|
|
227
|
+
{
|
|
228
|
+
"project": {
|
|
229
|
+
"name": "test-project"
|
|
230
|
+
},
|
|
231
|
+
"dependencies": {
|
|
232
|
+
"complex-module": {
|
|
233
|
+
"name": "complex-module",
|
|
234
|
+
"root": "/path",
|
|
235
|
+
"platforms": {
|
|
236
|
+
"android": {
|
|
237
|
+
"sourceDir": "android",
|
|
238
|
+
"packageImportPath": "com.example.Package",
|
|
239
|
+
"packageInstance": "new Package()",
|
|
240
|
+
"buildTypes": ["debug", "release"],
|
|
241
|
+
"libraryName": "ComplexModule",
|
|
242
|
+
"componentDescriptors": ["Comp1", "Comp2"],
|
|
243
|
+
"cmakeListsPath": "android/CMakeLists.txt",
|
|
244
|
+
"cxxModuleCMakeListsPath": "android/cxx/CMakeLists.txt",
|
|
245
|
+
"cxxModuleCMakeListsModuleName": "complex_cxx",
|
|
246
|
+
"cxxModuleHeaderName": "ComplexModule",
|
|
247
|
+
"isPureCxxDependency": false
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
""".trimIndent()
|
|
254
|
+
|
|
255
|
+
val config = AutolinkingParser.parse(json)
|
|
256
|
+
val modules = config.androidDependencies()
|
|
257
|
+
|
|
258
|
+
assertThat(modules).hasSize(1)
|
|
259
|
+
val module = modules[0]
|
|
260
|
+
|
|
261
|
+
assertThat(module.packageImportPath).isEqualTo("com.example.Package")
|
|
262
|
+
assertThat(module.packageInstance).isEqualTo("new Package()")
|
|
263
|
+
assertThat(module.libraryName).isEqualTo("ComplexModule")
|
|
264
|
+
assertThat(module.componentDescriptors).containsExactly("Comp1", "Comp2")
|
|
265
|
+
assertThat(module.cmakeListsPath).isEqualTo("android/CMakeLists.txt")
|
|
266
|
+
assertThat(module.cxxModuleCMakeListsPath).isEqualTo("android/cxx/CMakeLists.txt")
|
|
267
|
+
assertThat(module.cxxModuleHeaderName).isEqualTo("ComplexModule")
|
|
268
|
+
assertThat(module.isPureCxxDependency).isFalse
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@Test
|
|
272
|
+
fun `parse handles module with multiple dependencies`() {
|
|
273
|
+
val json = """
|
|
274
|
+
{
|
|
275
|
+
"project": {
|
|
276
|
+
"name": "test-project"
|
|
277
|
+
},
|
|
278
|
+
"dependencies": {
|
|
279
|
+
"module1": {
|
|
280
|
+
"name": "module1",
|
|
281
|
+
"root": "/path1",
|
|
282
|
+
"platforms": {
|
|
283
|
+
"android": {
|
|
284
|
+
"sourceDir": "android",
|
|
285
|
+
"libraryName": "Module1"
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
"module2": {
|
|
290
|
+
"name": "module2",
|
|
291
|
+
"root": "/path2",
|
|
292
|
+
"platforms": {
|
|
293
|
+
"android": {
|
|
294
|
+
"sourceDir": "android",
|
|
295
|
+
"libraryName": "Module2"
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
"module3": {
|
|
300
|
+
"name": "module3",
|
|
301
|
+
"root": "/path3",
|
|
302
|
+
"platforms": {
|
|
303
|
+
"android": {
|
|
304
|
+
"sourceDir": "android",
|
|
305
|
+
"libraryName": "Module3"
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
""".trimIndent()
|
|
312
|
+
|
|
313
|
+
val config = AutolinkingParser.parse(json)
|
|
314
|
+
|
|
315
|
+
assertThat(config.dependencies).hasSize(3)
|
|
316
|
+
assertThat(config.androidDependencies()).hasSize(3)
|
|
317
|
+
assertThat(config.androidDependencies().map { it.name })
|
|
318
|
+
.containsExactlyInAnyOrder("module1", "module2", "module3")
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
@Test
|
|
322
|
+
fun `parse loads fixture JSON file successfully`() {
|
|
323
|
+
val fixtureJson = javaClass.classLoader
|
|
324
|
+
.getResourceAsStream("fixtures/sample-rn-config.json")!!
|
|
325
|
+
.bufferedReader()
|
|
326
|
+
.use { it.readText() }
|
|
327
|
+
|
|
328
|
+
val config = AutolinkingParser.parse(fixtureJson)
|
|
329
|
+
|
|
330
|
+
assertThat(config.project.name).isEqualTo("test-project")
|
|
331
|
+
assertThat(config.project.android?.packageName).isEqualTo("com.example.testproject")
|
|
332
|
+
assertThat(config.dependencies).hasSize(3)
|
|
333
|
+
assertThat(config.androidDependencies()).hasSize(2) // pure-js-module excluded
|
|
334
|
+
}
|
|
335
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
package run.granite.gradle.utils
|
|
2
|
+
|
|
3
|
+
import org.gradle.testfixtures.ProjectBuilder
|
|
4
|
+
import org.junit.jupiter.api.Test
|
|
5
|
+
import org.junit.jupiter.api.assertThrows
|
|
6
|
+
import kotlin.test.assertFalse
|
|
7
|
+
import kotlin.test.assertTrue
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Unit tests for ConflictDetector.
|
|
11
|
+
*/
|
|
12
|
+
class ConflictDetectorTest {
|
|
13
|
+
|
|
14
|
+
@Test
|
|
15
|
+
fun `validateNoConflicts succeeds when no React Native plugin is applied`() {
|
|
16
|
+
// Given
|
|
17
|
+
val project = ProjectBuilder.builder().build()
|
|
18
|
+
project.pluginManager.apply("com.android.library")
|
|
19
|
+
|
|
20
|
+
// When/Then - Should not throw
|
|
21
|
+
ConflictDetector.validateNoConflicts(project)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Test
|
|
25
|
+
fun `validateNoConflicts fails when React Native plugin is applied`() {
|
|
26
|
+
// Given
|
|
27
|
+
val project = ProjectBuilder.builder().build()
|
|
28
|
+
|
|
29
|
+
// Apply a mock plugin ID (can't apply actual React Native plugin in unit tests)
|
|
30
|
+
// This test verifies the logic structure
|
|
31
|
+
|
|
32
|
+
// When/Then
|
|
33
|
+
// Note: In real scenario with actual React Native plugin, this would throw
|
|
34
|
+
// For unit test, we just verify the method exists and is callable
|
|
35
|
+
ConflictDetector.validateNoConflicts(project)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@Test
|
|
39
|
+
fun `hasReactNativePlugin returns false when no RN plugin applied`() {
|
|
40
|
+
// Given
|
|
41
|
+
val project = ProjectBuilder.builder().build()
|
|
42
|
+
project.pluginManager.apply("com.android.library")
|
|
43
|
+
|
|
44
|
+
// When
|
|
45
|
+
val hasPlugin = ConflictDetector.hasReactNativePlugin(project)
|
|
46
|
+
|
|
47
|
+
// Then
|
|
48
|
+
assertFalse(hasPlugin)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Test
|
|
52
|
+
fun `detectMultipleGraniteModules warns when multiple modules use plugin`() {
|
|
53
|
+
// Given - Create root project with subprojects
|
|
54
|
+
val rootProject = ProjectBuilder.builder()
|
|
55
|
+
.withName("root")
|
|
56
|
+
.build()
|
|
57
|
+
|
|
58
|
+
val subproject1 = ProjectBuilder.builder()
|
|
59
|
+
.withName("lib1")
|
|
60
|
+
.withParent(rootProject)
|
|
61
|
+
.build()
|
|
62
|
+
|
|
63
|
+
val subproject2 = ProjectBuilder.builder()
|
|
64
|
+
.withName("lib2")
|
|
65
|
+
.withParent(rootProject)
|
|
66
|
+
.build()
|
|
67
|
+
|
|
68
|
+
// Apply Granite plugin to both (simulated)
|
|
69
|
+
// Note: Full multi-module detection requires actual plugin application
|
|
70
|
+
// which is tested in integration tests
|
|
71
|
+
|
|
72
|
+
// When/Then - Should log warning but not fail
|
|
73
|
+
ConflictDetector.validateNoConflicts(subproject1)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
package run.granite.gradle.utils
|
|
2
|
+
|
|
3
|
+
import org.gradle.api.JavaVersion
|
|
4
|
+
import org.gradle.testfixtures.ProjectBuilder
|
|
5
|
+
import org.junit.jupiter.api.Test
|
|
6
|
+
import org.junit.jupiter.api.assertThrows
|
|
7
|
+
import kotlin.test.assertEquals
|
|
8
|
+
import kotlin.test.assertTrue
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Unit tests for JdkValidator.
|
|
12
|
+
*/
|
|
13
|
+
class JdkValidatorTest {
|
|
14
|
+
|
|
15
|
+
@Test
|
|
16
|
+
fun `getCurrentVersion returns current Java version`() {
|
|
17
|
+
// When
|
|
18
|
+
val version = JdkValidator.getCurrentVersion()
|
|
19
|
+
|
|
20
|
+
// Then
|
|
21
|
+
assertEquals(JavaVersion.current(), version)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Test
|
|
25
|
+
fun `getMinimumVersion returns Java 17`() {
|
|
26
|
+
// When
|
|
27
|
+
val version = JdkValidator.getMinimumVersion()
|
|
28
|
+
|
|
29
|
+
// Then
|
|
30
|
+
assertEquals(JavaVersion.VERSION_17, version)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Test
|
|
34
|
+
fun `isCompatible returns true for JDK 17 and above`() {
|
|
35
|
+
// Given - Current JDK is being used
|
|
36
|
+
val currentJdk = JavaVersion.current()
|
|
37
|
+
|
|
38
|
+
// When
|
|
39
|
+
val isCompatible = JdkValidator.isCompatible()
|
|
40
|
+
|
|
41
|
+
// Then
|
|
42
|
+
if (currentJdk >= JavaVersion.VERSION_17) {
|
|
43
|
+
assertTrue(isCompatible)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@Test
|
|
48
|
+
fun `validate succeeds when JDK is 17 or higher`() {
|
|
49
|
+
// Given
|
|
50
|
+
val project = ProjectBuilder.builder().build()
|
|
51
|
+
val currentJdk = JavaVersion.current()
|
|
52
|
+
|
|
53
|
+
// When/Then - Should not throw if current JDK >= 17
|
|
54
|
+
if (currentJdk >= JavaVersion.VERSION_17) {
|
|
55
|
+
// Should succeed
|
|
56
|
+
JdkValidator.validate(project)
|
|
57
|
+
} else {
|
|
58
|
+
// Should fail
|
|
59
|
+
assertThrows<IllegalStateException> {
|
|
60
|
+
JdkValidator.validate(project)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@Test
|
|
66
|
+
fun `validate provides helpful error message for incompatible JDK`() {
|
|
67
|
+
// Given
|
|
68
|
+
val currentJdk = JavaVersion.current()
|
|
69
|
+
|
|
70
|
+
// Skip test if running on JDK 17+
|
|
71
|
+
if (currentJdk >= JavaVersion.VERSION_17) {
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Given
|
|
76
|
+
val project = ProjectBuilder.builder().build()
|
|
77
|
+
|
|
78
|
+
// When/Then
|
|
79
|
+
val exception = assertThrows<IllegalStateException> {
|
|
80
|
+
JdkValidator.validate(project)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Verify error message contains helpful information
|
|
84
|
+
val message = exception.message ?: ""
|
|
85
|
+
assertTrue(message.contains("JDK 17"))
|
|
86
|
+
assertTrue(message.contains("JAVA_HOME") || message.contains("gradle.properties"))
|
|
87
|
+
}
|
|
88
|
+
}
|