@thelacanians/vue-native-cli 0.4.15 → 0.6.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.
Files changed (116) hide show
  1. package/dist/cli.js +329 -15
  2. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/NativeBridge.kt +118 -0
  3. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VViewFactory.kt +178 -1
  4. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/GeneratedModuleRegistry.kt +28 -0
  5. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModuleRegistry.kt +3 -0
  6. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ComponentFactoryTest.kt +674 -0
  7. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ErrorOverlayViewTest.kt +183 -0
  8. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/EventThrottleTest.kt +203 -0
  9. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/HotReloadManagerTest.kt +162 -0
  10. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/JSPolyfillsTest.kt +153 -0
  11. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeBridgeTest.kt +6 -3
  12. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeModuleTest.kt +475 -0
  13. package/native/android/gradle.properties +1 -0
  14. package/native/android/gradlew +1 -1
  15. package/native/ios/VueNativeCore/Package.swift +1 -1
  16. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/EventThrottle.swift +1 -0
  17. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/NativeBridge.swift +143 -5
  18. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VTextFactory.swift +43 -0
  19. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift +116 -4
  20. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/GestureWrapper.swift +100 -0
  21. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/GeneratedModuleRegistry.swift +28 -0
  22. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModuleRegistry.swift +3 -0
  23. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/CertificatePinningTests.swift +190 -0
  24. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/ComponentFactoryTests.swift +585 -0
  25. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/EventThrottleTests.swift +161 -0
  26. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/HotReloadManagerTests.swift +88 -0
  27. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/JSPolyfillsTests.swift +319 -0
  28. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/NativeModuleTests.swift +400 -0
  29. package/native/macos/VueNativeMacOS/Package.swift +34 -0
  30. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/ErrorOverlayView.swift +112 -0
  31. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/EventThrottle.swift +58 -0
  32. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/HotReloadManager.swift +153 -0
  33. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSPolyfills.swift +696 -0
  34. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSRuntime.swift +347 -0
  35. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/NativeBridge.swift +877 -0
  36. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/VueNativeWindowController.swift +125 -0
  37. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/ComponentRegistry.swift +209 -0
  38. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActionSheetFactory.swift +155 -0
  39. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActivityIndicatorFactory.swift +85 -0
  40. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VAlertDialogFactory.swift +132 -0
  41. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VButtonFactory.swift +83 -0
  42. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VCheckboxFactory.swift +108 -0
  43. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VDropdownFactory.swift +155 -0
  44. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VImageFactory.swift +270 -0
  45. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VInputFactory.swift +257 -0
  46. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VKeyboardAvoidingFactory.swift +22 -0
  47. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VListFactory.swift +324 -0
  48. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VModalFactory.swift +231 -0
  49. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VOutlineViewFactory.swift +276 -0
  50. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPickerFactory.swift +134 -0
  51. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPressableFactory.swift +120 -0
  52. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VProgressBarFactory.swift +71 -0
  53. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRadioFactory.swift +193 -0
  54. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRefreshControlFactory.swift +25 -0
  55. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSafeAreaFactory.swift +46 -0
  56. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VScrollViewFactory.swift +190 -0
  57. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSectionListFactory.swift +374 -0
  58. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSegmentedControlFactory.swift +125 -0
  59. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSliderFactory.swift +131 -0
  60. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSplitViewFactory.swift +215 -0
  61. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VStatusBarFactory.swift +25 -0
  62. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSwitchFactory.swift +92 -0
  63. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VTextFactory.swift +336 -0
  64. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VToolbarFactory.swift +212 -0
  65. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VVideoFactory.swift +245 -0
  66. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VViewFactory.swift +314 -0
  67. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VWebViewFactory.swift +162 -0
  68. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/NativeComponentFactory.swift +54 -0
  69. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/ClickableView.swift +100 -0
  70. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/Extensions.swift +23 -0
  71. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/GestureWrapper.swift +183 -0
  72. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/NSColor+Hex.swift +78 -0
  73. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/FlippedView.swift +19 -0
  74. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/LayoutNode.swift +493 -0
  75. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AnimationModule.swift +354 -0
  76. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AppStateModule.swift +62 -0
  77. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/BiometryModule.swift +60 -0
  78. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/CameraModule.swift +167 -0
  79. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ClipboardModule.swift +34 -0
  80. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DeviceInfoModule.swift +49 -0
  81. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DragDropModule.swift +50 -0
  82. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/FileDialogModule.swift +86 -0
  83. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/HapticsModule.swift +42 -0
  84. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/KeyboardModule.swift +28 -0
  85. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/LinkingModule.swift +49 -0
  86. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/MenuModule.swift +95 -0
  87. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NativeModuleRegistry.swift +63 -0
  88. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NotificationsModule.swift +112 -0
  89. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/PermissionsModule.swift +149 -0
  90. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ShareModule.swift +37 -0
  91. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/WindowModule.swift +71 -0
  92. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Resources/vue-native-placeholder.js +2 -0
  93. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Styling/StyleEngine.swift +885 -0
  94. package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/ComponentFactoryTests.swift +80 -0
  95. package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/VueNativeMacOSTests.swift +149 -0
  96. package/native/shared/VueNativeShared/AGENTS.md +129 -0
  97. package/native/shared/VueNativeShared/Package.swift +14 -0
  98. package/native/shared/VueNativeShared/Sources/VueNativeShared/CertificatePinning.swift +134 -0
  99. package/native/shared/VueNativeShared/Sources/VueNativeShared/EventThrottle.swift +78 -0
  100. package/native/shared/VueNativeShared/Sources/VueNativeShared/HotReloadManager.swift +162 -0
  101. package/native/shared/VueNativeShared/Sources/VueNativeShared/JSRuntime.swift +412 -0
  102. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AsyncStorageModule.swift +68 -0
  103. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AudioModule.swift +359 -0
  104. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/DatabaseModule.swift +259 -0
  105. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/FileSystemModule.swift +233 -0
  106. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/GeolocationModule.swift +156 -0
  107. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/NetworkModule.swift +59 -0
  108. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/PerformanceModule.swift +113 -0
  109. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/SecureStorageModule.swift +119 -0
  110. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/WebSocketModule.swift +212 -0
  111. package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeEventDispatcher.swift +6 -0
  112. package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModule.swift +26 -0
  113. package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModuleRegistry.swift +37 -0
  114. package/native/shared/VueNativeShared/Sources/VueNativeShared/SharedJSPolyfills.swift +673 -0
  115. package/native/shared/VueNativeShared/Tests/VueNativeSharedTests/VueNativeSharedTests.swift +44 -0
  116. package/package.json +8 -2
