@app-connect/core 1.7.37 → 1.7.38

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 (286) hide show
  1. package/README.md +17 -16
  2. package/dist/connector/developerPortal.d.ts +6 -0
  3. package/{connector → dist/connector}/developerPortal.js +29 -12
  4. package/dist/connector/mock.d.ts +1 -0
  5. package/{connector → dist/connector}/mock.js +33 -17
  6. package/dist/connector/proxy/engine.d.ts +10 -0
  7. package/dist/connector/proxy/engine.js +222 -0
  8. package/dist/connector/proxy/index.d.ts +5 -0
  9. package/dist/connector/proxy/index.js +511 -0
  10. package/dist/connector/registry.d.ts +1 -0
  11. package/dist/connector/registry.js +243 -0
  12. package/dist/handlers/admin.d.ts +1 -0
  13. package/{handlers → dist/handlers}/admin.js +137 -78
  14. package/dist/handlers/appointment.d.ts +9 -0
  15. package/{handlers → dist/handlers}/appointment.js +58 -29
  16. package/dist/handlers/auth.d.ts +9 -0
  17. package/{handlers → dist/handlers}/auth.js +68 -40
  18. package/dist/handlers/calldown.d.ts +10 -0
  19. package/dist/handlers/calldown.js +134 -0
  20. package/dist/handlers/contact.d.ts +1 -0
  21. package/{handlers → dist/handlers}/contact.js +61 -39
  22. package/dist/handlers/disposition.d.ts +1 -0
  23. package/{handlers → dist/handlers}/disposition.js +20 -10
  24. package/dist/handlers/log.d.ts +1 -0
  25. package/{handlers → dist/handlers}/log.js +91 -124
  26. package/dist/handlers/managedAuth.d.ts +1 -0
  27. package/{handlers → dist/handlers}/managedAuth.js +134 -61
  28. package/dist/handlers/managedOAuth.d.ts +13 -0
  29. package/{handlers → dist/handlers}/managedOAuth.js +102 -30
  30. package/dist/handlers/plugin.d.ts +1 -0
  31. package/{handlers → dist/handlers}/plugin.js +59 -27
  32. package/dist/handlers/user.d.ts +1 -0
  33. package/{handlers → dist/handlers}/user.js +45 -27
  34. package/dist/index.d.ts +1 -0
  35. package/{index.js → dist/index.js} +538 -449
  36. package/dist/jest.config.d.ts +1 -0
  37. package/dist/jest.config.js +65 -0
  38. package/dist/lib/analytics.d.ts +4 -0
  39. package/{lib → dist/lib}/analytics.js +8 -6
  40. package/dist/lib/authSession.d.ts +5 -0
  41. package/{lib → dist/lib}/authSession.js +15 -43
  42. package/dist/lib/cacheCleanup.d.ts +4 -0
  43. package/{lib → dist/lib}/cacheCleanup.js +5 -17
  44. package/dist/lib/callLogComposer.d.ts +109 -0
  45. package/{lib → dist/lib}/callLogComposer.js +157 -197
  46. package/dist/lib/callLogLookup.d.ts +6 -0
  47. package/{lib → dist/lib}/callLogLookup.js +12 -34
  48. package/dist/lib/constants.d.ts +6 -0
  49. package/dist/lib/constants.js +9 -0
  50. package/dist/lib/debugTracer.d.ts +17 -0
  51. package/{lib → dist/lib}/debugTracer.js +7 -83
  52. package/dist/lib/encode.d.ts +3 -0
  53. package/dist/lib/encode.js +50 -0
  54. package/dist/lib/errorHandler.d.ts +7 -0
  55. package/dist/lib/errorHandler.js +161 -0
  56. package/dist/lib/generalErrorMessage.d.ts +7 -0
  57. package/{lib → dist/lib}/generalErrorMessage.js +6 -6
  58. package/dist/lib/jwt.d.ts +4 -0
  59. package/dist/lib/jwt.js +18 -0
  60. package/dist/lib/logger.d.ts +24 -0
  61. package/dist/lib/logger.js +126 -0
  62. package/dist/lib/migrateCallLogsSchema.d.ts +32 -0
  63. package/{lib → dist/lib}/migrateCallLogsSchema.js +75 -160
  64. package/dist/lib/oauth.d.ts +4 -0
  65. package/{lib → dist/lib}/oauth.js +157 -160
  66. package/dist/lib/ringcentral.d.ts +24 -0
  67. package/dist/lib/ringcentral.js +226 -0
  68. package/dist/lib/s3ErrorLogReport.d.ts +4 -0
  69. package/{lib → dist/lib}/s3ErrorLogReport.js +11 -23
  70. package/dist/lib/sharedSMSComposer.d.ts +7 -0
  71. package/{lib → dist/lib}/sharedSMSComposer.js +21 -107
  72. package/dist/lib/util.d.ts +7 -0
  73. package/{lib → dist/lib}/util.js +9 -20
  74. package/dist/mcp/lib/oauthError.d.ts +1 -0
  75. package/dist/mcp/lib/oauthError.js +25 -0
  76. package/dist/mcp/lib/validator.d.ts +1 -0
  77. package/{mcp → dist/mcp}/lib/validator.js +16 -20
  78. package/dist/mcp/lib/widgetSessionToken.d.ts +1 -0
  79. package/dist/mcp/lib/widgetSessionToken.js +46 -0
  80. package/dist/mcp/mcpHandler.d.ts +8 -0
  81. package/{mcp → dist/mcp}/mcpHandler.js +98 -88
  82. package/dist/mcp/tools/cancelAppointment.d.ts +1 -0
  83. package/{mcp → dist/mcp}/tools/cancelAppointment.js +7 -16
  84. package/dist/mcp/tools/checkAuthStatus.d.ts +1 -0
  85. package/{mcp → dist/mcp}/tools/checkAuthStatus.js +21 -14
  86. package/dist/mcp/tools/confirmAppointment.d.ts +1 -0
  87. package/{mcp → dist/mcp}/tools/confirmAppointment.js +7 -16
  88. package/dist/mcp/tools/createAppointment.d.ts +1 -0
  89. package/{mcp → dist/mcp}/tools/createAppointment.js +7 -19
  90. package/dist/mcp/tools/createCallLog.d.ts +1 -0
  91. package/{mcp → dist/mcp}/tools/createCallLog.js +18 -29
  92. package/dist/mcp/tools/createContact.d.ts +1 -0
  93. package/{mcp → dist/mcp}/tools/createContact.js +8 -20
  94. package/dist/mcp/tools/createMessageLog.d.ts +1 -0
  95. package/{mcp → dist/mcp}/tools/createMessageLog.js +14 -26
  96. package/dist/mcp/tools/doAuth.d.ts +1 -0
  97. package/{mcp → dist/mcp}/tools/doAuth.js +17 -13
  98. package/dist/mcp/tools/findContactByName.d.ts +1 -0
  99. package/{mcp → dist/mcp}/tools/findContactByName.js +9 -15
  100. package/dist/mcp/tools/findContactByPhone.d.ts +1 -0
  101. package/{mcp → dist/mcp}/tools/findContactByPhone.js +8 -15
  102. package/dist/mcp/tools/getCallLog.d.ts +1 -0
  103. package/{mcp → dist/mcp}/tools/getCallLog.js +12 -21
  104. package/dist/mcp/tools/getGoogleFilePicker.d.ts +1 -0
  105. package/{mcp → dist/mcp}/tools/getGoogleFilePicker.js +9 -18
  106. package/dist/mcp/tools/getHelp.d.ts +1 -0
  107. package/{mcp → dist/mcp}/tools/getHelp.js +5 -6
  108. package/dist/mcp/tools/getPublicConnectors.d.ts +1 -0
  109. package/{mcp → dist/mcp}/tools/getPublicConnectors.js +19 -18
  110. package/dist/mcp/tools/getSessionInfo.d.ts +1 -0
  111. package/{mcp → dist/mcp}/tools/getSessionInfo.js +10 -16
  112. package/dist/mcp/tools/index.d.ts +8 -0
  113. package/dist/mcp/tools/index.js +50 -0
  114. package/dist/mcp/tools/listAppointments.d.ts +1 -0
  115. package/{mcp → dist/mcp}/tools/listAppointments.js +7 -19
  116. package/dist/mcp/tools/logout.d.ts +1 -0
  117. package/{mcp → dist/mcp}/tools/logout.js +16 -14
  118. package/dist/mcp/tools/rcGetCallLogs.d.ts +1 -0
  119. package/{mcp → dist/mcp}/tools/rcGetCallLogs.js +10 -8
  120. package/dist/mcp/tools/updateAppointment.d.ts +1 -0
  121. package/{mcp → dist/mcp}/tools/updateAppointment.js +17 -22
  122. package/dist/mcp/tools/updateCallLog.d.ts +1 -0
  123. package/{mcp → dist/mcp}/tools/updateCallLog.js +16 -26
  124. package/dist/models/accountDataModel.d.ts +3 -0
  125. package/dist/models/accountDataModel.js +39 -0
  126. package/dist/models/adminConfigModel.d.ts +2 -0
  127. package/dist/models/adminConfigModel.js +39 -0
  128. package/dist/models/cacheModel.d.ts +2 -0
  129. package/{models → dist/models}/cacheModel.js +7 -3
  130. package/dist/models/callDownListModel.d.ts +2 -0
  131. package/{models → dist/models}/callDownListModel.js +8 -4
  132. package/dist/models/callLogModel.d.ts +2 -0
  133. package/dist/models/callLogModel.js +43 -0
  134. package/dist/models/dynamo/connectorSchema.d.ts +2 -0
  135. package/dist/models/dynamo/connectorSchema.js +141 -0
  136. package/dist/models/dynamo/lockSchema.d.ts +2 -0
  137. package/{models → dist/models}/dynamo/lockSchema.js +5 -7
  138. package/dist/models/dynamo/noteCacheSchema.d.ts +2 -0
  139. package/{models → dist/models}/dynamo/noteCacheSchema.js +4 -6
  140. package/dist/models/llmSessionModel.d.ts +2 -0
  141. package/dist/models/llmSessionModel.js +21 -0
  142. package/dist/models/messageLogModel.d.ts +2 -0
  143. package/{models → dist/models}/messageLogModel.js +8 -4
  144. package/dist/models/sequelize.d.ts +2 -0
  145. package/dist/models/sequelize.js +68 -0
  146. package/dist/models/userModel.d.ts +2 -0
  147. package/dist/models/userModel.js +49 -0
  148. package/dist/package.json +100 -0
  149. package/dist/releaseNotes.json +1222 -0
  150. package/dist/tsconfig.json +14 -0
  151. package/dist/types/admin.d.ts +141 -0
  152. package/dist/types/analytics.d.ts +14 -0
  153. package/dist/types/appointment.d.ts +50 -0
  154. package/dist/types/auth.d.ts +137 -0
  155. package/dist/types/authSession.d.ts +35 -0
  156. package/dist/types/cacheCleanup.d.ts +12 -0
  157. package/dist/types/calldown.d.ts +54 -0
  158. package/dist/types/common.d.ts +46 -0
  159. package/dist/types/connector.d.ts +165 -0
  160. package/dist/types/contact.d.ts +125 -0
  161. package/dist/types/errorHandler.d.ts +60 -0
  162. package/dist/types/index.d.ts +76 -0
  163. package/dist/types/json.d.ts +9 -0
  164. package/dist/types/jwt.d.ts +8 -0
  165. package/dist/types/logging.d.ts +224 -0
  166. package/dist/types/managedAuth.d.ts +114 -0
  167. package/dist/types/managedOAuth.d.ts +59 -0
  168. package/dist/types/manifest.d.ts +120 -0
  169. package/dist/types/migration.d.ts +15 -0
  170. package/dist/types/plugin.d.ts +74 -0
  171. package/dist/types/ringcentral.d.ts +61 -0
  172. package/dist/types/s3ErrorLogReport.d.ts +16 -0
  173. package/dist/types/sharedSMSComposer.d.ts +105 -0
  174. package/dist/types/user.d.ts +46 -0
  175. package/dist/types/util.d.ts +7 -0
  176. package/package.json +34 -6
  177. package/releaseNotes.json +8 -0
  178. package/.env.test +0 -5
  179. package/connector/proxy/engine.js +0 -165
  180. package/connector/proxy/index.js +0 -500
  181. package/connector/registry.js +0 -252
  182. package/docs/README.md +0 -50
  183. package/docs/architecture.md +0 -94
  184. package/docs/connectors.md +0 -116
  185. package/docs/handlers.md +0 -128
  186. package/docs/libraries.md +0 -98
  187. package/docs/models.md +0 -146
  188. package/docs/routes.md +0 -119
  189. package/docs/tests.md +0 -73
  190. package/handlers/calldown.js +0 -99
  191. package/jest.config.js +0 -57
  192. package/lib/constants.js +0 -9
  193. package/lib/encode.js +0 -30
  194. package/lib/errorHandler.js +0 -218
  195. package/lib/jwt.js +0 -18
  196. package/lib/logger.js +0 -190
  197. package/lib/ringcentral.js +0 -267
  198. package/mcp/README.md +0 -420
  199. package/mcp/tools/index.js +0 -51
  200. package/mcp/ui/App/App.tsx +0 -358
  201. package/mcp/ui/App/components/AuthInfoForm.tsx +0 -113
  202. package/mcp/ui/App/components/AuthSuccess.tsx +0 -22
  203. package/mcp/ui/App/components/ConnectorList.tsx +0 -82
  204. package/mcp/ui/App/components/DebugPanel.tsx +0 -43
  205. package/mcp/ui/App/components/OAuthConnect.tsx +0 -270
  206. package/mcp/ui/App/lib/callTool.ts +0 -130
  207. package/mcp/ui/App/lib/debugLog.ts +0 -41
  208. package/mcp/ui/App/lib/developerPortal.ts +0 -111
  209. package/mcp/ui/App/main.css +0 -6
  210. package/mcp/ui/App/root.tsx +0 -13
  211. package/mcp/ui/dist/index.html +0 -53
  212. package/mcp/ui/vite.config.ts +0 -16
  213. package/models/accountDataModel.js +0 -34
  214. package/models/adminConfigModel.js +0 -35
  215. package/models/callLogModel.js +0 -39
  216. package/models/dynamo/connectorSchema.js +0 -146
  217. package/models/llmSessionModel.js +0 -17
  218. package/models/sequelize.js +0 -17
  219. package/models/userModel.js +0 -45
  220. package/test/connector/developerPortal.test.js +0 -166
  221. package/test/connector/mock.test.js +0 -131
  222. package/test/connector/proxy/engine.test.js +0 -211
  223. package/test/connector/proxy/index.test.js +0 -525
  224. package/test/connector/proxy/sample.json +0 -162
  225. package/test/connector/registry.test.js +0 -416
  226. package/test/handlers/admin.test.js +0 -960
  227. package/test/handlers/appointment.test.js +0 -260
  228. package/test/handlers/auth.test.js +0 -1096
  229. package/test/handlers/calldown.test.js +0 -310
  230. package/test/handlers/contact.test.js +0 -1014
  231. package/test/handlers/disposition.test.js +0 -396
  232. package/test/handlers/log.test.js +0 -1847
  233. package/test/handlers/managedAuth.test.js +0 -458
  234. package/test/handlers/managedOAuth.test.js +0 -262
  235. package/test/handlers/plugin.test.js +0 -429
  236. package/test/handlers/user.test.js +0 -381
  237. package/test/index.test.js +0 -301
  238. package/test/lib/analytics.test.js +0 -146
  239. package/test/lib/authSession.test.js +0 -173
  240. package/test/lib/cacheCleanup.test.js +0 -127
  241. package/test/lib/callLogComposer.test.js +0 -1231
  242. package/test/lib/debugTracer.test.js +0 -328
  243. package/test/lib/encode.test.js +0 -59
  244. package/test/lib/errorHandler.test.js +0 -246
  245. package/test/lib/generalErrorMessage.test.js +0 -82
  246. package/test/lib/jwt.test.js +0 -176
  247. package/test/lib/logger.test.js +0 -206
  248. package/test/lib/oauth.test.js +0 -359
  249. package/test/lib/ringcentral.test.js +0 -467
  250. package/test/lib/s3ErrorLogReport.test.js +0 -187
  251. package/test/lib/sharedSMSComposer.test.js +0 -1084
  252. package/test/lib/util.test.js +0 -329
  253. package/test/mcp/mcpHandler.test.js +0 -73
  254. package/test/mcp/mcpHandlerMore.test.js +0 -384
  255. package/test/mcp/tools/appointmentTools.test.js +0 -362
  256. package/test/mcp/tools/checkAuthStatus.test.js +0 -83
  257. package/test/mcp/tools/createCallLog.test.js +0 -436
  258. package/test/mcp/tools/createContact.test.js +0 -58
  259. package/test/mcp/tools/createMessageLog.test.js +0 -595
  260. package/test/mcp/tools/doAuth.test.js +0 -113
  261. package/test/mcp/tools/findContactByName.test.js +0 -275
  262. package/test/mcp/tools/findContactByPhone.test.js +0 -296
  263. package/test/mcp/tools/getCallLog.test.js +0 -298
  264. package/test/mcp/tools/getGoogleFilePicker.test.js +0 -281
  265. package/test/mcp/tools/getPublicConnectors.test.js +0 -107
  266. package/test/mcp/tools/getSessionInfo.test.js +0 -127
  267. package/test/mcp/tools/logout.test.js +0 -233
  268. package/test/mcp/tools/rcGetCallLogs.test.js +0 -56
  269. package/test/mcp/tools/updateCallLog.test.js +0 -360
  270. package/test/models/accountDataModel.test.js +0 -98
  271. package/test/models/callDownListModel.test.js +0 -125
  272. package/test/models/dynamo/connectorSchema.test.js +0 -189
  273. package/test/models/dynamo/lockSchema.test.js +0 -37
  274. package/test/models/dynamo/noteCacheSchema.test.js +0 -45
  275. package/test/models/llmSessionModel.test.js +0 -91
  276. package/test/models/models.test.js +0 -660
  277. package/test/routes/calldownRoutes.test.js +0 -224
  278. package/test/routes/coreRouterBroadRoutes.test.js +0 -855
  279. package/test/routes/dispositionRoutes.test.js +0 -192
  280. package/test/routes/managedAuthRoutes.test.js +0 -386
  281. package/test/routes/pluginRoutes.test.js +0 -262
  282. package/test/setup.js +0 -178
  283. /package/{mcp → dist/mcp}/ui/index.html +0 -0
  284. /package/{mcp → dist/mcp}/ui/package-lock.json +0 -0
  285. /package/{mcp → dist/mcp}/ui/package.json +0 -0
  286. /package/{mcp → dist/mcp}/ui/tsconfig.json +0 -0
