@dashx/react-native 1.1.1 → 1.1.3

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 (132) hide show
  1. package/.DS_Store +0 -0
  2. package/.claude/settings.local.json +14 -0
  3. package/.github/workflows/ci.yml +28 -0
  4. package/CONTRIBUTING.md +153 -0
  5. package/DashXReactNative.podspec +6 -2
  6. package/README.md +259 -97
  7. package/__tests__/index.test.js +363 -0
  8. package/android/.gitignore +10 -0
  9. package/android/.gradle/7.2/dependencies-accessors/dependencies-accessors.lock +0 -0
  10. package/android/.gradle/7.2/dependencies-accessors/gc.properties +0 -0
  11. package/android/.gradle/7.2/fileChanges/last-build.bin +0 -0
  12. package/android/.gradle/7.2/fileHashes/fileHashes.lock +0 -0
  13. package/android/.gradle/7.2/gc.properties +0 -0
  14. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  15. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  16. package/android/.gradle/checksums/checksums.lock +0 -0
  17. package/android/.gradle/checksums/md5-checksums.bin +0 -0
  18. package/android/.gradle/checksums/sha1-checksums.bin +0 -0
  19. package/android/.gradle/vcs-1/gc.properties +0 -0
  20. package/android/build/.transforms/9dceace6c3787533d2dbb1a387e9284c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/dashx/rn/sdk/DashXReactNativeFirebaseMessagingService.dex +0 -0
  21. package/android/build/.transforms/9dceace6c3787533d2dbb1a387e9284c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/dashx/rn/sdk/DashXReactNativeModule.dex +0 -0
  22. package/android/build/.transforms/9dceace6c3787533d2dbb1a387e9284c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/dashx/rn/sdk/MessageReceivedEventHolder.dex +0 -0
  23. package/android/build/.transforms/9dceace6c3787533d2dbb1a387e9284c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/dashx/rn/sdk/util/Utils$WhenMappings.dex +0 -0
  24. package/android/build/.transforms/9dceace6c3787533d2dbb1a387e9284c/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/dashx/rn/sdk/util/Utils.dex +0 -0
  25. package/android/build/.transforms/9dceace6c3787533d2dbb1a387e9284c/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
  26. package/android/build/.transforms/f3c6049e7ab4bb564c79f3a246b8575e/transformed/classes/classes_dex/classes.dex +0 -0
  27. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +16 -0
  28. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  29. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +31 -5
  30. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +16 -0
  31. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/dashx/rn/sdk/DashXReactNativeFirebaseMessagingService.class +0 -0
  32. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/dashx/rn/sdk/DashXReactNativeModule.class +0 -0
  33. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/dashx/rn/sdk/MessageReceivedEventHolder.class +0 -0
  34. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/dashx/rn/sdk/util/Utils$WhenMappings.class +0 -0
  35. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/dashx/rn/sdk/util/Utils.class +0 -0
  36. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  37. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  38. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
  39. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
  40. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
  41. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  42. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
  43. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  44. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  45. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  46. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
  47. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  48. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  49. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  50. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  51. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  52. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
  53. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  54. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  55. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  56. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  57. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  58. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  59. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  60. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  61. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab +0 -0
  62. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at +0 -0
  63. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  64. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  65. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  66. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
  67. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  68. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  69. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  70. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
  71. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
  72. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
  73. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  74. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
  75. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  76. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
  77. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
  78. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
  79. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  80. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
  81. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  82. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
  83. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
  84. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
  85. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  86. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
  87. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +1 -1
  88. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  89. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
  90. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
  91. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
  92. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  93. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
  94. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  95. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  96. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  97. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  98. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  99. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  100. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  101. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  102. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  103. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  104. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  105. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  106. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  107. package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  108. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  109. package/android/build/outputs/logs/manifest-merger-debug-report.txt +25 -3
  110. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  111. package/android/build/tmp/kotlin-classes/debug/com/dashx/rn/sdk/DashXReactNativeFirebaseMessagingService.class +0 -0
  112. package/android/build/tmp/kotlin-classes/debug/com/dashx/rn/sdk/DashXReactNativeModule.class +0 -0
  113. package/android/build/tmp/kotlin-classes/debug/com/dashx/rn/sdk/MessageReceivedEventHolder.class +0 -0
  114. package/android/build/tmp/kotlin-classes/debug/com/dashx/rn/sdk/util/Utils$WhenMappings.class +0 -0
  115. package/android/build/tmp/kotlin-classes/debug/com/dashx/rn/sdk/util/Utils.class +0 -0
  116. package/android/build.gradle +4 -1
  117. package/android/src/main/AndroidManifest.xml +15 -3
  118. package/android/src/main/java/com/dashx/rn/sdk/DashXReactNativeFirebaseMessagingService.kt +72 -0
  119. package/android/src/main/java/com/dashx/rn/sdk/DashXReactNativeModule.kt +84 -15
  120. package/android/src/main/java/com/dashx/rn/sdk/MessageReceivedEventHolder.kt +14 -0
  121. package/android/src/main/java/com/dashx/rn/sdk/util/Utils.kt +14 -0
  122. package/babel.config.js +1 -1
  123. package/index.d.ts +107 -0
  124. package/index.js +81 -4
  125. package/ios/.DS_Store +0 -0
  126. package/ios/DashXEventEmitter.swift +3 -2
  127. package/ios/DashXRCTAppDelegate.swift +110 -44
  128. package/ios/DashXReactNative-Bridging-Header.h +2 -0
  129. package/ios/DashXReactNative.h +1 -0
  130. package/ios/DashXReactNative.mm +16 -0
  131. package/ios/DashXReactNative.swift +118 -28
  132. package/package.json +18 -5