@@ -0,0 +1,153 @@
1
+ package com.vuenative.core
2
+
3
+ import org.junit.Assert.assertEquals
4
+ import org.junit.Assert.assertNotNull
5
+ import org.junit.Assert.assertTrue
6
+ import org.junit.Before
7
+ import org.junit.Test
8
+ import org.junit.runner.RunWith
9
+ import org.robolectric.RobolectricTestRunner
10
+ import org.robolectric.annotation.Config
11
+
12
+ @RunWith(RobolectricTestRunner::class)
13
+ @Config(sdk = [34])
14
+ class JSPolyfillsTest {
15
+
16
+ @Before
17
+ fun setUp() {
18
+ JSPolyfills.reset()
19
+ }
20
+
21
+ // -------------------------------------------------------------------------
22
+ // reset() clears state
23
+ // -------------------------------------------------------------------------
24
+
25
+ @Test
26
+ fun testResetClearsState() {
27
+ // Call reset — should not throw
28
+ JSPolyfills.reset()
29
+ // Call again — idempotent
30
+ JSPolyfills.reset()
31
+ assertTrue("reset() should complete without error", true)
32
+ }
33
+
34
+ // -------------------------------------------------------------------------
35
+ // JSPolyfills is a singleton object
36
+ // -------------------------------------------------------------------------
37
+
38
+ @Test
39
+ fun testIsSingletonObject() {
40
+ val ref1 = JSPolyfills
41
+ val ref2 = JSPolyfills
42
+ assertTrue("JSPolyfills should be a singleton object", ref1 === ref2)
43
+ }
44
+
45
+ // -------------------------------------------------------------------------
46
+ // reset() is idempotent — can be called multiple times
47
+ // -------------------------------------------------------------------------
48
+
49
+ @Test
50
+ fun testResetIsIdempotent() {
51
+ JSPolyfills.reset()
52
+ JSPolyfills.reset()
53
+ JSPolyfills.reset()
54
+ assertTrue("Multiple resets should not crash", true)
55
+ }
56
+
57
+ // -------------------------------------------------------------------------
58
+ // TAG constant exists (validates structure)
59
+ // -------------------------------------------------------------------------
60
+
61
+ @Test
62
+ fun testTagConstant() {
63
+ // Access via reflection to verify TAG is set
64
+ val tagField = JSPolyfills::class.java.getDeclaredField("TAG")
65
+ tagField.isAccessible = true
66
+ val tag = tagField.get(null) as String
67
+ assertEquals("VueNative-Polyfills", tag)
68
+ }
69
+
70
+ // -------------------------------------------------------------------------
71
+ // Timer storage is accessible internally
72
+ // -------------------------------------------------------------------------
73
+
74
+ @Test
75
+ fun testTimerStorageCleared() {
76
+ // Access internal timers map via reflection
77
+ val timersField = JSPolyfills::class.java.getDeclaredField("timers")
78
+ timersField.isAccessible = true
79
+ @Suppress("UNCHECKED_CAST")
80
+ val timers = timersField.get(null) as MutableMap<Int, Runnable>
81
+ assertTrue("Timers should be empty after reset", timers.isEmpty())
82
+ }
83
+
84
+ // -------------------------------------------------------------------------
85
+ // Timer ID counter resets
86
+ // -------------------------------------------------------------------------
87
+
88
+ @Test
89
+ fun testTimerIdResets() {
90
+ val field = JSPolyfills::class.java.getDeclaredField("nextTimerId")
91
+ field.isAccessible = true
92
+
93
+ JSPolyfills.reset()
94
+ val afterReset = field.getInt(null)
95
+ assertEquals("nextTimerId should reset to 1", 1, afterReset)
96
+ }
97
+
98
+ // -------------------------------------------------------------------------
99
+ // RAF state resets
100
+ // -------------------------------------------------------------------------
101
+
102
+ @Test
103
+ fun testRafStateResets() {
104
+ val callbacksField = JSPolyfills::class.java.getDeclaredField("rafCallbacks")
105
+ callbacksField.isAccessible = true
106
+ @Suppress("UNCHECKED_CAST")
107
+ val rafCallbacks = callbacksField.get(null) as MutableMap<Int, Any>
108
+ assertTrue("RAF callbacks should be empty after reset", rafCallbacks.isEmpty())
109
+
110
+ val postedField = JSPolyfills::class.java.getDeclaredField("rafChoreographerPosted")
111
+ postedField.isAccessible = true
112
+ val posted = postedField.getBoolean(null)
113
+ assertTrue("rafChoreographerPosted should be false after reset", !posted)
114
+ }
115
+
116
+ // -------------------------------------------------------------------------
117
+ // RAF ID counter resets
118
+ // -------------------------------------------------------------------------
119
+
120
+ @Test
121
+ fun testRafIdResets() {
122
+ val field = JSPolyfills::class.java.getDeclaredField("nextRafId")
123
+ field.isAccessible = true
124
+
125
+ JSPolyfills.reset()
126
+ val afterReset = field.getInt(null)
127
+ assertEquals("nextRafId should reset to 1", 1, afterReset)
128
+ }
129
+
130
+ // -------------------------------------------------------------------------
131
+ // mainHandler exists
132
+ // -------------------------------------------------------------------------
133
+
134
+ @Test
135
+ fun testMainHandlerExists() {
136
+ val field = JSPolyfills::class.java.getDeclaredField("mainHandler")
137
+ field.isAccessible = true
138
+ val handler = field.get(null)
139
+ assertNotNull("mainHandler should not be null", handler)
140
+ }
141
+
142
+ // -------------------------------------------------------------------------
143
+ // httpClient exists
144
+ // -------------------------------------------------------------------------
145
+
146
+ @Test
147
+ fun testHttpClientExists() {
148
+ val field = JSPolyfills::class.java.getDeclaredField("httpClient")
149
+ field.isAccessible = true
150
+ val client = field.get(null)
151
+ assertNotNull("httpClient should not be null", client)
152
+ }
153
+ }
@@ -278,11 +278,14 @@ class NativeBridgeTest {
278
278
 
279
279
  assertNotNull("rootView should be set", bridge.rootView)
280
280
  assertEquals("rootView should be nodeViews[1]", bridge.nodeViews[1], bridge.rootView)
281
+ val hostContainer = bridge.hostContainer!!
281
282
  assertEquals(
282
- "hostContainer should have 1 child",
283
- 1,
284
- bridge.hostContainer!!.childCount
283
+ "hostContainer should have root view plus modal container",
284
+ 2,
285
+ hostContainer.childCount
285
286
  )
287
+ assertEquals("First child should be the root view", bridge.rootView, hostContainer.getChildAt(0))
288
+ assertTrue("Second child should be a modal FrameLayout", hostContainer.getChildAt(1) is FrameLayout)
286
289
  }
