@thelacanians/vue-native-cli 0.4.15 → 0.6.2
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/dist/cli.js +329 -15
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/NativeBridge.kt +118 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VViewFactory.kt +178 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/GeneratedModuleRegistry.kt +28 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModuleRegistry.kt +3 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ComponentFactoryTest.kt +674 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ErrorOverlayViewTest.kt +183 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/EventThrottleTest.kt +203 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/HotReloadManagerTest.kt +162 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/JSPolyfillsTest.kt +153 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeBridgeTest.kt +6 -3
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeModuleTest.kt +475 -0
- package/native/android/gradle.properties +1 -0
- package/native/android/gradlew +1 -1
- package/native/ios/VueNativeCore/Package.swift +1 -1
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/EventThrottle.swift +1 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/NativeBridge.swift +143 -5
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VTextFactory.swift +43 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift +116 -4
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/GestureWrapper.swift +100 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/GeneratedModuleRegistry.swift +28 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModuleRegistry.swift +3 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/CertificatePinningTests.swift +190 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/ComponentFactoryTests.swift +585 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/EventThrottleTests.swift +161 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/HotReloadManagerTests.swift +88 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/JSPolyfillsTests.swift +319 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/NativeModuleTests.swift +400 -0
- package/native/macos/VueNativeMacOS/Package.swift +34 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/ErrorOverlayView.swift +112 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/EventThrottle.swift +58 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/HotReloadManager.swift +153 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSPolyfills.swift +696 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSRuntime.swift +347 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/NativeBridge.swift +877 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/VueNativeWindowController.swift +125 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/ComponentRegistry.swift +209 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActionSheetFactory.swift +155 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActivityIndicatorFactory.swift +85 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VAlertDialogFactory.swift +132 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VButtonFactory.swift +83 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VCheckboxFactory.swift +108 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VDropdownFactory.swift +155 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VImageFactory.swift +270 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VInputFactory.swift +257 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VKeyboardAvoidingFactory.swift +22 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VListFactory.swift +324 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VModalFactory.swift +231 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VOutlineViewFactory.swift +276 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPickerFactory.swift +134 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPressableFactory.swift +120 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VProgressBarFactory.swift +71 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRadioFactory.swift +193 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRefreshControlFactory.swift +25 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSafeAreaFactory.swift +46 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VScrollViewFactory.swift +190 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSectionListFactory.swift +374 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSegmentedControlFactory.swift +125 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSliderFactory.swift +131 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSplitViewFactory.swift +215 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VStatusBarFactory.swift +25 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSwitchFactory.swift +92 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VTextFactory.swift +336 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VToolbarFactory.swift +212 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VVideoFactory.swift +245 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VViewFactory.swift +314 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VWebViewFactory.swift +162 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/NativeComponentFactory.swift +54 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/ClickableView.swift +100 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/Extensions.swift +23 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/GestureWrapper.swift +183 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/NSColor+Hex.swift +78 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/FlippedView.swift +19 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/LayoutNode.swift +493 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AnimationModule.swift +354 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AppStateModule.swift +62 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/BiometryModule.swift +60 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/CameraModule.swift +167 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ClipboardModule.swift +34 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DeviceInfoModule.swift +49 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DragDropModule.swift +50 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/FileDialogModule.swift +86 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/HapticsModule.swift +42 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/KeyboardModule.swift +28 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/LinkingModule.swift +49 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/MenuModule.swift +95 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NativeModuleRegistry.swift +63 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NotificationsModule.swift +112 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/PermissionsModule.swift +149 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ShareModule.swift +37 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/WindowModule.swift +71 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Resources/vue-native-placeholder.js +2 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Styling/StyleEngine.swift +885 -0
- package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/ComponentFactoryTests.swift +80 -0
- package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/VueNativeMacOSTests.swift +149 -0
- package/native/shared/VueNativeShared/AGENTS.md +129 -0
- package/native/shared/VueNativeShared/Package.swift +14 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/CertificatePinning.swift +134 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/EventThrottle.swift +78 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/HotReloadManager.swift +162 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/JSRuntime.swift +412 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AsyncStorageModule.swift +68 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AudioModule.swift +359 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/DatabaseModule.swift +259 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/FileSystemModule.swift +233 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/GeolocationModule.swift +156 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/NetworkModule.swift +59 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/PerformanceModule.swift +113 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/SecureStorageModule.swift +119 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/WebSocketModule.swift +212 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeEventDispatcher.swift +6 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModule.swift +26 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModuleRegistry.swift +37 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/SharedJSPolyfills.swift +673 -0
- package/native/shared/VueNativeShared/Tests/VueNativeSharedTests/VueNativeSharedTests.swift +44 -0
- 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
|
|
283
|
-
|
|
284
|
-
|
|
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
|
+
}
|
package/native/android/gradlew
CHANGED