@@ -1,1014 +0,0 @@
1
- // Use in-memory SQLite for isolated model tests
2
- jest.mock('../../models/sequelize', () => {
3
- const { Sequelize } = require('sequelize');
4
- return {
5
- sequelize: new Sequelize({
6
- dialect: 'sqlite',
7
- storage: ':memory:',
8
- logging: false,
9
- }),
10
- };
11
- });
12
-
13
- jest.mock('../../connector/registry');
14
- jest.mock('../../lib/oauth');
15
- jest.mock('../../models/dynamo/connectorSchema', () => ({
16
- Connector: {
17
- getProxyConfig: jest.fn()
18
- }
19
- }));
20
-
21
- const contactHandler = require('../../handlers/contact');
22
- const { UserModel } = require('../../models/userModel');
23
- const { AccountDataModel } = require('../../models/accountDataModel');
24
- const connectorRegistry = require('../../connector/registry');
25
- const oauth = require('../../lib/oauth');
26
- const { Connector } = require('../../models/dynamo/connectorSchema');
27
- const { sequelize } = require('../../models/sequelize');
28
-
29
- describe('Contact Handler', () => {
30
- beforeAll(async () => {
31
- await UserModel.sync({ force: true });
32
- await AccountDataModel.sync({ force: true });
33
- });
34
-
35
- afterEach(async () => {
36
- await UserModel.destroy({ where: {} });
37
- await AccountDataModel.destroy({ where: {} });
38
- jest.clearAllMocks();
39
- });
40
-
41
- afterAll(async () => {
42
- await sequelize.close();
43
- });
44
-
45
- describe('findContact', () => {
46
- const mockUser = {
47
- id: 'test-user-id',
48
- platform: 'testCRM',
49
- accessToken: 'test-access-token',
50
- rcAccountId: 'rc-account-123',
51
- platformAdditionalInfo: {}
52
- };
53
-
54
- test('should return warning when user not found', async () => {
55
- // Act
56
- const result = await contactHandler.findContact({
57
- platform: 'testCRM',
58
- userId: 'non-existent-user',
59
- phoneNumber: '+1234567890'
60
- });
61
-
62
- // Assert
63
- expect(result.successful).toBe(false);
64
- expect(result.returnMessage.message).toBe('Contact not found');
65
- expect(result.returnMessage.messageType).toBe('warning');
66
- });
67
-
68
- test('should return warning when user has no access token', async () => {
69
- // Arrange
70
- await UserModel.create({
71
- id: 'test-user-id',
72
- platform: 'testCRM',
73
- accessToken: null
74
- });
75
-
76
- // Act
77
- const result = await contactHandler.findContact({
78
- platform: 'testCRM',
79
- userId: 'test-user-id',
80
- phoneNumber: '+1234567890'
81
- });
82
-
83
- // Assert
84
- expect(result.successful).toBe(false);
85
- expect(result.returnMessage.message).toBe('Contact not found');
86
- });
87
-
88
- test('should return cached contact when available', async () => {
89
- // Arrange
90
- await UserModel.create(mockUser);
91
-
92
- const cachedContact = [
93
- { id: 'contact-1', name: 'Cached Contact', type: 'Contact', phone: '+1234567890' }
94
- ];
95
- await AccountDataModel.create({
96
- rcAccountId: 'rc-account-123',
97
- platformName: 'testCRM',
98
- dataKey: 'contact-+1234567890',
99
- data: cachedContact
100
- });
101
-
102
- // Act
103
- const result = await contactHandler.findContact({
104
- platform: 'testCRM',
105
- userId: 'test-user-id',
106
- phoneNumber: '+1234567890',
107
- isForceRefreshAccountData: false
108
- });
109
-
110
- // Assert
111
- expect(result.successful).toBe(true);
112
- expect(result.contact).toEqual(cachedContact);
113
- // Should not call platform module
114
- expect(connectorRegistry.getConnector).not.toHaveBeenCalled();
115
- });
116
-
117
- test('should bypass cache when isForceRefreshAccountData is true', async () => {
118
- // Arrange
119
- await UserModel.create(mockUser);
120
-
121
- const cachedContact = [
122
- { id: 'contact-1', name: 'Cached Contact', type: 'Contact', phone: '+1234567890' }
123
- ];
124
- await AccountDataModel.create({
125
- rcAccountId: 'rc-account-123',
126
- platformName: 'testCRM',
127
- dataKey: 'contact-+1234567890',
128
- data: cachedContact
129
- });
130
-
131
- const freshContact = [
132
- { id: 'contact-1', name: 'Fresh Contact', type: 'Contact', phone: '+1234567890' }
133
- ];
134
-
135
- const mockConnector = {
136
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
137
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
138
- findContact: jest.fn().mockResolvedValue({
139
- successful: true,
140
- matchedContactInfo: freshContact
141
- })
142
- };
143
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
144
-
145
- // Act
146
- const result = await contactHandler.findContact({
147
- platform: 'testCRM',
148
- userId: 'test-user-id',
149
- phoneNumber: '+1234567890',
150
- isForceRefreshAccountData: true
151
- });
152
-
153
- // Assert
154
- expect(result.successful).toBe(true);
155
- expect(result.contact).toEqual(freshContact);
156
- expect(mockConnector.findContact).toHaveBeenCalled();
157
- });
158
-
159
- test('should find contact with apiKey auth and cache result', async () => {
160
- // Arrange
161
- await UserModel.create(mockUser);
162
-
163
- const matchedContact = [
164
- { id: 'contact-new', name: 'New Contact', type: 'Contact', phone: '+9876543210' }
165
- ];
166
-
167
- const mockConnector = {
168
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
169
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
170
- findContact: jest.fn().mockResolvedValue({
171
- successful: true,
172
- matchedContactInfo: matchedContact
173
- })
174
- };
175
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
176
-
177
- // Act
178
- const result = await contactHandler.findContact({
179
- platform: 'testCRM',
180
- userId: 'test-user-id',
181
- phoneNumber: '+9876543210'
182
- });
183
-
184
- // Assert
185
- expect(result.successful).toBe(true);
186
- expect(result.contact).toEqual(matchedContact);
187
- expect(mockConnector.getBasicAuth).toHaveBeenCalledWith({ apiKey: 'test-access-token' });
188
-
189
- // Verify contact was cached
190
- const cachedData = await AccountDataModel.findOne({
191
- where: {
192
- rcAccountId: 'rc-account-123',
193
- platformName: 'testCRM',
194
- dataKey: 'contact-+9876543210'
195
- }
196
- });
197
- expect(cachedData).not.toBeNull();
198
- expect(cachedData.data).toEqual(matchedContact);
199
- });
200
-
201
- test('should find contact with oauth auth', async () => {
202
- // Arrange
203
- await UserModel.create(mockUser);
204
-
205
- const matchedContact = [
206
- { id: 'oauth-contact', name: 'OAuth Contact', type: 'Lead' }
207
- ];
208
-
209
- const mockConnector = {
210
- getAuthType: jest.fn().mockResolvedValue('oauth'),
211
- getOauthInfo: jest.fn().mockResolvedValue({
212
- clientId: 'client-id',
213
- clientSecret: 'client-secret',
214
- accessTokenUri: 'https://token.url',
215
- authorizationUri: 'https://auth.url'
216
- }),
217
- findContact: jest.fn().mockResolvedValue({
218
- successful: true,
219
- matchedContactInfo: matchedContact
220
- })
221
- };
222
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
223
-
224
- const mockOAuthApp = {};
225
- oauth.getOAuthApp.mockReturnValue(mockOAuthApp);
226
- oauth.checkAndRefreshAccessToken.mockResolvedValue({
227
- ...mockUser,
228
- accessToken: 'refreshed-token'
229
- });
230
-
231
- // Act
232
- const result = await contactHandler.findContact({
233
- platform: 'testCRM',
234
- userId: 'test-user-id',
235
- phoneNumber: '+1111111111'
236
- });
237
-
238
- // Assert
239
- expect(result.successful).toBe(true);
240
- expect(oauth.checkAndRefreshAccessToken).toHaveBeenCalled();
241
- });
242
-
243
- test('should use proxy config when proxyId is present', async () => {
244
- // Arrange
245
- const userWithProxy = {
246
- ...mockUser,
247
- platformAdditionalInfo: { proxyId: 'proxy-123' }
248
- };
249
- await UserModel.create(userWithProxy);
250
-
251
- const proxyConfig = { baseUrl: 'https://proxy.example.com' };
252
- Connector.getProxyConfig.mockResolvedValue(proxyConfig);
253
-
254
- const matchedContact = [{ id: 'proxy-contact', name: 'Proxy Contact' }];
255
-
256
- const mockConnector = {
257
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
258
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
259
- findContact: jest.fn().mockResolvedValue({
260
- successful: true,
261
- matchedContactInfo: matchedContact
262
- })
263
- };
264
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
265
-
266
- // Act
267
- const result = await contactHandler.findContact({
268
- platform: 'testCRM',
269
- userId: 'test-user-id',
270
- phoneNumber: '+2222222222'
271
- });
272
-
273
- // Assert
274
- expect(result.successful).toBe(true);
275
- expect(Connector.getProxyConfig).toHaveBeenCalledWith('proxy-123');
276
- expect(mockConnector.findContact).toHaveBeenCalledWith(
277
- expect.objectContaining({ proxyConfig })
278
- );
279
- });
280
-
281
- test('should return warning when no contacts found', async () => {
282
- // Arrange
283
- await UserModel.create(mockUser);
284
-
285
- const mockConnector = {
286
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
287
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
288
- findContact: jest.fn().mockResolvedValue({
289
- successful: false,
290
- matchedContactInfo: null
291
- })
292
- };
293
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
294
-
295
- // Act
296
- const result = await contactHandler.findContact({
297
- platform: 'testCRM',
298
- userId: 'test-user-id',
299
- phoneNumber: '+9999999999'
300
- });
301
-
302
- // Assert
303
- expect(result.successful).toBe(false);
304
- expect(result.returnMessage.message).toBe('Contact not found');
305
- expect(result.returnMessage.details[0].items[0].text).toContain('+9999999999');
306
- });
307
-
308
- test('should return platform returnMessage when provided', async () => {
309
- // Arrange
310
- await UserModel.create(mockUser);
311
-
312
- const customReturnMessage = {
313
- message: 'Custom platform message',
314
- messageType: 'info',
315
- ttl: 5000
316
- };
317
-
318
- const mockConnector = {
319
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
320
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
321
- findContact: jest.fn().mockResolvedValue({
322
- successful: false,
323
- matchedContactInfo: null,
324
- returnMessage: customReturnMessage
325
- })
326
- };
327
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
328
-
329
- // Act
330
- const result = await contactHandler.findContact({
331
- platform: 'testCRM',
332
- userId: 'test-user-id',
333
- phoneNumber: '+8888888888'
334
- });
335
-
336
- // Assert
337
- expect(result.returnMessage).toEqual(customReturnMessage);
338
- });
339
-
340
- test('should handle 429 rate limit error', async () => {
341
- // Arrange
342
- await UserModel.create(mockUser);
343
-
344
- const mockConnector = {
345
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
346
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
347
- findContact: jest.fn().mockRejectedValue({
348
- response: { status: 429 }
349
- })
350
- };
351
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
352
-
353
- // Act
354
- const result = await contactHandler.findContact({
355
- platform: 'testCRM',
356
- userId: 'test-user-id',
357
- phoneNumber: '+7777777777'
358
- });
359
-
360
- // Assert
361
- expect(result.successful).toBe(false);
362
- expect(result.extraDataTracking.statusCode).toBe(429);
363
- });
364
-
365
- test('should handle 401 authorization error', async () => {
366
- // Arrange
367
- await UserModel.create(mockUser);
368
-
369
- const mockConnector = {
370
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
371
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
372
- findContact: jest.fn().mockRejectedValue({
373
- response: { status: 401 }
374
- })
375
- };
376
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
377
-
378
- // Act
379
- const result = await contactHandler.findContact({
380
- platform: 'testCRM',
381
- userId: 'test-user-id',
382
- phoneNumber: '+6666666666'
383
- });
384
-
385
- // Assert
386
- expect(result.successful).toBe(false);
387
- expect(result.extraDataTracking.statusCode).toBe(401);
388
- });
389
-
390
- test('should update existing cached contact', async () => {
391
- // Arrange
392
- await UserModel.create(mockUser);
393
-
394
- // Create existing cached contact
395
- await AccountDataModel.create({
396
- rcAccountId: 'rc-account-123',
397
- platformName: 'testCRM',
398
- dataKey: 'contact-+5555555555',
399
- data: [{ id: 'old-contact', name: 'Old Name' }]
400
- });
401
-
402
- const updatedContact = [
403
- { id: 'old-contact', name: 'Updated Name', type: 'Contact' }
404
- ];
405
-
406
- const mockConnector = {
407
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
408
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
409
- findContact: jest.fn().mockResolvedValue({
410
- successful: true,
411
- matchedContactInfo: updatedContact
412
- })
413
- };
414
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
415
-
416
- // Act
417
- const result = await contactHandler.findContact({
418
- platform: 'testCRM',
419
- userId: 'test-user-id',
420
- phoneNumber: '+5555555555',
421
- isForceRefreshAccountData: true
422
- });
423
-
424
- // Assert
425
- expect(result.successful).toBe(true);
426
- expect(result.contact).toEqual(updatedContact);
427
-
428
- // Verify cache was updated
429
- const cachedData = await AccountDataModel.findOne({
430
- where: {
431
- rcAccountId: 'rc-account-123',
432
- platformName: 'testCRM',
433
- dataKey: 'contact-+5555555555'
434
- }
435
- });
436
- expect(cachedData.data).toEqual(updatedContact);
437
- });
438
-
439
- test('should remove cached contact when force refresh returns null', async () => {
440
- // Arrange
441
- await UserModel.create(mockUser);
442
- await AccountDataModel.create({
443
- rcAccountId: 'rc-account-123',
444
- platformName: 'testCRM',
445
- dataKey: 'contact-+3333333333',
446
- data: [{ id: 'stale-contact', name: 'Stale Contact' }]
447
- });
448
-
449
- const mockConnector = {
450
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
451
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
452
- findContact: jest.fn().mockResolvedValue({
453
- successful: false,
454
- matchedContactInfo: null
455
- })
456
- };
457
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
458
-
459
- // Act
460
- const result = await contactHandler.findContact({
461
- platform: 'testCRM',
462
- userId: 'test-user-id',
463
- phoneNumber: '+3333333333',
464
- isForceRefreshAccountData: true
465
- });
466
-
467
- // Assert
468
- expect(result.successful).toBe(false);
469
- const cachedData = await AccountDataModel.findOne({
470
- where: {
471
- rcAccountId: 'rc-account-123',
472
- platformName: 'testCRM',
473
- dataKey: 'contact-+3333333333'
474
- }
475
- });
476
- expect(cachedData).toBeNull();
477
- });
478
-
479
- test('should remove cached contact when force refresh returns empty array', async () => {
480
- // Arrange
481
- await UserModel.create(mockUser);
482
- await AccountDataModel.create({
483
- rcAccountId: 'rc-account-123',
484
- platformName: 'testCRM',
485
- dataKey: 'contact-+1212121212',
486
- data: [{ id: 'stale-contact', name: 'Stale Contact' }]
487
- });
488
-
489
- const mockConnector = {
490
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
491
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
492
- findContact: jest.fn().mockResolvedValue({
493
- successful: false,
494
- matchedContactInfo: []
495
- })
496
- };
497
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
498
-
499
- // Act
500
- await contactHandler.findContact({
501
- platform: 'testCRM',
502
- userId: 'test-user-id',
503
- phoneNumber: '+1212121212',
504
- isForceRefreshAccountData: true
505
- });
506
-
507
- // Assert
508
- const cachedData = await AccountDataModel.findOne({
509
- where: {
510
- rcAccountId: 'rc-account-123',
511
- platformName: 'testCRM',
512
- dataKey: 'contact-+1212121212'
513
- }
514
- });
515
- expect(cachedData).toBeNull();
516
- });
517
-
518
- test('should remove cached contact when force refresh returns only new contact placeholder', async () => {
519
- // Arrange
520
- await UserModel.create(mockUser);
521
- await AccountDataModel.create({
522
- rcAccountId: 'rc-account-123',
523
- platformName: 'testCRM',
524
- dataKey: 'contact-+3434343434',
525
- data: [{ id: 'stale-contact', name: 'Stale Contact' }]
526
- });
527
-
528
- const placeholderContact = [
529
- { id: 'new-contact', name: 'Create Contact', isNewContact: true }
530
- ];
531
- const mockConnector = {
532
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
533
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
534
- findContact: jest.fn().mockResolvedValue({
535
- successful: false,
536
- matchedContactInfo: placeholderContact
537
- })
538
- };
539
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
540
-
541
- // Act
542
- const result = await contactHandler.findContact({
543
- platform: 'testCRM',
544
- userId: 'test-user-id',
545
- phoneNumber: '+3434343434',
546
- isForceRefreshAccountData: true
547
- });
548
-
549
- // Assert
550
- expect(result.contact).toEqual(placeholderContact);
551
- const cachedData = await AccountDataModel.findOne({
552
- where: {
553
- rcAccountId: 'rc-account-123',
554
- platformName: 'testCRM',
555
- dataKey: 'contact-+3434343434'
556
- }
557
- });
558
- expect(cachedData).toBeNull();
559
- });
560
-
561
- test('should keep cached contact when force refresh connector call errors', async () => {
562
- // Arrange
563
- await UserModel.create(mockUser);
564
- await AccountDataModel.create({
565
- rcAccountId: 'rc-account-123',
566
- platformName: 'testCRM',
567
- dataKey: 'contact-+5656565656',
568
- data: [{ id: 'stale-contact', name: 'Stale Contact' }]
569
- });
570
-
571
- const mockConnector = {
572
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
573
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
574
- findContact: jest.fn().mockRejectedValue({
575
- response: { status: 500 }
576
- })
577
- };
578
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
579
-
580
- // Act
581
- const result = await contactHandler.findContact({
582
- platform: 'testCRM',
583
- userId: 'test-user-id',
584
- phoneNumber: '+5656565656',
585
- isForceRefreshAccountData: true
586
- });
587
-
588
- // Assert
589
- expect(result.successful).toBe(false);
590
- const cachedData = await AccountDataModel.findOne({
591
- where: {
592
- rcAccountId: 'rc-account-123',
593
- platformName: 'testCRM',
594
- dataKey: 'contact-+5656565656'
595
- }
596
- });
597
- expect(cachedData).not.toBeNull();
598
- expect(cachedData.data).toEqual([{ id: 'stale-contact', name: 'Stale Contact' }]);
599
- });
600
-
601
- test('should work with tracer when provided', async () => {
602
- // Arrange
603
- await UserModel.create(mockUser);
604
-
605
- const mockTracer = {
606
- trace: jest.fn(),
607
- traceError: jest.fn()
608
- };
609
-
610
- const matchedContact = [{ id: 'traced-contact', name: 'Traced Contact' }];
611
-
612
- const mockConnector = {
613
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
614
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
615
- findContact: jest.fn().mockResolvedValue({
616
- successful: true,
617
- matchedContactInfo: matchedContact
618
- })
619
- };
620
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
621
-
622
- // Act
623
- const result = await contactHandler.findContact({
624
- platform: 'testCRM',
625
- userId: 'test-user-id',
626
- phoneNumber: '+4444444444',
627
- tracer: mockTracer
628
- });
629
-
630
- // Assert
631
- expect(result.successful).toBe(true);
632
- expect(mockTracer.trace).toHaveBeenCalled();
633
- });
634
- });
635
-
636
- describe('createContact', () => {
637
- const mockUser = {
638
- id: 'test-user-id',
639
- platform: 'testCRM',
640
- accessToken: 'test-access-token',
641
- platformAdditionalInfo: {}
642
- };
643
-
644
- test('should return error when user not found', async () => {
645
- // Act
646
- const result = await contactHandler.createContact({
647
- platform: 'testCRM',
648
- userId: 'non-existent-user',
649
- phoneNumber: '+1234567890',
650
- newContactName: 'New Contact',
651
- newContactType: 'Contact'
652
- });
653
-
654
- // Assert
655
- expect(result.successful).toBe(false);
656
- expect(result.message).toBe('Contact not found');
657
- });
658
-
659
- test('should return error when user has no access token', async () => {
660
- // Arrange
661
- await UserModel.create({
662
- id: 'test-user-id',
663
- platform: 'testCRM',
664
- accessToken: null
665
- });
666
-
667
- // Act
668
- const result = await contactHandler.createContact({
669
- platform: 'testCRM',
670
- userId: 'test-user-id',
671
- phoneNumber: '+1234567890',
672
- newContactName: 'New Contact',
673
- newContactType: 'Contact'
674
- });
675
-
676
- // Assert
677
- expect(result.successful).toBe(false);
678
- });
679
-
680
- test('should successfully create contact with apiKey auth', async () => {
681
- // Arrange
682
- await UserModel.create(mockUser);
683
-
684
- const createdContact = {
685
- id: 'new-contact-123',
686
- name: 'New Contact',
687
- type: 'Contact',
688
- phone: '+1234567890'
689
- };
690
-
691
- const mockConnector = {
692
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
693
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
694
- createContact: jest.fn().mockResolvedValue({
695
- contactInfo: createdContact,
696
- returnMessage: { message: 'Contact created', messageType: 'success', ttl: 2000 }
697
- })
698
- };
699
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
700
-
701
- // Act
702
- const result = await contactHandler.createContact({
703
- platform: 'testCRM',
704
- userId: 'test-user-id',
705
- phoneNumber: '+1234567890',
706
- newContactName: 'New Contact',
707
- newContactType: 'Contact',
708
- additionalSubmission: {}
709
- });
710
-
711
- // Assert
712
- expect(result.successful).toBe(true);
713
- expect(result.contact).toEqual(createdContact);
714
- expect(mockConnector.createContact).toHaveBeenCalledWith({
715
- user: expect.any(Object),
716
- authHeader: 'Basic base64-encoded',
717
- phoneNumber: '+1234567890',
718
- newContactName: 'New Contact',
719
- newContactType: 'Contact',
720
- additionalSubmission: {},
721
- proxyConfig: null
722
- });
723
- });
724
-
725
- test('should successfully create contact with oauth auth', async () => {
726
- // Arrange
727
- await UserModel.create(mockUser);
728
-
729
- const createdContact = {
730
- id: 'oauth-contact-123',
731
- name: 'OAuth Contact'
732
- };
733
-
734
- const mockConnector = {
735
- getAuthType: jest.fn().mockResolvedValue('oauth'),
736
- getOauthInfo: jest.fn().mockResolvedValue({
737
- clientId: 'client-id',
738
- clientSecret: 'client-secret',
739
- accessTokenUri: 'https://token.url',
740
- authorizationUri: 'https://auth.url'
741
- }),
742
- createContact: jest.fn().mockResolvedValue({
743
- contactInfo: createdContact,
744
- returnMessage: { message: 'Created', messageType: 'success' }
745
- })
746
- };
747
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
748
-
749
- oauth.getOAuthApp.mockReturnValue({});
750
- oauth.checkAndRefreshAccessToken.mockResolvedValue({
751
- ...mockUser,
752
- accessToken: 'refreshed-token'
753
- });
754
-
755
- // Act
756
- const result = await contactHandler.createContact({
757
- platform: 'testCRM',
758
- userId: 'test-user-id',
759
- phoneNumber: '+1234567890',
760
- newContactName: 'OAuth Contact',
761
- newContactType: 'Lead'
762
- });
763
-
764
- // Assert
765
- expect(result.successful).toBe(true);
766
- expect(result.contact).toEqual(createdContact);
767
- expect(oauth.checkAndRefreshAccessToken).toHaveBeenCalled();
768
- });
769
-
770
- test('should return unsuccessful when platform returns null contactInfo', async () => {
771
- // Arrange
772
- await UserModel.create(mockUser);
773
-
774
- const mockConnector = {
775
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
776
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
777
- createContact: jest.fn().mockResolvedValue({
778
- contactInfo: null,
779
- returnMessage: { message: 'Failed to create', messageType: 'error' }
780
- })
781
- };
782
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
783
-
784
- // Act
785
- const result = await contactHandler.createContact({
786
- platform: 'testCRM',
787
- userId: 'test-user-id',
788
- phoneNumber: '+1234567890',
789
- newContactName: 'Failed Contact',
790
- newContactType: 'Contact'
791
- });
792
-
793
- // Assert
794
- expect(result.successful).toBe(false);
795
- expect(result.returnMessage.message).toBe('Failed to create');
796
- });
797
-
798
- test('should handle 429 rate limit error', async () => {
799
- // Arrange
800
- await UserModel.create(mockUser);
801
-
802
- const mockConnector = {
803
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
804
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
805
- createContact: jest.fn().mockRejectedValue({
806
- response: { status: 429 }
807
- })
808
- };
809
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
810
-
811
- // Act
812
- const result = await contactHandler.createContact({
813
- platform: 'testCRM',
814
- userId: 'test-user-id',
815
- phoneNumber: '+1234567890',
816
- newContactName: 'Rate Limited',
817
- newContactType: 'Contact'
818
- });
819
-
820
- // Assert
821
- expect(result.successful).toBe(false);
822
- });
823
-
824
- test('should handle 401 authorization error', async () => {
825
- // Arrange
826
- await UserModel.create(mockUser);
827
-
828
- const mockConnector = {
829
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
830
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
831
- createContact: jest.fn().mockRejectedValue({
832
- response: { status: 401 }
833
- })
834
- };
835
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
836
-
837
- // Act
838
- const result = await contactHandler.createContact({
839
- platform: 'testCRM',
840
- userId: 'test-user-id',
841
- phoneNumber: '+1234567890',
842
- newContactName: 'Unauthorized',
843
- newContactType: 'Contact'
844
- });
845
-
846
- // Assert
847
- expect(result.successful).toBe(false);
848
- expect(result.extraDataTracking.statusCode).toBe(401);
849
- });
850
-
851
- test('should handle generic errors', async () => {
852
- // Arrange
853
- await UserModel.create(mockUser);
854
-
855
- const mockConnector = {
856
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
857
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
858
- createContact: jest.fn().mockRejectedValue(new Error('Unknown error'))
859
- };
860
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
861
-
862
- // Act
863
- const result = await contactHandler.createContact({
864
- platform: 'testCRM',
865
- userId: 'test-user-id',
866
- phoneNumber: '+1234567890',
867
- newContactName: 'Error Contact',
868
- newContactType: 'Contact'
869
- });
870
-
871
- // Assert
872
- expect(result.successful).toBe(false);
873
- expect(result.returnMessage.message).toBe('Error creating contact');
874
- });
875
- });
876
-
877
- describe('findContactWithName', () => {
878
- const mockUser = {
879
- id: 'test-user-id',
880
- platform: 'testCRM',
881
- accessToken: 'test-access-token',
882
- platformAdditionalInfo: {}
883
- };
884
-
885
- test('should return warning when user not found', async () => {
886
- // Act
887
- const result = await contactHandler.findContactWithName({
888
- platform: 'testCRM',
889
- userId: 'non-existent-user',
890
- name: 'John Doe'
891
- });
892
-
893
- // Assert
894
- expect(result.successful).toBe(false);
895
- expect(result.returnMessage.message).toContain('No contact found with name');
896
- });
897
-
898
- test('should find contact by name with apiKey auth', async () => {
899
- // Arrange
900
- await UserModel.create(mockUser);
901
-
902
- const matchedContacts = [
903
- { id: 'contact-1', name: 'John Doe', type: 'Contact' }
904
- ];
905
-
906
- const mockConnector = {
907
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
908
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
909
- findContactWithName: jest.fn().mockResolvedValue({
910
- successful: true,
911
- matchedContactInfo: matchedContacts
912
- })
913
- };
914
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
915
-
916
- // Act
917
- const result = await contactHandler.findContactWithName({
918
- platform: 'testCRM',
919
- userId: 'test-user-id',
920
- name: 'John Doe'
921
- });
922
-
923
- // Assert
924
- expect(result.successful).toBe(true);
925
- expect(result.contact).toEqual(matchedContacts);
926
- });
927
-
928
- test('should return warning when no contacts found by name', async () => {
929
- // Arrange
930
- await UserModel.create(mockUser);
931
-
932
- const mockConnector = {
933
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
934
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
935
- findContactWithName: jest.fn().mockResolvedValue({
936
- successful: false,
937
- matchedContactInfo: null
938
- })
939
- };
940
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
941
-
942
- // Act
943
- const result = await contactHandler.findContactWithName({
944
- platform: 'testCRM',
945
- userId: 'test-user-id',
946
- name: 'Unknown Person'
947
- });
948
-
949
- // Assert
950
- expect(result.successful).toBe(false);
951
- expect(result.returnMessage.message).toContain('No contact found with name');
952
- });
953
-
954
- test('should handle 429 rate limit error', async () => {
955
- // Arrange
956
- await UserModel.create(mockUser);
957
-
958
- const mockConnector = {
959
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
960
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
961
- findContactWithName: jest.fn().mockRejectedValue({
962
- response: { status: 429 }
963
- })
964
- };
965
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
966
-
967
- // Act
968
- const result = await contactHandler.findContactWithName({
969
- platform: 'testCRM',
970
- userId: 'test-user-id',
971
- name: 'Rate Limited'
972
- });
973
-
974
- // Assert
975
- expect(result.successful).toBe(false);
976
- });
977
-
978
- test('should use proxy config when proxyId is present', async () => {
979
- // Arrange
980
- const userWithProxy = {
981
- ...mockUser,
982
- platformAdditionalInfo: { proxyId: 'proxy-123' }
983
- };
984
- await UserModel.create(userWithProxy);
985
-
986
- const proxyConfig = { baseUrl: 'https://proxy.example.com' };
987
- Connector.getProxyConfig.mockResolvedValue(proxyConfig);
988
-
989
- const matchedContacts = [{ id: 'proxy-contact', name: 'Proxy Contact' }];
990
-
991
- const mockConnector = {
992
- getAuthType: jest.fn().mockResolvedValue('apiKey'),
993
- getBasicAuth: jest.fn().mockReturnValue('base64-encoded'),
994
- findContactWithName: jest.fn().mockResolvedValue({
995
- successful: true,
996
- matchedContactInfo: matchedContacts
997
- })
998
- };
999
- connectorRegistry.getConnector.mockReturnValue(mockConnector);
1000
-
1001
- // Act
1002
- const result = await contactHandler.findContactWithName({
1003
- platform: 'testCRM',
1004
- userId: 'test-user-id',
1005
- name: 'Proxy Contact'
1006
- });
1007
-
1008
- // Assert
1009
- expect(result.successful).toBe(true);
1010
- expect(Connector.getProxyConfig).toHaveBeenCalledWith('proxy-123');
1011
- });
1012
- });
1013
- });
1014
-