287
290
 
288
291
  // -------------------------------------------------------------------------
@@ -0,0 +1,475 @@
1
+ package com.vuenative.core
2
+
3
+ import android.content.Context
4
+ import android.widget.FrameLayout
5
+ import androidx.test.core.app.ApplicationProvider
6
+ import org.junit.Assert.assertEquals
7
+ import org.junit.Assert.assertNotNull
8
+ import org.junit.Assert.assertNull
9
+ import org.junit.Assert.assertTrue
10
+ import org.junit.Before
11
+ import org.junit.Test
12
+ import org.junit.runner.RunWith
13
+ import org.robolectric.RobolectricTestRunner
14
+ import org.robolectric.annotation.Config
15
+
16
+ @RunWith(RobolectricTestRunner::class)
17
+ @Config(sdk = [34])
18
+ class NativeModuleTest {
19
+
20
+ private lateinit var context: Context
21
+ private lateinit var bridge: NativeBridge
22
+
23
+ @Before
24
+ fun setUp() {
25
+ // Reset singletons
26
+ val crField = ComponentRegistry::class.java.getDeclaredField("instance")
27
+ crField.isAccessible = true
28
+ crField.set(null, null)
29
+
30
+ val nmrField = NativeModuleRegistry::class.java.getDeclaredField("instance")
31
+ nmrField.isAccessible = true
32
+ nmrField.set(null, null)
33
+
34
+ context = ApplicationProvider.getApplicationContext()
35
+ bridge = NativeBridge(context)
36
+ bridge.hostContainer = FrameLayout(context)
37
+ }
38
+
39
+ // =========================================================================
40
+ // HapticsModule
41
+ // =========================================================================
42
+
43
+ @Test
44
+ fun testHapticsModuleName() {
45
+ val module = HapticsModule()
46
+ assertEquals("Haptics", module.moduleName)
47
+ }
48
+
49
+ @Test
50
+ fun testHapticsModuleInitialize() {
51
+ val module = HapticsModule()
52
+ // Should not throw in Robolectric
53
+ module.initialize(context, bridge)
54
+ }
55
+
56
+ @Test
57
+ fun testHapticsModuleVibrateDoesNotCrash() {
58
+ val module = HapticsModule()
59
+ module.initialize(context, bridge)
60
+
61
+ var resultError: String? = "not_called"
62
+ module.invoke("vibrate", listOf("medium"), bridge) { _, error ->
63
+ resultError = error
64
+ }
65
+ assertNull("vibrate should not produce error", resultError)
66
+ }
67
+
68
+ @Test
69
+ fun testHapticsModuleSelectionChanged() {
70
+ val module = HapticsModule()
71
+ module.initialize(context, bridge)
72
+
73
+ var resultError: String? = "not_called"
74
+ module.invoke("selectionChanged", emptyList(), bridge) { _, error ->
75
+ resultError = error
76
+ }
77
+ assertNull("selectionChanged should not produce error", resultError)
78
+ }
79
+
80
+ @Test
81
+ fun testHapticsModuleUnknownMethod() {
82
+ val module = HapticsModule()
83
+ module.initialize(context, bridge)
84
+
85
+ var resultError: String? = null
86
+ module.invoke("nonexistent", emptyList(), bridge) { _, error ->
87
+ resultError = error
88
+ }
89
+ assertNotNull("Unknown method should produce error", resultError)
90
+ assertTrue("Error should mention method", resultError!!.contains("Unknown method"))
91
+ }
92
+
93
+ // =========================================================================
94
+ // ClipboardModule
95
+ // =========================================================================
96
+
97
+ @Test
98
+ fun testClipboardModuleName() {
99
+ val module = ClipboardModule()
100
+ assertEquals("Clipboard", module.moduleName)
101
+ }
102
+
103
+ @Test
104
+ fun testClipboardModuleSetAndGetString() {
105
+ val module = ClipboardModule()
106
+ module.initialize(context, bridge)
107
+
108
+ // Set
109
+ var setError: String? = "not_called"
110
+ module.invoke("setString", listOf("Hello Clipboard"), bridge) { _, error ->
111
+ setError = error
112
+ }
113
+ assertNull("setString should not produce error", setError)
114
+
115
+ // Get
116
+ var gotValue: Any? = null
117
+ module.invoke("getString", emptyList(), bridge) { result, _ ->
118
+ gotValue = result
119
+ }
120
+ assertEquals("Hello Clipboard", gotValue)
121
+ }
122
+
123
+ @Test
124
+ fun testClipboardModuleHasString() {
125
+ val module = ClipboardModule()
126
+ module.initialize(context, bridge)
127
+
128
+ module.invoke("setString", listOf("test"), bridge) { _, _ -> }
129
+
130
+ var hasString: Any? = null
131
+ module.invoke("hasString", emptyList(), bridge) { result, _ ->
132
+ hasString = result
133
+ }
134
+ assertEquals(true, hasString)
135
+ }
136
+
137
+ @Test
138
+ fun testClipboardModuleUnknownMethod() {
139
+ val module = ClipboardModule()
140
+ module.initialize(context, bridge)
141
+
142
+ var error: String? = null
143
+ module.invoke("nonexistent", emptyList(), bridge) { _, err ->
144
+ error = err
145
+ }
146
+ assertNotNull("Unknown method should produce error", error)
147
+ }
148
+
149
+ // =========================================================================
150
+ // DeviceInfoModule
151
+ // =========================================================================
152
+
153
+ @Test
154
+ fun testDeviceInfoModuleName() {
155
+ val module = DeviceInfoModule()
156
+ assertEquals("DeviceInfo", module.moduleName)
157
+ }
158
+
159
+ @Test
160
+ fun testDeviceInfoModuleReturnsInfo() {
161
+ val module = DeviceInfoModule()
162
+ module.initialize(context, bridge)
163
+
164
+ var result: Any? = null
165
+ module.invoke("getDeviceInfo", emptyList(), bridge) { res, _ ->
166
+ result = res
167
+ }
168
+
169
+ assertNotNull("getDeviceInfo should return data", result)
170
+ @Suppress("UNCHECKED_CAST")
171
+ val info = result as Map<String, Any>
172
+ assertEquals("android", info["platform"])
173
+ assertEquals("Android", info["systemName"])
174
+ assertNotNull("model should be present", info["model"])
175
+ assertNotNull("screenWidth should be present", info["screenWidth"])
176
+ assertNotNull("screenHeight should be present", info["screenHeight"])
177
+ assertNotNull("screenScale should be present", info["screenScale"])
178
+ assertNotNull("bundleId should be present", info["bundleId"])
179
+ }
180
+
181
+ @Test
182
+ fun testDeviceInfoModuleGetInfo() {
183
+ val module = DeviceInfoModule()
184
+ module.initialize(context, bridge)
185
+
186
+ var result: Any? = null
187
+ module.invoke("getInfo", emptyList(), bridge) { res, _ ->
188
+ result = res
189
+ }
190
+
191
+ assertNotNull("getInfo should return data", result)
192
+ }
193
+
194
+ @Test
195
+ fun testDeviceInfoModuleUnknownMethod() {
196
+ val module = DeviceInfoModule()
197
+ module.initialize(context, bridge)
198
+
199
+ var error: String? = null
200
+ module.invoke("nonexistent", emptyList(), bridge) { _, err ->
201
+ error = err
202
+ }
203
+ assertNotNull(error)
204
+ }
205
+
206
+ // =========================================================================
207
+ // AsyncStorageModule
208
+ // =========================================================================
209
+
210
+ @Test
211
+ fun testAsyncStorageModuleName() {
212
+ val module = AsyncStorageModule()
213
+ assertEquals("AsyncStorage", module.moduleName)
214
+ }
215
+
216
+ @Test
217
+ fun testAsyncStorageSetAndGetItem() {
218
+ val module = AsyncStorageModule()
219
+ module.initialize(context, bridge)
220
+
221
+ // Set
222
+ var setError: String? = "not_called"
223
+ module.invoke("setItem", listOf("testKey", "testValue"), bridge) { _, error ->
224
+ setError = error
225
+ }
226
+ assertNull("setItem should not produce error", setError)
227
+
228
+ // Get
229
+ var result: Any? = null
230
+ module.invoke("getItem", listOf("testKey"), bridge) { res, _ ->
231
+ result = res
232
+ }
233
+ assertEquals("testValue", result)
234
+ }
235
+
236
+ @Test
237
+ fun testAsyncStorageRemoveItem() {
238
+ val module = AsyncStorageModule()
239
+ module.initialize(context, bridge)
240
+
241
+ module.invoke("setItem", listOf("key1", "value1"), bridge) { _, _ -> }
242
+
243
+ module.invoke("removeItem", listOf("key1"), bridge) { _, _ -> }
244
+
245
+ var result: Any? = "not_null"
246
+ module.invoke("getItem", listOf("key1"), bridge) { res, _ ->
247
+ result = res
248
+ }
249
+ assertNull("Value should be null after removeItem", result)
250
+ }
251
+
252
+ @Test
253
+ fun testAsyncStorageClear() {
254
+ val module = AsyncStorageModule()
255
+ module.initialize(context, bridge)
256
+
257
+ module.invoke("setItem", listOf("k1", "v1"), bridge) { _, _ -> }
258
+ module.invoke("setItem", listOf("k2", "v2"), bridge) { _, _ -> }
259
+
260
+ module.invoke("clear", emptyList(), bridge) { _, _ -> }
261
+
262
+ var result: Any? = "not_null"
263
+ module.invoke("getItem", listOf("k1"), bridge) { res, _ ->
264
+ result = res
265
+ }
266
+ assertNull("Value should be null after clear", result)
267
+ }
268
+
269
+ @Test
270
+ fun testAsyncStorageGetAllKeys() {
271
+ val module = AsyncStorageModule()
272
+ module.initialize(context, bridge)
273
+
274
+ // Clear first
275
+ module.invoke("clear", emptyList(), bridge) { _, _ -> }
276
+
277
+ module.invoke("setItem", listOf("alpha", "1"), bridge) { _, _ -> }
278
+ module.invoke("setItem", listOf("beta", "2"), bridge) { _, _ -> }
279
+
280
+ var keys: Any? = null
281
+ module.invoke("getAllKeys", emptyList(), bridge) { res, _ ->
282
+ keys = res
283
+ }
284
+
285
+ assertNotNull("getAllKeys should return list", keys)
286
+ @Suppress("UNCHECKED_CAST")
287
+ val keyList = keys as List<String>
288
+ assertTrue("Keys should contain 'alpha'", keyList.contains("alpha"))
289
+ assertTrue("Keys should contain 'beta'", keyList.contains("beta"))
290
+ }
291
+
292
+ @Test
293
+ fun testAsyncStorageMissingKeyError() {
294
+ val module = AsyncStorageModule()
295
+ module.initialize(context, bridge)
296
+
297
+ var error: String? = null
298
+ module.invoke("getItem", emptyList(), bridge) { _, err ->
299
+ error = err
300
+ }
301
+ assertNotNull("Missing key should produce error", error)
302
+ assertTrue("Error should mention key", error!!.contains("key", ignoreCase = true))
303
+ }
304
+
305
+ @Test
306
+ fun testAsyncStorageUnknownMethod() {
307
+ val module = AsyncStorageModule()
308
+ module.initialize(context, bridge)
309
+
310
+ var error: String? = null
311
+ module.invoke("nonexistent", emptyList(), bridge) { _, err ->
312
+ error = err
313
+ }
314
+ assertNotNull(error)
315
+ }
316
+
317
+ // =========================================================================
318
+ // AnimationModule
319
+ // =========================================================================
320
+
321
+ @Test
322
+ fun testAnimationModuleName() {
323
+ val module = AnimationModule()
324
+ assertEquals("Animation", module.moduleName)
325
+ }
326
+
327
+ @Test
328
+ fun testAnimationModuleUnknownMethod() {
329
+ val module = AnimationModule()
330
+ module.initialize(context, bridge)
331
+
332
+ var error: String? = null
333
+ module.invoke("nonexistent", emptyList(), bridge) { _, err ->
334
+ error = err
335
+ }
336
+ assertNotNull("Unknown animation method should produce error", error)
337
+ assertTrue(error!!.contains("Unknown animation method"))
338
+ }
339
+
340
+ // =========================================================================
341
+ // NetworkModule
342
+ // =========================================================================
343
+
344
+ @Test
345
+ fun testNetworkModuleName() {
346
+ val module = NetworkModule()
347
+ assertEquals("Network", module.moduleName)
348
+ }
349
+
350
+ @Test
351
+ fun testNetworkModuleGetStatus() {
352
+ val module = NetworkModule()
353
+ module.initialize(context, bridge)
354
+
355
+ var result: Any? = null
356
+ module.invoke("getStatus", emptyList(), bridge) { res, _ ->
357
+ result = res
358
+ }
359
+
360
+ assertNotNull("getStatus should return data", result)
361
+ @Suppress("UNCHECKED_CAST")
362
+ val status = result as Map<String, Any>
363
+ assertTrue("Status should contain isConnected", status.containsKey("isConnected"))
364
+ assertTrue("Status should contain connectionType", status.containsKey("connectionType"))
365
+ }
366
+
367
+ @Test
368
+ fun testNetworkModuleUnknownMethod() {
369
+ val module = NetworkModule()
370
+ module.initialize(context, bridge)
371
+
372
+ var error: String? = null
373
+ module.invoke("nonexistent", emptyList(), bridge) { _, err ->
374
+ error = err
375
+ }
376
+ assertNotNull(error)
377
+ }
378
+
379
+ @Test
380
+ fun testNetworkModuleDestroy() {
381
+ val module = NetworkModule()
382
+ module.initialize(context, bridge)
383
+ // Should not crash
384
+ module.destroy()
385
+ }
386
+
387
+ // =========================================================================
388
+ // KeyboardModule
389
+ // =========================================================================
390
+
391
+ @Test
392
+ fun testKeyboardModuleName() {
393
+ val module = KeyboardModule()
394
+ assertEquals("Keyboard", module.moduleName)
395
+ }
396
+
397
+ @Test
398
+ fun testKeyboardModuleDismiss() {
399
+ val module = KeyboardModule()
400
+ module.initialize(context, bridge)
401
+
402
+ var error: String? = "not_called"
403
+ module.invoke("dismiss", emptyList(), bridge) { _, err ->
404
+ error = err
405
+ }
406
+ assertNull("dismiss should not produce error", error)
407
+ }
408
+
409
+ @Test
410
+ fun testKeyboardModuleGetHeight() {
411
+ val module = KeyboardModule()
412
+ module.initialize(context, bridge)
413
+
414
+ var result: Any? = null
415
+ module.invoke("getKeyboardHeight", emptyList(), bridge) { res, _ ->
416
+ result = res
417
+ }
418
+ assertEquals(0, result)
419
+ }
420
+
421
+ @Test
422
+ fun testKeyboardModuleUnknownMethod() {
423
+ val module = KeyboardModule()
424
+ module.initialize(context, bridge)
425
+
426
+ var error: String? = null
427
+ module.invoke("nonexistent", emptyList(), bridge) { _, err ->
428
+ error = err
429
+ }
430
+ assertNotNull(error)
431
+ }
432
+
433
+ // =========================================================================
434
+ // NativeModule interface defaults
435
+ // =========================================================================
436
+
437
+ @Test
438
+ fun testNativeModuleDefaultInvokeSync() {
439
+ val module = object : NativeModule {
440
+ override val moduleName = "TestDefault"
441
+ override fun invoke(method: String, args: List<Any?>, bridge: NativeBridge, callback: (Any?, String?) -> Unit) {
442
+ callback(null, null)
443
+ }
444
+ }
445
+
446
+ val result = module.invokeSync("test", emptyList(), bridge)
447
+ assertNull("Default invokeSync should return null", result)
448
+ }
449
+
450
+ @Test
451
+ fun testNativeModuleDefaultInitialize() {
452
+ val module = object : NativeModule {
453
+ override val moduleName = "TestDefault"
454
+ override fun invoke(method: String, args: List<Any?>, bridge: NativeBridge, callback: (Any?, String?) -> Unit) {
455
+ callback(null, null)
456
+ }
457
+ }
458
+
459
+ // Default initialize should not crash
460
+ module.initialize(context, bridge)
461
+ }
462
+
463
+ @Test
464
+ fun testNativeModuleDefaultDestroy() {
465
+ val module = object : NativeModule {
466
+ override val moduleName = "TestDefault"
467
+ override fun invoke(method: String, args: List<Any?>, bridge: NativeBridge, callback: (Any?, String?) -> Unit) {
468
+ callback(null, null)
469
+ }
470
+ }
471
+
472
+ // Default destroy should not crash
473
+ module.destroy()
474
+ }
475
+ }
@@ -1,4 +1,5 @@
1
1
  org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
2
2
  android.useAndroidX=true
3
3
  android.enableJetifier=true
4
+ android.suppressUnsupportedCompileSdk=35
4
5
  kotlin.code.style=official
@@ -14,7 +14,7 @@ while [ -h "$PRG" ] ; do
14
14
  fi
15
15
  done
16
16
  SAVED="$(pwd)"
17
- cd "$(dirname \"$PRG\")/" >/dev/null
17
+ cd "$(dirname "$PRG")/" >/dev/null
18
18
  APP_HOME="$(pwd -P)"
19
19
  cd "$SAVED" >/dev/null
20
20
 
@@ -21,7 +21,7 @@ let package = Package(
21
21
  path: "Sources/VueNativeCore",
22
22
  resources: [
23
23
  .copy("Resources/vue-native-placeholder.js")
24
- ],
24
+ ]
25
25
  ),
26
26
  .testTarget(
27
27
  name: "VueNativeCoreTests",
@@ -1,5 +1,6 @@
1
1
  #if canImport(UIKit)
2
2
  import Foundation
3
+ import QuartzCore
3
4
 
4
5
  /// Throttles high-frequency event handlers to avoid flooding the JS bridge.
5
6
  ///