1
+ using Moq ;
2
+ using Moq . Protected ;
3
+ using NUnit . Framework ;
4
+ using System ;
5
+ using System . Collections . Generic ;
6
+ using System . Linq ;
7
+ using System . Net ;
8
+ using System . Net . Http ;
9
+ using System . Threading ;
10
+ using System . Threading . Tasks ;
11
+ using Umbraco . Core . Logging ;
12
+ using Umbraco . Forms . Core ;
13
+ using Umbraco . Forms . Core . Persistence . Dtos ;
14
+ using Umbraco . Forms . Core . Providers . Models ;
15
+ using Umbraco . Forms . Integrations . Crm . Hubspot . Models ;
16
+ using Umbraco . Forms . Integrations . Crm . Hubspot . Services ;
17
+
18
+ namespace Umbraco . Forms . Integrations . Crm . Hubspot . Tests
19
+ {
20
+ public class HubspotContactServiceTests
21
+ {
22
+ private const string ApiKey = "test-api-key" ;
23
+ private readonly string s_contactPropertiesResponse = @"{
24
+ ""results"":[
25
+ {
26
+ ""updatedAt"":""2019-10-14T20:45:41.715Z"",
27
+ ""createdAt"":""2019-08-06T02:41:08.029Z"",
28
+ ""name"":""firstname"",
29
+ ""label"":""First Name"",
30
+ ""type"":""string"",
31
+ ""fieldType"":""text"",
32
+ ""description"":""A contact's first name"",
33
+ ""groupName"":""contactinformation"",
34
+ ""options"":[
35
+ ],
36
+ ""displayOrder"":0,
37
+ ""calculated"":false,
38
+ ""externalOptions"":false,
39
+ ""hasUniqueValue"":false,
40
+ ""hidden"":false,
41
+ ""hubspotDefined"":true,
42
+ ""modificationMetadata"":{
43
+ ""archivable"":true,
44
+ ""readOnlyDefinition"":true,
45
+ ""readOnlyValue"":false
46
+ },
47
+ ""formField"":true
48
+ },
49
+ {
50
+ ""updatedAt"":""2019-10-14T20:45:41.796Z"",
51
+ ""createdAt"":""2019-08-06T02:41:08.109Z"",
52
+ ""name"":""lastname"",
53
+ ""label"":""Last Name"",
54
+ ""type"":""string"",
55
+ ""fieldType"":""text"",
56
+ ""description"":""A contact's last name"",
57
+ ""groupName"":""contactinformation"",
58
+ ""options"":[
59
+ ],
60
+ ""displayOrder"":1,
61
+ ""calculated"":false,
62
+ ""externalOptions"":false,
63
+ ""hasUniqueValue"":false,
64
+ ""hidden"":false,
65
+ ""hubspotDefined"":true,
66
+ ""modificationMetadata"":{
67
+ ""archivable"":true,
68
+ ""readOnlyDefinition"":true,
69
+ ""readOnlyValue"":false
70
+ },
71
+ ""formField"":true
72
+ },
73
+ {
74
+ ""updatedAt"":""2019-10-14T20:45:42.027Z"",
75
+ ""createdAt"":""2019-08-06T02:41:08.204Z"",
76
+ ""name"":""email"",
77
+ ""label"":""Email"",
78
+ ""type"":""string"",
79
+ ""fieldType"":""text"",
80
+ ""description"":""A contact's email address"",
81
+ ""groupName"":""contactinformation"",
82
+ ""options"":[
83
+ ],
84
+ ""displayOrder"":3,
85
+ ""calculated"":false,
86
+ ""externalOptions"":false,
87
+ ""hasUniqueValue"":false,
88
+ ""hidden"":false,
89
+ ""hubspotDefined"":true,
90
+ ""modificationMetadata"":{
91
+ ""archivable"":true,
92
+ ""readOnlyDefinition"":true,
93
+ ""readOnlyValue"":false
94
+ },
95
+ ""formField"":true
96
+ }
97
+ ]
98
+ }" ;
99
+
100
+ [ Test ]
101
+ public async Task GetContactProperties_WithoutApiKeyConfigured_ReturnsEmptyCollectionWithLoggedWarning ( )
102
+ {
103
+ Mock < IFacadeConfiguration > mockedConfig = CreateMockedConfiguration ( withApiKey : false ) ;
104
+ var mockedLogger = new Mock < ILogger > ( ) ;
105
+ var sut = new HubspotContactService ( mockedConfig . Object , mockedLogger . Object ) ;
106
+
107
+ var result = await sut . GetContactProperties ( ) ;
108
+
109
+ mockedLogger
110
+ . Verify ( x => x . Warn ( It . Is < Type > ( y => y == typeof ( HubspotContactService ) ) , It . IsAny < string > ( ) ) , Times . Once ) ;
111
+ Assert . IsEmpty ( result ) ;
112
+ }
113
+
114
+ [ Test ]
115
+ public async Task GetContactProperties_WithFailedRequest_ReturnsEmptyCollectionWithLoggedError ( )
116
+ {
117
+ Mock < IFacadeConfiguration > mockedConfig = CreateMockedConfiguration ( ) ;
118
+ var mockedLogger = new Mock < ILogger > ( ) ;
119
+ var sut = new HubspotContactService ( mockedConfig . Object , mockedLogger . Object ) ;
120
+
121
+ var httpClient = CreateMockedHttpClient ( HttpStatusCode . InternalServerError ) ;
122
+ HubspotContactService . ClientFactory = ( ) => httpClient ;
123
+
124
+ var result = await sut . GetContactProperties ( ) ;
125
+
126
+ mockedLogger
127
+ . Verify ( x => x . Error ( It . Is < Type > ( y => y == typeof ( HubspotContactService ) ) , It . IsAny < string > ( ) , It . IsAny < object [ ] > ( ) ) , Times . Once ) ;
128
+ Assert . IsEmpty ( result ) ;
129
+ }
130
+
131
+ [ Test ]
132
+ public async Task GetContactProperties_WithSuccessfulRequest_ReturnsMappedAndOrderedPropertyCollection ( )
133
+ {
134
+ Mock < IFacadeConfiguration > mockedConfig = CreateMockedConfiguration ( ) ;
135
+ var mockedLogger = new Mock < ILogger > ( ) ;
136
+ var sut = new HubspotContactService ( mockedConfig . Object , mockedLogger . Object ) ;
137
+
138
+ var httpClient = CreateMockedHttpClient ( HttpStatusCode . OK , s_contactPropertiesResponse ) ;
139
+ HubspotContactService . ClientFactory = ( ) => httpClient ;
140
+
141
+ var result = await sut . GetContactProperties ( ) ;
142
+
143
+ Assert . AreEqual ( 3 , result . Count ( ) ) ;
144
+ Assert . AreEqual ( "Email,First Name,Last Name" , string . Join ( "," , result . Select ( x => x . Label ) ) ) ;
145
+ Assert . AreEqual ( "email,firstname,lastname" , string . Join ( "," , result . Select ( x => x . Name ) ) ) ;
146
+ }
147
+
148
+ [ Test ]
149
+ public async Task PostContact_WithoutApiKeyConfigured_ReturnsNotConfiguredWithLoggedWarning ( )
150
+ {
151
+ Mock < IFacadeConfiguration > mockedConfig = CreateMockedConfiguration ( withApiKey : false ) ;
152
+ var mockedLogger = new Mock < ILogger > ( ) ;
153
+ var sut = new HubspotContactService ( mockedConfig . Object , mockedLogger . Object ) ;
154
+
155
+ var record = new Record ( ) ;
156
+ var fieldMappings = new List < MappedProperty > ( ) ;
157
+ var result = await sut . PostContact ( record , fieldMappings ) ;
158
+
159
+ mockedLogger
160
+ . Verify ( x => x . Warn ( It . Is < Type > ( y => y == typeof ( HubspotContactService ) ) , It . IsAny < string > ( ) ) , Times . Once ) ;
161
+ Assert . AreEqual ( CommandResult . NotConfigured , result ) ;
162
+ }
163
+
164
+ [ Test ]
165
+ public async Task PostContact_WithFailedRequest_ReturnsFailedWithLoggedError ( )
166
+ {
167
+ Mock < IFacadeConfiguration > mockedConfig = CreateMockedConfiguration ( ) ;
168
+ var mockedLogger = new Mock < ILogger > ( ) ;
169
+ var sut = new HubspotContactService ( mockedConfig . Object , mockedLogger . Object ) ;
170
+
171
+ var httpClient = CreateMockedHttpClient ( HttpStatusCode . InternalServerError ) ;
172
+ HubspotContactService . ClientFactory = ( ) => httpClient ;
173
+
174
+ var record = new Record ( ) ;
175
+ var fieldMappings = new List < MappedProperty > ( ) ;
176
+ var result = await sut . PostContact ( record , fieldMappings ) ;
177
+
178
+ mockedLogger
179
+ . Verify ( x => x . Error ( It . Is < Type > ( y => y == typeof ( HubspotContactService ) ) , It . IsAny < string > ( ) ) , Times . Once ) ;
180
+
181
+ Assert . AreEqual ( CommandResult . Failed , result ) ;
182
+ }
183
+
184
+ [ Test ]
185
+ public async Task PostContact_WithSuccessfulRequest_ReturnSuccess ( )
186
+ {
187
+ Mock < IFacadeConfiguration > mockedConfig = CreateMockedConfiguration ( ) ;
188
+ var mockedLogger = new Mock < ILogger > ( ) ;
189
+ var sut = new HubspotContactService ( mockedConfig . Object , mockedLogger . Object ) ;
190
+
191
+ var httpClient = CreateMockedHttpClient ( HttpStatusCode . OK ) ;
192
+ HubspotContactService . ClientFactory = ( ) => httpClient ;
193
+
194
+ var formFieldId = Guid . NewGuid ( ) ;
195
+ var record = new Record ( ) ;
196
+ record . RecordFields . Add ( formFieldId , new RecordField
197
+ {
198
+ FieldId = formFieldId ,
199
+ Values = new List < object > { "Fred" }
200
+ } ) ;
201
+ var fieldMappings = new List < MappedProperty > ( )
202
+ {
203
+ new MappedProperty
204
+ {
205
+ FormField = formFieldId . ToString ( ) ,
206
+ HubspotField = "firstname"
207
+ }
208
+ } ;
209
+ var result = await sut . PostContact ( record , fieldMappings ) ;
210
+
211
+ mockedLogger
212
+ . Verify ( x => x . Warn ( It . Is < Type > ( y => y == typeof ( HubspotContactService ) ) , It . IsAny < string > ( ) , It . IsAny < object [ ] > ( ) ) , Times . Never ) ;
213
+
214
+ Assert . AreEqual ( CommandResult . Success , result ) ;
215
+ }
216
+
217
+ [ Test ]
218
+ public async Task PostContact_WithSuccessfulRequestAndUnmappedField_ReturnSuccessWithLoggedWarning ( )
219
+ {
220
+ Mock < IFacadeConfiguration > mockedConfig = CreateMockedConfiguration ( ) ;
221
+ var mockedLogger = new Mock < ILogger > ( ) ;
222
+ var sut = new HubspotContactService ( mockedConfig . Object , mockedLogger . Object ) ;
223
+
224
+ var httpClient = CreateMockedHttpClient ( HttpStatusCode . OK ) ;
225
+ HubspotContactService . ClientFactory = ( ) => httpClient ;
226
+
227
+ var formFieldId = Guid . NewGuid ( ) ;
228
+ var record = new Record ( ) ;
229
+ var fieldMappings = new List < MappedProperty > ( )
230
+ {
231
+ new MappedProperty
232
+ {
233
+ FormField = formFieldId . ToString ( ) ,
234
+ HubspotField = "firstname"
235
+ }
236
+ } ;
237
+ var result = await sut . PostContact ( record , fieldMappings ) ;
238
+
239
+ mockedLogger
240
+ . Verify ( x => x . Warn ( It . Is < Type > ( y => y == typeof ( HubspotContactService ) ) , It . IsAny < string > ( ) , It . IsAny < object [ ] > ( ) ) , Times . Once ) ;
241
+
242
+ Assert . AreEqual ( CommandResult . Success , result ) ;
243
+ }
244
+
245
+ private static Mock < IFacadeConfiguration > CreateMockedConfiguration ( bool withApiKey = true )
246
+ {
247
+ var mockedConfiguration = new Mock < IFacadeConfiguration > ( ) ;
248
+ if ( withApiKey )
249
+ {
250
+ mockedConfiguration
251
+ . Setup ( x => x . GetSetting ( It . Is < string > ( y => y == "HubSpotApiKey" ) ) )
252
+ . Returns ( ApiKey ) ;
253
+ }
254
+
255
+ return mockedConfiguration ;
256
+ }
257
+
258
+ private static HttpClient CreateMockedHttpClient ( HttpStatusCode statusCode , string responseContent = "" )
259
+ {
260
+ var handlerMock = new Mock < HttpMessageHandler > ( ) ;
261
+ var response = new HttpResponseMessage
262
+ {
263
+ StatusCode = statusCode ,
264
+ Content = new StringContent ( responseContent ) ,
265
+ } ;
266
+
267
+ handlerMock
268
+ . Protected ( )
269
+ . Setup < Task < HttpResponseMessage > > (
270
+ "SendAsync" ,
271
+ ItExpr . IsAny < HttpRequestMessage > ( ) ,
272
+ ItExpr . IsAny < CancellationToken > ( ) )
273
+ . ReturnsAsync ( response ) ;
274
+ var httpClient = new HttpClient ( handlerMock . Object ) ;
275
+ return httpClient ;
276
+ }
277
+ }
278
+ }
0 commit comments