@@ -0,0 +1,363 @@
1
+ const mockNativeModule = {
2
+ configure: jest.fn(),
3
+ identify: jest.fn(),
4
+ setIdentity: jest.fn(),
5
+ reset: jest.fn(),
6
+ track: jest.fn(),
7
+ screen: jest.fn(),
8
+ fetchRecord: jest.fn(),
9
+ searchRecords: jest.fn(),
10
+ fetchStoredPreferences: jest.fn(),
11
+ saveStoredPreferences: jest.fn(),
12
+ subscribe: jest.fn(),
13
+ unsubscribe: jest.fn(),
14
+ setLogLevel: jest.fn(),
15
+ uploadAsset: jest.fn(),
16
+ fetchAsset: jest.fn(),
17
+ enableLifecycleTracking: jest.fn(),
18
+ enableAdTracking: jest.fn(),
19
+ requestNotificationPermission: jest.fn(),
20
+ getNotificationPermissionStatus: jest.fn(),
21
+ addListener: jest.fn(),
22
+ removeListeners: jest.fn(),
23
+ };
24
+
25
+ const mockAddListener = jest.fn(() => ({ remove: jest.fn() }));
26
+
27
+ jest.mock('react-native', () => ({
28
+ NativeModules: {
29
+ DashXReactNative: mockNativeModule,
30
+ },
31
+ NativeEventEmitter: jest.fn().mockImplementation(() => ({
32
+ addListener: mockAddListener,
33
+ })),
34
+ Platform: {
35
+ select: jest.fn((obj) => obj.default || ''),
36
+ },
37
+ }));
38
+
39
+ const DashX = require('../index').default;
40
+
41
+ beforeEach(() => {
42
+ jest.clearAllMocks();
43
+ });
44
+
45
+ // --- configure ---
46
+
47
+ describe('configure', () => {
48
+ it('calls native configure with options', () => {
49
+ DashX.configure({ publicKey: 'pk_test' });
50
+ expect(mockNativeModule.configure).toHaveBeenCalledWith({
51
+ publicKey: 'pk_test',
52
+ });
53
+ });
54
+
55
+ it('throws if options is not an object', () => {
56
+ expect(() => DashX.configure(null)).toThrow('options must be an object');
57
+ expect(() => DashX.configure('string')).toThrow('options must be an object');
58
+ });
59
+
60
+ it('throws if publicKey is missing', () => {
61
+ expect(() => DashX.configure({})).toThrow('publicKey is required');
62
+ });
63
+
64
+ it('throws if publicKey is not a string', () => {
65
+ expect(() => DashX.configure({ publicKey: 123 })).toThrow(
66
+ 'publicKey is required and must be a string'
67
+ );
68
+ });
69
+ });
70
+
71
+ // --- identify ---
72
+
73
+ describe('identify', () => {
74
+ it('calls native identify with options', () => {
75
+ DashX.identify({ email: 'test@example.com' });
76
+ expect(mockNativeModule.identify).toHaveBeenCalledWith({
77
+ email: 'test@example.com',
78
+ });
79
+ });
80
+
81
+ it('throws if options is not an object', () => {
82
+ expect(() => DashX.identify(null)).toThrow('options must be an object');
83
+ });
84
+ });
85
+
86
+ // --- setIdentity ---
87
+
88
+ describe('setIdentity', () => {
89
+ it('calls native setIdentity with uid and token', () => {
90
+ DashX.setIdentity('user-1', 'token-abc');
91
+ expect(mockNativeModule.setIdentity).toHaveBeenCalledWith(
92
+ 'user-1',
93
+ 'token-abc'
94
+ );
95
+ });
96
+
97
+ it('throws if uid is missing', () => {
98
+ expect(() => DashX.setIdentity(null, 'token')).toThrow('uid is required');
99
+ });
100
+
101
+ it('throws if token is missing', () => {
102
+ expect(() => DashX.setIdentity('uid', null)).toThrow(
103
+ 'token is required'
104
+ );
105
+ });
106
+ });
107
+
108
+ // --- reset ---
109
+
110
+ describe('reset', () => {
111
+ it('calls native reset', () => {
112
+ DashX.reset();
113
+ expect(mockNativeModule.reset).toHaveBeenCalled();
114
+ });
115
+ });
116
+
117
+ // --- track ---
118
+
119
+ describe('track', () => {
120
+ it('calls native track with event and data', () => {
121
+ DashX.track('purchase', { amount: 100 });
122
+ expect(mockNativeModule.track).toHaveBeenCalledWith('purchase', {
123
+ amount: 100,
124
+ });
125
+ });
126
+
127
+ it('calls native track with null data when omitted', () => {
128
+ DashX.track('page_view');
129
+ expect(mockNativeModule.track).toHaveBeenCalledWith('page_view', null);
130
+ });
131
+
132
+ it('throws if event is missing', () => {
133
+ expect(() => DashX.track(null)).toThrow('event is required');
134
+ });
135
+
136
+ it('throws if event is not a string', () => {
137
+ expect(() => DashX.track(42)).toThrow(
138
+ 'event is required and must be a string'
139
+ );
140
+ });
141
+ });
142
+
143
+ // --- screen ---
144
+
145
+ describe('screen', () => {
146
+ it('calls native screen with name and data', () => {
147
+ DashX.screen('Home', { section: 'top' });
148
+ expect(mockNativeModule.screen).toHaveBeenCalledWith('Home', {
149
+ section: 'top',
150
+ });
151
+ });
152
+
153
+ it('calls native screen with null data when omitted', () => {
154
+ DashX.screen('Settings');
155
+ expect(mockNativeModule.screen).toHaveBeenCalledWith('Settings', null);
156
+ });
157
+
158
+ it('throws if screenName is missing', () => {
159
+ expect(() => DashX.screen(null)).toThrow('screenName is required');
160
+ });
161
+ });
162
+
163
+ // --- fetchRecord ---
164
+
165
+ describe('fetchRecord', () => {
166
+ it('calls native fetchRecord with urn and options', () => {
167
+ mockNativeModule.fetchRecord.mockResolvedValue({ id: '123' });
168
+ const result = DashX.fetchRecord('article/123', { preview: true });
169
+ expect(mockNativeModule.fetchRecord).toHaveBeenCalledWith('article/123', {
170
+ preview: true,
171
+ });
172
+ return expect(result).resolves.toEqual({ id: '123' });
173
+ });
174
+
175
+ it('calls native fetchRecord with empty options when omitted', () => {
176
+ mockNativeModule.fetchRecord.mockResolvedValue({});
177
+ DashX.fetchRecord('article/456');
178
+ expect(mockNativeModule.fetchRecord).toHaveBeenCalledWith(
179
+ 'article/456',
180
+ {}
181
+ );
182
+ });
183
+
184
+ it('throws if urn is missing', () => {
185
+ expect(() => DashX.fetchRecord(null)).toThrow('urn is required');
186
+ });
187
+ });
188
+
189
+ // --- searchRecords ---
190
+
191
+ describe('searchRecords', () => {
192
+ it('calls native searchRecords with resource and options', () => {
193
+ mockNativeModule.searchRecords.mockResolvedValue([{ id: '1' }]);
194
+ const result = DashX.searchRecords('articles', { limit: 10 });
195
+ expect(mockNativeModule.searchRecords).toHaveBeenCalledWith('articles', {
196
+ limit: 10,
197
+ });
198
+ return expect(result).resolves.toEqual([{ id: '1' }]);
199
+ });
200
+
201
+ it('throws if resource is missing', () => {
202
+ expect(() => DashX.searchRecords(null)).toThrow('resource is required');
203
+ });
204
+ });
205
+
206
+ // --- fetchStoredPreferences ---
207
+
208
+ describe('fetchStoredPreferences', () => {
209
+ it('calls native fetchStoredPreferences', () => {
210
+ mockNativeModule.fetchStoredPreferences.mockResolvedValue({
211
+ email: true,
212
+ });
213
+ const result = DashX.fetchStoredPreferences();
214
+ expect(mockNativeModule.fetchStoredPreferences).toHaveBeenCalled();
215
+ return expect(result).resolves.toEqual({ email: true });
216
+ });
217
+ });
218
+
219
+ // --- saveStoredPreferences ---
220
+
221
+ describe('saveStoredPreferences', () => {
222
+ it('calls native saveStoredPreferences with data', () => {
223
+ mockNativeModule.saveStoredPreferences.mockResolvedValue({ success: true });
224
+ const result = DashX.saveStoredPreferences({ email: false });
225
+ expect(mockNativeModule.saveStoredPreferences).toHaveBeenCalledWith({
226
+ email: false,
227
+ });
228
+ return expect(result).resolves.toEqual({ success: true });
229
+ });
230
+
231
+ it('throws if preferenceData is not an object', () => {
232
+ expect(() => DashX.saveStoredPreferences(null)).toThrow(
233
+ 'preferenceData is required'
234
+ );
235
+ });
236
+ });
237
+
238
+ // --- subscribe / unsubscribe ---
239
+
240
+ describe('subscribe', () => {
241
+ it('calls native subscribe', () => {
242
+ DashX.subscribe();
243
+ expect(mockNativeModule.subscribe).toHaveBeenCalled();
244
+ });
245
+ });
246
+
247
+ describe('unsubscribe', () => {
248
+ it('calls native unsubscribe', () => {
249
+ DashX.unsubscribe();
250
+ expect(mockNativeModule.unsubscribe).toHaveBeenCalled();
251
+ });
252
+ });
253
+
254
+ // --- setLogLevel ---
255
+
256
+ describe('setLogLevel', () => {
257
+ it('calls native setLogLevel with level', () => {
258
+ DashX.setLogLevel(2);
259
+ expect(mockNativeModule.setLogLevel).toHaveBeenCalledWith(2);
260
+ });
261
+
262
+ it('throws if level is not a number', () => {
263
+ expect(() => DashX.setLogLevel('debug')).toThrow(
264
+ 'level must be a number'
265
+ );
266
+ });
267
+ });
268
+
269
+ // --- onMessageReceived ---
270
+
271
+ describe('onMessageReceived', () => {
272
+ it('throws if callback is not a function', () => {
273
+ expect(() => DashX.onMessageReceived('not a function')).toThrow(
274
+ 'callback must be a function'
275
+ );
276
+ });
277
+
278
+ it('registers a listener for messageReceived events', () => {
279
+ const callback = jest.fn();
280
+ const subscription = DashX.onMessageReceived(callback);
281
+ expect(mockAddListener).toHaveBeenCalledWith('messageReceived', callback);
282
+ expect(subscription).toBeDefined();
283
+ });
284
+ });
285
+
286
+ // --- uploadAsset ---
287
+
288
+ describe('uploadAsset', () => {
289
+ it('calls native uploadAsset with filePath, resource, attribute', () => {
290
+ mockNativeModule.uploadAsset.mockResolvedValue({ status: 'ready' });
291
+ const result = DashX.uploadAsset('/path/to/file.jpg', 'products', 'image');
292
+ expect(mockNativeModule.uploadAsset).toHaveBeenCalledWith(
293
+ '/path/to/file.jpg',
294
+ 'products',
295
+ 'image'
296
+ );
297
+ return expect(result).resolves.toEqual({ status: 'ready' });
298
+ });
299
+
300
+ it('throws if filePath is missing', () => {
301
+ expect(() => DashX.uploadAsset(null, 'r', 'a')).toThrow('filePath must be a string');
302
+ });
303
+
304
+ it('throws if resource is missing', () => {
305
+ expect(() => DashX.uploadAsset('/path', null, 'a')).toThrow('resource must be a string');
306
+ });
307
+
308
+ it('throws if attribute is missing', () => {
309
+ expect(() => DashX.uploadAsset('/path', 'r', null)).toThrow('attribute must be a string');
310
+ });
311
+ });
312
+
313
+ // --- fetchAsset ---
314
+
315
+ describe('fetchAsset', () => {
316
+ it('calls native fetchAsset with assetId', () => {
317
+ mockNativeModule.fetchAsset.mockResolvedValue({ status: 'ready' });
318
+ const result = DashX.fetchAsset('asset-123');
319
+ expect(mockNativeModule.fetchAsset).toHaveBeenCalledWith('asset-123');
320
+ return expect(result).resolves.toEqual({ status: 'ready' });
321
+ });
322
+
323
+ it('throws if assetId is missing', () => {
324
+ expect(() => DashX.fetchAsset(null)).toThrow('assetId must be a string');
325
+ });
326
+ });
327
+
328
+ // --- requestNotificationPermission / getNotificationPermissionStatus ---
329
+
330
+ describe('requestNotificationPermission', () => {
331
+ it('calls native requestNotificationPermission', () => {
332
+ mockNativeModule.requestNotificationPermission.mockResolvedValue(2);
333
+ const result = DashX.requestNotificationPermission();
334
+ expect(mockNativeModule.requestNotificationPermission).toHaveBeenCalled();
335
+ return expect(result).resolves.toBe(2);
336
+ });
337
+ });
338
+
339
+ describe('getNotificationPermissionStatus', () => {
340
+ it('calls native getNotificationPermissionStatus', () => {
341
+ mockNativeModule.getNotificationPermissionStatus.mockResolvedValue(1);
342
+ const result = DashX.getNotificationPermissionStatus();
343
+ expect(mockNativeModule.getNotificationPermissionStatus).toHaveBeenCalled();
344
+ return expect(result).resolves.toBe(1);
345
+ });
346
+ });
347
+
348
+ // --- onLinkReceived ---
349
+
350
+ describe('onLinkReceived', () => {
351
+ it('throws if callback is not a function', () => {
352
+ expect(() => DashX.onLinkReceived('not a function')).toThrow(
353
+ 'callback must be a function'
354
+ );
355
+ });
356
+
357
+ it('registers a listener for linkReceived events', () => {
358
+ const callback = jest.fn();
359
+ const subscription = DashX.onLinkReceived(callback);
360
+ expect(mockAddListener).toHaveBeenCalledWith('linkReceived', callback);
361
+ expect(subscription).toBeDefined();
362
+ });
363
+ });
@@ -0,0 +1,10 @@
1
+ # Build outputs
2
+ build/
3
+
4
+ # Gradle
5
+ .gradle/
6
+ local.properties
7
+
8
+ # IDE
9
+ .idea/
10
+ *.iml
File without changes
@@ -0,0 +1,2 @@
1
+ #Mon Mar 23 22:47:55 IST 2026
2
+ gradle.version=7.2
File without changes
@@ -1,7 +1,23 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
2
  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ xmlns:tools="http://schemas.android.com/tools"
