meadow-integration 1.0.23 → 1.0.24
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/package.json
CHANGED
|
@@ -258,15 +258,12 @@ class MeadowIntegrationAdapter extends libFableServiceProviderBase
|
|
|
258
258
|
let tmpSchemaURL = `${this.Entity}/Schema`;
|
|
259
259
|
|
|
260
260
|
tmpClient.getJSON(tmpSchemaURL,
|
|
261
|
-
(pError,
|
|
261
|
+
(pError, pResponse, pParsedBody) =>
|
|
262
262
|
{
|
|
263
|
-
// getJSON
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
{
|
|
268
|
-
tmpBody = arguments[2];
|
|
269
|
-
}
|
|
263
|
+
// getJSON returns (pError, pResponse, pParsedBody).
|
|
264
|
+
// Use the parsed body (3rd arg) if present; fall back to
|
|
265
|
+
// pResponse for clients that return (pError, pBody) only.
|
|
266
|
+
let tmpBody = (typeof(pParsedBody) === 'object') ? pParsedBody : pResponse;
|
|
270
267
|
|
|
271
268
|
if (tmpBody && (typeof(tmpBody) == 'object'))
|
|
272
269
|
{
|
|
@@ -1,72 +1,455 @@
|
|
|
1
1
|
/*
|
|
2
2
|
Unit tests for Retold Integration Adapter
|
|
3
|
+
|
|
4
|
+
Validates that the integration adapter correctly fetches the remote
|
|
5
|
+
schema, marshals source records, and upserts them to the server.
|
|
6
|
+
|
|
7
|
+
Uses a mock HTTP server to simulate meadow-endpoints API responses.
|
|
3
8
|
*/
|
|
4
9
|
|
|
5
10
|
const Chai = require('chai');
|
|
6
11
|
const Expect = Chai.expect;
|
|
7
12
|
|
|
13
|
+
const libHTTP = require('http');
|
|
8
14
|
const libPict = require('pict');
|
|
9
15
|
const libIntegrationAdapter = require('../source/Meadow-Service-Integration-Adapter.js');
|
|
16
|
+
const libMeadowCloneRestClient = require('../source/services/clone/Meadow-Service-RestClient.js');
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
// ── Test Constants ──────────────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
const MOCK_PORT = 18199;
|
|
21
|
+
const MOCK_BASE_URL = `http://localhost:${MOCK_PORT}/1.0/`;
|
|
22
|
+
|
|
23
|
+
// ── Mock Schema ─────────────────────────────────────────────────────────────────
|
|
24
|
+
// This is what the Schema endpoint returns — a JSON schema with properties.
|
|
25
|
+
|
|
26
|
+
const MOCK_SCHEMA =
|
|
27
|
+
{
|
|
28
|
+
title: 'TestEntity',
|
|
29
|
+
type: 'object',
|
|
30
|
+
properties:
|
|
31
|
+
{
|
|
32
|
+
IDTestEntity: { type: 'integer' },
|
|
33
|
+
GUIDTestEntity: { type: 'string', size: 128 },
|
|
34
|
+
Name: { type: 'string', size: 200 },
|
|
35
|
+
Value: { type: 'integer' }
|
|
36
|
+
},
|
|
37
|
+
required: ['IDTestEntity']
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// ── Mock Server State ───────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
let _MockState =
|
|
43
|
+
{
|
|
44
|
+
NextID: 1,
|
|
45
|
+
UpsertedRecords: [],
|
|
46
|
+
StoredRecords: {}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
function resetMockState()
|
|
50
|
+
{
|
|
51
|
+
_MockState.NextID = 1;
|
|
52
|
+
_MockState.UpsertedRecords = [];
|
|
53
|
+
_MockState.StoredRecords = {};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── Mock HTTP Server ────────────────────────────────────────────────────────────
|
|
57
|
+
// Simulates meadow-endpoints API responses for the TestEntity entity.
|
|
58
|
+
|
|
59
|
+
function createMockServer()
|
|
60
|
+
{
|
|
61
|
+
return libHTTP.createServer(
|
|
62
|
+
(pRequest, pResponse) =>
|
|
15
63
|
{
|
|
16
|
-
|
|
64
|
+
let tmpURL = pRequest.url;
|
|
65
|
+
let tmpBody = '';
|
|
17
66
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
67
|
+
pResponse.setHeader('Content-Type', 'application/json');
|
|
68
|
+
|
|
69
|
+
pRequest.on('data',
|
|
70
|
+
(pChunk) =>
|
|
71
|
+
{
|
|
72
|
+
tmpBody += pChunk;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
pRequest.on('end',
|
|
76
|
+
() =>
|
|
77
|
+
{
|
|
78
|
+
// GET /1.0/TestEntity/Schema
|
|
79
|
+
if (pRequest.method === 'GET' && tmpURL.match(/\/1\.0\/TestEntity\/Schema/))
|
|
80
|
+
{
|
|
81
|
+
pResponse.end(JSON.stringify(MOCK_SCHEMA));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// PUT /1.0/TestEntity/Upsert
|
|
86
|
+
if (pRequest.method === 'PUT' && tmpURL.match(/\/1\.0\/TestEntity\/Upsert/))
|
|
87
|
+
{
|
|
88
|
+
let tmpRecord = {};
|
|
89
|
+
try
|
|
90
|
+
{
|
|
91
|
+
tmpRecord = JSON.parse(tmpBody);
|
|
92
|
+
}
|
|
93
|
+
catch (pError)
|
|
94
|
+
{
|
|
95
|
+
pResponse.statusCode = 400;
|
|
96
|
+
pResponse.end(JSON.stringify({ Error: 'Invalid JSON' }));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Assign an auto-incremented ID if not present or zero
|
|
101
|
+
if (!tmpRecord.IDTestEntity || tmpRecord.IDTestEntity === 0)
|
|
102
|
+
{
|
|
103
|
+
tmpRecord.IDTestEntity = _MockState.NextID++;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Store and track the upserted record
|
|
107
|
+
_MockState.UpsertedRecords.push(JSON.parse(JSON.stringify(tmpRecord)));
|
|
108
|
+
_MockState.StoredRecords[tmpRecord.GUIDTestEntity] = tmpRecord;
|
|
109
|
+
|
|
110
|
+
pResponse.end(JSON.stringify(tmpRecord));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// GET /1.0/TestEntitys/By/GUIDTestEntity/{guid}/0/1
|
|
115
|
+
if (pRequest.method === 'GET' && tmpURL.match(/\/1\.0\/TestEntitys\/By\/GUIDTestEntity\//))
|
|
116
|
+
{
|
|
117
|
+
let tmpParts = tmpURL.split('/');
|
|
118
|
+
// URL pattern: /1.0/TestEntitys/By/GUIDTestEntity/{guid}/0/1
|
|
119
|
+
let tmpGUID = tmpParts[5];
|
|
120
|
+
let tmpRecord = _MockState.StoredRecords[tmpGUID];
|
|
121
|
+
if (tmpRecord)
|
|
122
|
+
{
|
|
123
|
+
pResponse.end(JSON.stringify([tmpRecord]));
|
|
124
|
+
}
|
|
125
|
+
else
|
|
126
|
+
{
|
|
127
|
+
pResponse.end(JSON.stringify([]));
|
|
128
|
+
}
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Fallback — 404
|
|
133
|
+
pResponse.statusCode = 404;
|
|
134
|
+
pResponse.end(JSON.stringify({ Error: `Unknown endpoint: ${pRequest.method} ${tmpURL}` }));
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
suite
|
|
140
|
+
(
|
|
141
|
+
'Integration Adapter Basic',
|
|
142
|
+
() =>
|
|
143
|
+
{
|
|
144
|
+
setup(() => { });
|
|
145
|
+
|
|
146
|
+
suite
|
|
147
|
+
(
|
|
148
|
+
'Basic Tests',
|
|
149
|
+
() =>
|
|
150
|
+
{
|
|
151
|
+
test(
|
|
152
|
+
'Object Instantiation',
|
|
153
|
+
(fDone) =>
|
|
154
|
+
{
|
|
155
|
+
let _Fable = new libPict();
|
|
156
|
+
_Fable.addServiceType('IntegrationAdapter', libIntegrationAdapter);
|
|
157
|
+
let tmpIntegrationAdapter = _Fable.instantiateServiceProvider('IntegrationAdapter', { Entity: 'TestEntity' }, 'TestEntity');
|
|
158
|
+
Expect(tmpIntegrationAdapter).to.be.an('object');
|
|
159
|
+
return fDone();
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
suite
|
|
167
|
+
(
|
|
168
|
+
'Integration Adapter with Mock Server',
|
|
169
|
+
() =>
|
|
170
|
+
{
|
|
171
|
+
let _MockServer = null;
|
|
172
|
+
|
|
173
|
+
suiteSetup
|
|
174
|
+
(
|
|
175
|
+
(fDone) =>
|
|
176
|
+
{
|
|
177
|
+
_MockServer = createMockServer();
|
|
178
|
+
_MockServer.listen(MOCK_PORT,
|
|
21
179
|
() =>
|
|
22
180
|
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
181
|
+
return fDone();
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
suiteTeardown
|
|
187
|
+
(
|
|
188
|
+
(fDone) =>
|
|
189
|
+
{
|
|
190
|
+
if (_MockServer)
|
|
191
|
+
{
|
|
192
|
+
_MockServer.close(fDone);
|
|
193
|
+
}
|
|
194
|
+
else
|
|
195
|
+
{
|
|
196
|
+
return fDone();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
setup
|
|
202
|
+
(
|
|
203
|
+
() =>
|
|
204
|
+
{
|
|
205
|
+
resetMockState();
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
// ── Schema Fetch ────────────────────────────────────────────────────
|
|
210
|
+
|
|
211
|
+
suite
|
|
212
|
+
(
|
|
213
|
+
'Schema Fetch',
|
|
214
|
+
() =>
|
|
215
|
+
{
|
|
216
|
+
test
|
|
217
|
+
(
|
|
218
|
+
'meadowSchema should be populated after integrateRecords',
|
|
219
|
+
(fDone) =>
|
|
220
|
+
{
|
|
221
|
+
let tmpFable = new libPict(
|
|
222
|
+
{
|
|
223
|
+
Product: 'AdapterTest',
|
|
224
|
+
ProductVersion: '1.0.0',
|
|
225
|
+
LogStreams: [{ streamtype: 'console', level: 'error' }]
|
|
226
|
+
});
|
|
227
|
+
tmpFable.addServiceType('IntegrationAdapter', libIntegrationAdapter);
|
|
228
|
+
tmpFable.serviceManager.addServiceType('MeadowCloneRestClient', libMeadowCloneRestClient);
|
|
229
|
+
tmpFable.serviceManager.instantiateServiceProvider('MeadowCloneRestClient',
|
|
230
|
+
{
|
|
231
|
+
ServerURL: MOCK_BASE_URL
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
let tmpAdapter = tmpFable.instantiateServiceProvider('IntegrationAdapter',
|
|
235
|
+
{
|
|
236
|
+
Entity: 'TestEntity',
|
|
237
|
+
SimpleMarshal: true
|
|
238
|
+
}, 'TestEntity');
|
|
239
|
+
|
|
240
|
+
tmpAdapter.addSourceRecord({ GUIDTestEntity: 'test-schema-1', Name: 'SchemaCheck', Value: 1 });
|
|
241
|
+
|
|
242
|
+
// Before integration, meadowSchema should not be set
|
|
243
|
+
Expect(tmpAdapter.meadowSchema).to.not.be.ok;
|
|
244
|
+
|
|
245
|
+
tmpAdapter.integrateRecords(
|
|
246
|
+
(pError) =>
|
|
247
|
+
{
|
|
248
|
+
Expect(pError).to.not.exist;
|
|
249
|
+
|
|
250
|
+
// After integration, meadowSchema should be populated
|
|
251
|
+
Expect(tmpAdapter.meadowSchema).to.be.an('object');
|
|
252
|
+
Expect(tmpAdapter.meadowSchema).to.have.property('properties');
|
|
253
|
+
Expect(tmpAdapter.meadowSchema.properties).to.have.property('Name');
|
|
254
|
+
Expect(tmpAdapter.meadowSchema.properties).to.have.property('Value');
|
|
255
|
+
Expect(tmpAdapter.meadowSchema.properties).to.have.property('IDTestEntity');
|
|
256
|
+
Expect(tmpAdapter.meadowSchema.properties).to.have.property('GUIDTestEntity');
|
|
257
|
+
|
|
31
258
|
return fDone();
|
|
32
259
|
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
// ── Full Integration Pipeline ───────────────────────────────────────
|
|
266
|
+
|
|
267
|
+
suite
|
|
268
|
+
(
|
|
269
|
+
'Full Integration Pipeline',
|
|
270
|
+
() =>
|
|
271
|
+
{
|
|
272
|
+
test
|
|
273
|
+
(
|
|
274
|
+
'upsert body should include marshaled field values (not just the GUID)',
|
|
275
|
+
function (fDone)
|
|
276
|
+
{
|
|
277
|
+
this.timeout(10000);
|
|
278
|
+
|
|
279
|
+
let tmpFable = new libPict(
|
|
280
|
+
{
|
|
281
|
+
Product: 'AdapterTest',
|
|
282
|
+
ProductVersion: '1.0.0',
|
|
283
|
+
LogStreams: [{ streamtype: 'console', level: 'error' }]
|
|
284
|
+
});
|
|
285
|
+
tmpFable.addServiceType('IntegrationAdapter', libIntegrationAdapter);
|
|
286
|
+
tmpFable.serviceManager.addServiceType('MeadowCloneRestClient', libMeadowCloneRestClient);
|
|
287
|
+
tmpFable.serviceManager.instantiateServiceProvider('MeadowCloneRestClient',
|
|
288
|
+
{
|
|
289
|
+
ServerURL: MOCK_BASE_URL
|
|
49
290
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
(fDone) =>
|
|
291
|
+
|
|
292
|
+
let tmpAdapter = tmpFable.instantiateServiceProvider('IntegrationAdapter',
|
|
53
293
|
{
|
|
54
|
-
|
|
294
|
+
Entity: 'TestEntity',
|
|
295
|
+
SimpleMarshal: true
|
|
296
|
+
}, 'TestEntity');
|
|
297
|
+
|
|
298
|
+
tmpAdapter.addSourceRecord({ GUIDTestEntity: 'test-1', Name: 'Alice', Value: 42 });
|
|
299
|
+
|
|
300
|
+
tmpAdapter.integrateRecords(
|
|
301
|
+
(pError) =>
|
|
302
|
+
{
|
|
303
|
+
Expect(pError).to.not.exist;
|
|
304
|
+
|
|
305
|
+
// The mock server should have received exactly one upsert
|
|
306
|
+
Expect(_MockState.UpsertedRecords.length).to.equal(1,
|
|
307
|
+
`Expected 1 upserted record, got ${_MockState.UpsertedRecords.length}`);
|
|
55
308
|
|
|
56
|
-
|
|
309
|
+
let tmpUpsertedRecord = _MockState.UpsertedRecords[0];
|
|
310
|
+
|
|
311
|
+
// The GUID should be present (with the adapter prefix)
|
|
312
|
+
Expect(tmpUpsertedRecord).to.have.property('GUIDTestEntity');
|
|
313
|
+
Expect(tmpUpsertedRecord.GUIDTestEntity).to.be.a('string');
|
|
314
|
+
Expect(tmpUpsertedRecord.GUIDTestEntity).to.include('test-1');
|
|
315
|
+
|
|
316
|
+
// CRITICAL: Verify field values were marshaled through.
|
|
317
|
+
// If the arrow-function arguments bug is present, the schema
|
|
318
|
+
// fetch would fail silently, meadowSchema would be null, and
|
|
319
|
+
// SimpleMarshal would not copy Name and Value through.
|
|
320
|
+
Expect(tmpUpsertedRecord).to.have.property('Name');
|
|
321
|
+
Expect(tmpUpsertedRecord.Name).to.equal('Alice');
|
|
322
|
+
Expect(tmpUpsertedRecord).to.have.property('Value');
|
|
323
|
+
Expect(tmpUpsertedRecord.Value).to.equal(42);
|
|
324
|
+
|
|
325
|
+
// Verify the schema was also populated
|
|
326
|
+
Expect(tmpAdapter.meadowSchema).to.be.an('object');
|
|
327
|
+
Expect(tmpAdapter.meadowSchema.properties).to.have.property('Name');
|
|
328
|
+
|
|
329
|
+
return fDone();
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
test
|
|
335
|
+
(
|
|
336
|
+
'should integrate multiple records with correct field values',
|
|
337
|
+
function (fDone)
|
|
338
|
+
{
|
|
339
|
+
this.timeout(10000);
|
|
340
|
+
|
|
341
|
+
let tmpFable = new libPict(
|
|
342
|
+
{
|
|
343
|
+
Product: 'AdapterTest',
|
|
344
|
+
ProductVersion: '1.0.0',
|
|
345
|
+
LogStreams: [{ streamtype: 'console', level: 'error' }]
|
|
346
|
+
});
|
|
347
|
+
tmpFable.addServiceType('IntegrationAdapter', libIntegrationAdapter);
|
|
348
|
+
tmpFable.serviceManager.addServiceType('MeadowCloneRestClient', libMeadowCloneRestClient);
|
|
349
|
+
tmpFable.serviceManager.instantiateServiceProvider('MeadowCloneRestClient',
|
|
350
|
+
{
|
|
351
|
+
ServerURL: MOCK_BASE_URL
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
let tmpAdapter = tmpFable.instantiateServiceProvider('IntegrationAdapter',
|
|
355
|
+
{
|
|
356
|
+
Entity: 'TestEntity',
|
|
357
|
+
SimpleMarshal: true
|
|
358
|
+
}, 'TestEntity');
|
|
359
|
+
|
|
360
|
+
tmpAdapter.addSourceRecord({ GUIDTestEntity: 'multi-1', Name: 'Alice', Value: 42 });
|
|
361
|
+
tmpAdapter.addSourceRecord({ GUIDTestEntity: 'multi-2', Name: 'Bob', Value: 99 });
|
|
362
|
+
tmpAdapter.addSourceRecord({ GUIDTestEntity: 'multi-3', Name: 'Charlie', Value: 7 });
|
|
363
|
+
|
|
364
|
+
tmpAdapter.integrateRecords(
|
|
365
|
+
(pError) =>
|
|
366
|
+
{
|
|
367
|
+
Expect(pError).to.not.exist;
|
|
57
368
|
|
|
58
|
-
|
|
369
|
+
Expect(_MockState.UpsertedRecords.length).to.equal(3,
|
|
370
|
+
`Expected 3 upserted records, got ${_MockState.UpsertedRecords.length}`);
|
|
59
371
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
372
|
+
// Build a lookup by the original GUID suffix for easy verification
|
|
373
|
+
let tmpByGUID = {};
|
|
374
|
+
for (let i = 0; i < _MockState.UpsertedRecords.length; i++)
|
|
375
|
+
{
|
|
376
|
+
let tmpRec = _MockState.UpsertedRecords[i];
|
|
377
|
+
if (tmpRec.GUIDTestEntity.indexOf('multi-1') > -1) tmpByGUID['multi-1'] = tmpRec;
|
|
378
|
+
if (tmpRec.GUIDTestEntity.indexOf('multi-2') > -1) tmpByGUID['multi-2'] = tmpRec;
|
|
379
|
+
if (tmpRec.GUIDTestEntity.indexOf('multi-3') > -1) tmpByGUID['multi-3'] = tmpRec;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
Expect(tmpByGUID['multi-1'].Name).to.equal('Alice');
|
|
383
|
+
Expect(tmpByGUID['multi-1'].Value).to.equal(42);
|
|
384
|
+
|
|
385
|
+
Expect(tmpByGUID['multi-2'].Name).to.equal('Bob');
|
|
386
|
+
Expect(tmpByGUID['multi-2'].Value).to.equal(99);
|
|
387
|
+
|
|
388
|
+
Expect(tmpByGUID['multi-3'].Name).to.equal('Charlie');
|
|
389
|
+
Expect(tmpByGUID['multi-3'].Value).to.equal(7);
|
|
390
|
+
|
|
391
|
+
// Each record should have been assigned a server-side ID
|
|
392
|
+
Expect(tmpByGUID['multi-1'].IDTestEntity).to.be.above(0);
|
|
393
|
+
Expect(tmpByGUID['multi-2'].IDTestEntity).to.be.above(0);
|
|
394
|
+
Expect(tmpByGUID['multi-3'].IDTestEntity).to.be.above(0);
|
|
395
|
+
|
|
396
|
+
return fDone();
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
);
|
|
400
|
+
|
|
401
|
+
test
|
|
402
|
+
(
|
|
403
|
+
'without SimpleMarshal, fields not in schema properties are excluded',
|
|
404
|
+
function (fDone)
|
|
405
|
+
{
|
|
406
|
+
this.timeout(10000);
|
|
407
|
+
|
|
408
|
+
let tmpFable = new libPict(
|
|
409
|
+
{
|
|
410
|
+
Product: 'AdapterTest',
|
|
411
|
+
ProductVersion: '1.0.0',
|
|
412
|
+
LogStreams: [{ streamtype: 'console', level: 'error' }]
|
|
413
|
+
});
|
|
414
|
+
tmpFable.addServiceType('IntegrationAdapter', libIntegrationAdapter);
|
|
415
|
+
tmpFable.serviceManager.addServiceType('MeadowCloneRestClient', libMeadowCloneRestClient);
|
|
416
|
+
tmpFable.serviceManager.instantiateServiceProvider('MeadowCloneRestClient',
|
|
417
|
+
{
|
|
418
|
+
ServerURL: MOCK_BASE_URL
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
let tmpAdapter = tmpFable.instantiateServiceProvider('IntegrationAdapter',
|
|
422
|
+
{
|
|
423
|
+
Entity: 'TestEntity',
|
|
424
|
+
SimpleMarshal: false
|
|
425
|
+
}, 'TestEntity');
|
|
426
|
+
|
|
427
|
+
// ExtraField is not in the mock schema
|
|
428
|
+
tmpAdapter.addSourceRecord({ GUIDTestEntity: 'test-extra', Name: 'Diana', Value: 55, ExtraField: 'should-not-appear' });
|
|
429
|
+
|
|
430
|
+
tmpAdapter.integrateRecords(
|
|
431
|
+
(pError) =>
|
|
432
|
+
{
|
|
433
|
+
Expect(pError).to.not.exist;
|
|
434
|
+
|
|
435
|
+
Expect(_MockState.UpsertedRecords.length).to.equal(1);
|
|
436
|
+
|
|
437
|
+
let tmpUpsertedRecord = _MockState.UpsertedRecords[0];
|
|
438
|
+
|
|
439
|
+
// Name and Value should be marshaled through the schema
|
|
440
|
+
Expect(tmpUpsertedRecord).to.have.property('Name');
|
|
441
|
+
Expect(tmpUpsertedRecord.Name).to.equal('Diana');
|
|
442
|
+
Expect(tmpUpsertedRecord).to.have.property('Value');
|
|
443
|
+
Expect(tmpUpsertedRecord.Value).to.equal(55);
|
|
444
|
+
|
|
445
|
+
// ExtraField should NOT be in the upserted record
|
|
446
|
+
Expect(tmpUpsertedRecord).to.not.have.property('ExtraField');
|
|
447
|
+
|
|
448
|
+
return fDone();
|
|
67
449
|
});
|
|
68
|
-
*/
|
|
69
450
|
}
|
|
70
451
|
);
|
|
71
|
-
|
|
72
|
-
|
|
452
|
+
}
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
);
|