3
4
  package="com.dashx.rn.sdk" >
4
5
 
5
6
  <uses-sdk android:minSdkVersion="26" />
6
7
 
8
+ <application>
9
+
10
+ <!-- Replace dashx-android's FCM service with our subclass that also emits to JS. -->
11
+ <service
12
+ android:name="com.dashx.android.DashXFirebaseMessagingService"
13
+ tools:node="remove" />
14
+ <service
15
+ android:name="com.dashx.rn.sdk.DashXReactNativeFirebaseMessagingService"
16
+ android:exported="false" >
17
+ <intent-filter>
18
+ <action android:name="com.google.firebase.MESSAGING_EVENT" />
19
+ </intent-filter>
20
+ </service>
21
+ </application>
22
+
7
23
  </manifest>
@@ -1,7 +1,33 @@
1
1
  1<?xml version="1.0" encoding="utf-8"?>
2
2
  2<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
- 3 package="com.dashx.rn.sdk" >
4
- 4
5
- 5 <uses-sdk android:minSdkVersion="26" />
6
- 6
7
- 7</manifest>
3
+ 3 xmlns:tools="http://schemas.android.com/tools"
4
+ 4 package="com.dashx.rn.sdk" >
5
+ 5
6
+ 6 <uses-sdk android:minSdkVersion="26" />
7
+ 7
8
+ 8 <application>
9
+ 8-->/Users/gulshan/Work/dashx-demo-rn/node_modules/@dashx/react-native/android/src/main/AndroidManifest.xml:3:5-15:19
10
+ 9
11
+ 10 <!-- Replace dashx-android's FCM service with our subclass that also emits to JS. -->
12
+ 11 <service
13
+ 11-->/Users/gulshan/Work/dashx-demo-rn/node_modules/@dashx/react-native/android/src/main/AndroidManifest.xml:5:9-7:35
14
+ 12 android:name="com.dashx.android.DashXFirebaseMessagingService"
15
+ 12-->/Users/gulshan/Work/dashx-demo-rn/node_modules/@dashx/react-native/android/src/main/AndroidManifest.xml:6:13-75
16
+ 13 tools:node="remove" />
17
+ 13-->/Users/gulshan/Work/dashx-demo-rn/node_modules/@dashx/react-native/android/src/main/AndroidManifest.xml:7:13-32
18
+ 14 <service
19
+ 14-->/Users/gulshan/Work/dashx-demo-rn/node_modules/@dashx/react-native/android/src/main/AndroidManifest.xml:8:9-14:19
20
+ 15 android:name="com.dashx.rn.sdk.DashXReactNativeFirebaseMessagingService"
21
+ 15-->/Users/gulshan/Work/dashx-demo-rn/node_modules/@dashx/react-native/android/src/main/AndroidManifest.xml:9:13-85
22
+ 16 android:exported="false" >
23
+ 16-->/Users/gulshan/Work/dashx-demo-rn/node_modules/@dashx/react-native/android/src/main/AndroidManifest.xml:10:13-37
24
+ 17 <intent-filter>
25
+ 17-->/Users/gulshan/Work/dashx-demo-rn/node_modules/@dashx/react-native/android/src/main/AndroidManifest.xml:11:13-13:29
26
+ 18 <action android:name="com.google.firebase.MESSAGING_EVENT" />
27
+ 18-->/Users/gulshan/Work/dashx-demo-rn/node_modules/@dashx/react-native/android/src/main/AndroidManifest.xml:12:17-78
28
+ 18-->/Users/gulshan/Work/dashx-demo-rn/node_modules/@dashx/react-native/android/src/main/AndroidManifest.xml:12:25-75
29
+ 19 </intent-filter>
30
+ 20 </service>
31
+ 21 </application>
32
+ 22
33
+ 23</manifest>
@@ -1,7 +1,23 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
2
  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
+ xmlns:tools="http://schemas.android.com/tools"
3
4
  package="com.dashx.rn.sdk" >
4
5
 
5
6
  <uses-sdk android:minSdkVersion="26" />
6
7
 
8
+ <application>
9
+
10
+ <!-- Replace dashx-android's FCM service with our subclass that also emits to JS. -->
11
+ <service
12
+ android:name="com.dashx.android.DashXFirebaseMessagingService"
13
+ tools:node="remove" />
14
+ <service
15
+ android:name="com.dashx.rn.sdk.DashXReactNativeFirebaseMessagingService"
16
+ android:exported="false" >
17
+ <intent-filter>
18
+ <action android:name="com.google.firebase.MESSAGING_EVENT" />
19
+ </intent-filter>
20
+ </service>
21
+ </application>
22
+
7
23
  </manifest>