@devrev/ts-adaas 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -4
- package/dist/src/adapter/index.d.ts +35 -30
- package/dist/src/adapter/index.js +93 -56
- package/dist/src/common/constants.d.ts +2 -0
- package/dist/src/common/constants.js +10 -0
- package/dist/src/{adapter → common}/helpers.d.ts +4 -1
- package/dist/src/{adapter → common}/helpers.js +16 -4
- package/dist/src/demo-extractor/index.d.ts +8 -1
- package/dist/src/demo-extractor/index.js +64 -56
- package/dist/src/demo-extractor/initial_domain_mapping.json +107 -0
- package/dist/src/http/client.d.ts +1 -1
- package/dist/src/http/client.js +2 -2
- package/dist/src/http/index.d.ts +0 -1
- package/dist/src/http/index.js +0 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/logging/index.d.ts +5 -18
- package/dist/src/logging/index.js +20 -41
- package/dist/src/state/index.d.ts +23 -0
- package/dist/src/state/index.js +111 -0
- package/dist/src/types/extraction.d.ts +16 -5
- package/dist/src/uploader/index.d.ts +4 -2
- package/dist/src/uploader/index.js +61 -4
- package/dist/tests/adapter.helpers.test.js +60 -0
- package/dist/tests/adapter.test.js +106 -57
- package/dist/tests/demo-extractor.test.js +44 -81
- package/dist/tests/state.test.js +100 -0
- package/dist/tests/uploader.test.js +29 -0
- package/package.json +1 -1
- package/dist/src/adapter/index.test.js +0 -105
- package/dist/src/demo-extractor/recipe.json +0 -37
- package/dist/tests/helpers.test.js +0 -38
- package/dist/tests/test-helpers.d.ts +0 -2
- package/dist/tests/test-helpers.js +0 -33
- package/dist/tests/types.test.js +0 -71
- /package/dist/{src/adapter/index.test.d.ts → tests/adapter.helpers.test.d.ts} +0 -0
- /package/dist/tests/{helpers.test.d.ts → state.test.d.ts} +0 -0
- /package/dist/tests/{types.test.d.ts → uploader.test.d.ts} +0 -0
|
@@ -5,69 +5,118 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const axios_1 = __importDefault(require("axios"));
|
|
7
7
|
const adapter_1 = require("../src/adapter");
|
|
8
|
+
const state_1 = require("../src/state");
|
|
8
9
|
const types_1 = require("../src/types");
|
|
9
|
-
const
|
|
10
|
+
const helpers_1 = require("../src/common/helpers");
|
|
11
|
+
jest.mock('axios');
|
|
12
|
+
jest.mock('../src/state');
|
|
13
|
+
jest.mock('../src/common/helpers');
|
|
14
|
+
jest.mock('../src/logging');
|
|
15
|
+
const mockedAxios = axios_1.default;
|
|
16
|
+
const mockedCreateAdapterState = state_1.createAdapterState;
|
|
17
|
+
const mockedGetTimeoutExtractorEventType = helpers_1.getTimeoutExtractorEventType;
|
|
10
18
|
describe('Adapter', () => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
const event = {
|
|
20
|
+
execution_metadata: {
|
|
21
|
+
devrev_endpoint: 'devrev_endpoint',
|
|
22
|
+
},
|
|
23
|
+
context: {
|
|
24
|
+
secrets: {
|
|
25
|
+
service_account_token: 'service_account_token',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
payload: {
|
|
29
|
+
connection_data: {
|
|
30
|
+
org_id: 'org_id',
|
|
31
|
+
org_name: 'org_name',
|
|
32
|
+
key: 'key',
|
|
33
|
+
key_type: 'key_type',
|
|
34
|
+
},
|
|
35
|
+
event_context: {
|
|
36
|
+
mode: 'mode',
|
|
37
|
+
callback_url: 'callback_url',
|
|
38
|
+
dev_org_id: 'dev_org_id',
|
|
39
|
+
dev_user_id: 'dev_user_id',
|
|
40
|
+
external_system_id: 'external_system_id',
|
|
41
|
+
uuid: 'uuid',
|
|
42
|
+
sync_run_id: 'sync_run_id',
|
|
43
|
+
sync_unit_id: 'sync_unit_id',
|
|
44
|
+
worker_data_url: 'worker_data_url',
|
|
45
|
+
},
|
|
46
|
+
event_type: types_1.EventType.ExtractionDataStart,
|
|
47
|
+
},
|
|
48
|
+
input_data: {
|
|
49
|
+
global_values: {},
|
|
50
|
+
event_sources: {},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
const initialState = {
|
|
54
|
+
customField: 'initial',
|
|
55
|
+
};
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
jest.clearAllMocks();
|
|
15
58
|
});
|
|
16
|
-
describe('
|
|
17
|
-
it('should
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
adapter.
|
|
22
|
-
expect(
|
|
23
|
-
});
|
|
24
|
-
it('should not add anything if artifact is not provided', () => {
|
|
25
|
-
const event = (0, test_helpers_1.createAirdropEvent)(types_1.EventType.ExtractionDataStart);
|
|
26
|
-
const adapter = new adapter_1.Adapter(event);
|
|
27
|
-
adapter.update({});
|
|
28
|
-
expect(adapter.getArtifacts()).toHaveLength(0);
|
|
59
|
+
describe('createAdapter', () => {
|
|
60
|
+
it('should create an Adapter instance', async () => {
|
|
61
|
+
const adapterState = new state_1.State(event, initialState);
|
|
62
|
+
mockedCreateAdapterState.mockResolvedValue(adapterState);
|
|
63
|
+
const adapter = await (0, adapter_1.createAdapter)(event, initialState, false);
|
|
64
|
+
expect(adapter).toBeInstanceOf(adapter_1.Adapter);
|
|
65
|
+
expect(mockedCreateAdapterState).toHaveBeenCalledWith(event, expect.anything());
|
|
29
66
|
});
|
|
30
67
|
});
|
|
31
|
-
describe('
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
68
|
+
describe('Adapter', () => {
|
|
69
|
+
let adapter;
|
|
70
|
+
let adapterState;
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
adapterState = new state_1.State(event, initialState);
|
|
73
|
+
adapter = new adapter_1.Adapter(event, adapterState, false);
|
|
74
|
+
});
|
|
75
|
+
it('should emit event and save state if event type is not stateless', async () => {
|
|
76
|
+
const data = {};
|
|
77
|
+
mockedAxios.post.mockResolvedValue({ data: {} });
|
|
78
|
+
await adapter.emit(types_1.ExtractorEventType.ExtractionDataDone, data);
|
|
79
|
+
expect(mockedAxios.post).toHaveBeenCalledWith('callback_url', expect.objectContaining({
|
|
80
|
+
event_type: types_1.ExtractorEventType.ExtractionDataDone,
|
|
81
|
+
}), expect.any(Object));
|
|
82
|
+
expect(adapterState.postState).toHaveBeenCalledWith(adapter.state);
|
|
83
|
+
});
|
|
84
|
+
it('should not save state if event type is stateless', async () => {
|
|
85
|
+
const statelessEvent = Object.assign(Object.assign({}, event), { payload: Object.assign(Object.assign({}, event.payload), { event_type: types_1.EventType.ExtractionExternalSyncUnitsStart }) });
|
|
86
|
+
adapter = new adapter_1.Adapter(statelessEvent, adapterState, false);
|
|
87
|
+
const data = {};
|
|
88
|
+
mockedAxios.post.mockResolvedValue({ data: {} });
|
|
89
|
+
await adapter.emit(types_1.ExtractorEventType.ExtractionExternalSyncUnitsDone, data);
|
|
90
|
+
expect(mockedAxios.post).toHaveBeenCalledWith('callback_url', expect.objectContaining({
|
|
91
|
+
event_type: types_1.ExtractorEventType.ExtractionExternalSyncUnitsDone,
|
|
92
|
+
}), expect.any(Object));
|
|
93
|
+
expect(adapterState.postState).not.toHaveBeenCalled();
|
|
94
|
+
});
|
|
95
|
+
it('should exit adapter on heartbeat timeout', async () => {
|
|
96
|
+
mockedGetTimeoutExtractorEventType.mockReturnValue({
|
|
97
|
+
eventType: types_1.ExtractorEventType.ExtractionMetadataError,
|
|
98
|
+
isError: true,
|
|
99
|
+
});
|
|
100
|
+
jest
|
|
101
|
+
.spyOn(Date, 'now')
|
|
102
|
+
.mockImplementation(() => adapter['startTime'] + adapter['lambdaTimeout'] + 1);
|
|
103
|
+
const heartbeatResult = await adapter['heartbeat']();
|
|
104
|
+
expect(heartbeatResult).toBe(true);
|
|
105
|
+
expect(mockedGetTimeoutExtractorEventType).toHaveBeenCalledWith(event.payload.event_type);
|
|
106
|
+
expect(mockedAxios.post).toHaveBeenCalledWith('callback_url', expect.objectContaining({
|
|
107
|
+
event_type: types_1.ExtractorEventType.ExtractionMetadataError,
|
|
108
|
+
}), expect.any(Object));
|
|
109
|
+
});
|
|
110
|
+
it('should not emit event if adapter is in exit state', async () => {
|
|
111
|
+
adapter['exit'] = true;
|
|
112
|
+
await adapter.emit(types_1.ExtractorEventType.ExtractionDataDone);
|
|
113
|
+
expect(mockedAxios.post).not.toHaveBeenCalled();
|
|
48
114
|
});
|
|
49
|
-
it('should
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const data = {
|
|
55
|
-
error: { message: 'some error message' },
|
|
56
|
-
};
|
|
57
|
-
await adapter.emit(newEventType, data);
|
|
58
|
-
expect(axiosSpy).toHaveBeenCalledWith(event.payload.event_context.callback_url, expect.objectContaining({
|
|
59
|
-
event_type: newEventType,
|
|
60
|
-
event_data: expect.objectContaining({
|
|
61
|
-
error: data.error,
|
|
62
|
-
}),
|
|
63
|
-
}), expect.objectContaining({
|
|
64
|
-
headers: {
|
|
65
|
-
Accept: 'application/json, text/plain, */*',
|
|
66
|
-
Authorization: event.context.secrets["service_account_token"],
|
|
67
|
-
'Content-Type': 'application/json',
|
|
68
|
-
},
|
|
69
|
-
}));
|
|
70
|
-
axiosSpy.mockRestore();
|
|
115
|
+
it('should handle failed event emission gracefully', async () => {
|
|
116
|
+
mockedAxios.post.mockRejectedValue(new Error('Network error'));
|
|
117
|
+
await adapter.emit(types_1.ExtractorEventType.ExtractionDataDone);
|
|
118
|
+
expect(mockedAxios.post).toHaveBeenCalled();
|
|
119
|
+
expect(adapter['exit']).toBe(true);
|
|
71
120
|
});
|
|
72
121
|
});
|
|
73
122
|
});
|
|
@@ -2,96 +2,59 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const types_1 = require("../src/types");
|
|
4
4
|
const adapter_1 = require("../src/adapter");
|
|
5
|
-
const uploader_1 = require("../src/uploader");
|
|
6
5
|
const demo_extractor_1 = require("../src/demo-extractor");
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
const mockEvent = {
|
|
7
|
+
execution_metadata: {
|
|
8
|
+
devrev_endpoint: 'devrev_endpoint',
|
|
9
|
+
},
|
|
10
|
+
context: {
|
|
11
|
+
secrets: {
|
|
12
|
+
service_account_token: 'service_account_token',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
payload: {
|
|
16
|
+
connection_data: {
|
|
17
|
+
org_id: 'org_id',
|
|
18
|
+
org_name: 'org_name',
|
|
19
|
+
key: 'key',
|
|
20
|
+
key_type: 'key_type',
|
|
21
|
+
},
|
|
22
|
+
event_context: {
|
|
23
|
+
mode: 'mode',
|
|
24
|
+
callback_url: 'callback_url',
|
|
25
|
+
dev_org_id: 'dev_org_id',
|
|
26
|
+
dev_user_id: 'dev_user_id',
|
|
27
|
+
external_system_id: 'external_system_id',
|
|
28
|
+
uuid: 'uuid',
|
|
29
|
+
sync_run_id: 'sync_run_id',
|
|
30
|
+
worker_data_url: 'worker_data_url',
|
|
31
|
+
},
|
|
32
|
+
event_type: types_1.EventType.ExtractionExternalSyncUnitsStart,
|
|
33
|
+
},
|
|
34
|
+
input_data: {
|
|
35
|
+
global_values: {},
|
|
36
|
+
event_sources: {},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
10
39
|
describe('DemoExtractor', () => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
adapterMock = new adapter_1.Adapter({});
|
|
16
|
-
uploaderMock = new uploader_1.Uploader('', '');
|
|
17
|
-
adapter_1.Adapter.mockImplementation(() => adapterMock);
|
|
18
|
-
uploader_1.Uploader.mockImplementation(() => uploaderMock);
|
|
19
|
-
demoExtractor = new demo_extractor_1.DemoExtractor();
|
|
20
|
-
});
|
|
21
|
-
afterEach(() => {
|
|
22
|
-
jest.resetAllMocks();
|
|
23
|
-
});
|
|
24
|
-
it('should be able to create an instance of DemoExtractor', () => {
|
|
40
|
+
it('should create a new instance of the DemoExtractor', async () => {
|
|
41
|
+
const adapter = await (0, adapter_1.createAdapter)(mockEvent, {});
|
|
42
|
+
const demoExtractor = new demo_extractor_1.DemoExtractor(mockEvent, adapter);
|
|
25
43
|
expect(demoExtractor).toBeInstanceOf(demo_extractor_1.DemoExtractor);
|
|
26
44
|
});
|
|
27
|
-
it('should emit
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
45
|
+
it('should emit EXTRACTION_EXTERNAL_SYNC_UNITS_DONE with correct payload', async () => {
|
|
46
|
+
const adapter = await (0, adapter_1.createAdapter)(mockEvent, {});
|
|
47
|
+
const demoExtractor = new demo_extractor_1.DemoExtractor(mockEvent, adapter);
|
|
48
|
+
const spy = jest.spyOn(adapter, 'emit');
|
|
49
|
+
await demoExtractor.run();
|
|
50
|
+
expect(spy).toHaveBeenCalledWith(types_1.ExtractorEventType.ExtractionExternalSyncUnitsDone, {
|
|
31
51
|
external_sync_units: [
|
|
32
52
|
{
|
|
33
53
|
id: 'devrev',
|
|
34
54
|
name: 'devrev',
|
|
35
|
-
description: '
|
|
36
|
-
item_count: 0,
|
|
55
|
+
description: 'Demo external sync unit',
|
|
37
56
|
},
|
|
38
57
|
],
|
|
39
|
-
})
|
|
40
|
-
});
|
|
41
|
-
it('should emit ExtractionMetadataDone when metadata is uploaded successfully', async () => {
|
|
42
|
-
const event = (0, test_helpers_1.createAirdropEvent)(types_1.EventType.ExtractionMetadataStart);
|
|
43
|
-
const artifact = { id: 'id', item_type: 'item_type', item_count: 1 };
|
|
44
|
-
uploaderMock.upload.mockResolvedValueOnce({ artifact, error: undefined });
|
|
45
|
-
await demoExtractor.run(event);
|
|
46
|
-
expect(adapterMock.update).toHaveBeenCalledWith({ artifact });
|
|
47
|
-
expect(adapterMock.emit).toHaveBeenCalledWith(types_1.ExtractorEventType.ExtractionMetadataDone);
|
|
48
|
-
});
|
|
49
|
-
it("should emit ExtractionMetadataError when there's an error uploading metadata", async () => {
|
|
50
|
-
const event = (0, test_helpers_1.createAirdropEvent)(types_1.EventType.ExtractionMetadataStart);
|
|
51
|
-
const error = new Error('Failed to upload metadata');
|
|
52
|
-
uploaderMock.upload.mockResolvedValueOnce({ artifact: undefined, error });
|
|
53
|
-
await demoExtractor.run(event);
|
|
54
|
-
expect(adapterMock.emit).toHaveBeenCalledWith(types_1.ExtractorEventType.ExtractionMetadataError, { error });
|
|
55
|
-
});
|
|
56
|
-
it('should emit ExtractionDataProgress when data is uploaded successfully', async () => {
|
|
57
|
-
const event = (0, test_helpers_1.createAirdropEvent)(types_1.EventType.ExtractionDataStart);
|
|
58
|
-
const artifact = { id: 'id', item_type: 'item_type', item_count: 1 };
|
|
59
|
-
uploaderMock.upload.mockResolvedValueOnce({ artifact, error: undefined });
|
|
60
|
-
await demoExtractor.run(event);
|
|
61
|
-
expect(adapterMock.update).toHaveBeenCalledWith({ artifact });
|
|
62
|
-
expect(adapterMock.emit).toHaveBeenCalledWith(types_1.ExtractorEventType.ExtractionDataProgress, { progress: 50 });
|
|
63
|
-
});
|
|
64
|
-
it('should emit ExtractionDataDone when data is uploaded successfully', async () => {
|
|
65
|
-
const event = (0, test_helpers_1.createAirdropEvent)(types_1.EventType.ExtractionDataContinue);
|
|
66
|
-
const artifact = { id: 'id', item_type: 'item_type', item_count: 1 };
|
|
67
|
-
uploaderMock.upload
|
|
68
|
-
.mockResolvedValueOnce({ artifact, error: undefined }) // First call to upload (users data)
|
|
69
|
-
.mockResolvedValueOnce({ artifact, error: undefined }); // Second call to upload (recipe.json)
|
|
70
|
-
await demoExtractor.run(event);
|
|
71
|
-
expect(adapterMock.update).toHaveBeenCalledTimes(2);
|
|
72
|
-
expect(adapterMock.update).toHaveBeenCalledWith({ artifact });
|
|
73
|
-
expect(adapterMock.emit).toHaveBeenCalledWith(types_1.ExtractorEventType.ExtractionDataDone, { progress: 100 });
|
|
74
|
-
});
|
|
75
|
-
it("should emit ExtractionDataError when there's an error uploading data", async () => {
|
|
76
|
-
const event = (0, test_helpers_1.createAirdropEvent)(types_1.EventType.ExtractionDataStart);
|
|
77
|
-
const error = new Error('Failed to upload data');
|
|
78
|
-
uploaderMock.upload.mockResolvedValueOnce({ artifact: undefined, error });
|
|
79
|
-
await demoExtractor.run(event);
|
|
80
|
-
expect(adapterMock.emit).toHaveBeenCalledWith(types_1.ExtractorEventType.ExtractionDataError, { error });
|
|
81
|
-
});
|
|
82
|
-
it('should emit ExtractionAttachmentsDone when attachments are uploaded successfully', async () => {
|
|
83
|
-
const event = (0, test_helpers_1.createAirdropEvent)(types_1.EventType.ExtractionAttachmentsStart);
|
|
84
|
-
const artifact = { id: 'id', item_type: 'item_type', item_count: 1 };
|
|
85
|
-
uploaderMock.upload.mockResolvedValueOnce({ artifact, error: undefined });
|
|
86
|
-
await demoExtractor.run(event);
|
|
87
|
-
expect(adapterMock.update).toHaveBeenCalledWith({ artifact });
|
|
88
|
-
expect(adapterMock.emit).toHaveBeenCalledWith(types_1.ExtractorEventType.ExtractionAttachmentsProgress);
|
|
89
|
-
});
|
|
90
|
-
it("should emit ExtractionAttachmentsError when there's an error uploading attachments", async () => {
|
|
91
|
-
const event = (0, test_helpers_1.createAirdropEvent)(types_1.EventType.ExtractionAttachmentsStart);
|
|
92
|
-
const error = new Error('Failed to upload attachment');
|
|
93
|
-
uploaderMock.upload.mockResolvedValueOnce({ artifact: undefined, error });
|
|
94
|
-
await demoExtractor.run(event);
|
|
95
|
-
expect(adapterMock.emit).toHaveBeenCalledWith(types_1.ExtractorEventType.ExtractionAttachmentsError, { error });
|
|
58
|
+
});
|
|
96
59
|
});
|
|
97
60
|
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const axios_1 = __importDefault(require("axios"));
|
|
7
|
+
const state_1 = require("../src/state");
|
|
8
|
+
const types_1 = require("../src/types");
|
|
9
|
+
const constants_1 = require("../src/common/constants");
|
|
10
|
+
jest.mock('axios');
|
|
11
|
+
const mockedAxios = axios_1.default;
|
|
12
|
+
describe('AdapterState', () => {
|
|
13
|
+
const event = {
|
|
14
|
+
execution_metadata: {
|
|
15
|
+
devrev_endpoint: 'devrev_endpoint',
|
|
16
|
+
},
|
|
17
|
+
context: {
|
|
18
|
+
secrets: {
|
|
19
|
+
service_account_token: 'service_account_token',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
payload: {
|
|
23
|
+
connection_data: {
|
|
24
|
+
org_id: 'org_id',
|
|
25
|
+
org_name: 'org_name',
|
|
26
|
+
key: 'key',
|
|
27
|
+
key_type: 'key_type',
|
|
28
|
+
},
|
|
29
|
+
event_context: {
|
|
30
|
+
mode: 'mode',
|
|
31
|
+
callback_url: 'callback_url',
|
|
32
|
+
dev_org_id: 'dev_org_id',
|
|
33
|
+
dev_user_id: 'dev_user_id',
|
|
34
|
+
external_system_id: 'external_system_id',
|
|
35
|
+
uuid: 'uuid',
|
|
36
|
+
sync_run_id: 'sync_run_id',
|
|
37
|
+
sync_unit_id: 'sync_unit_id',
|
|
38
|
+
worker_data_url: 'worker_data_url',
|
|
39
|
+
},
|
|
40
|
+
event_type: types_1.EventType.ExtractionDataStart,
|
|
41
|
+
},
|
|
42
|
+
input_data: {
|
|
43
|
+
global_values: {},
|
|
44
|
+
event_sources: {},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
const initialState = {
|
|
48
|
+
customField: 'initial',
|
|
49
|
+
};
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
jest.clearAllMocks();
|
|
52
|
+
});
|
|
53
|
+
describe('createAdapterState', () => {
|
|
54
|
+
it('should create an AdapterState instance', async () => {
|
|
55
|
+
const adapterState = await (0, state_1.createAdapterState)(event, initialState);
|
|
56
|
+
expect(adapterState).toBeInstanceOf(state_1.State);
|
|
57
|
+
expect(adapterState.state).toEqual(Object.assign(Object.assign({}, initialState), { lastSyncStarted: '', lastSuccessfulSyncStarted: '' }));
|
|
58
|
+
});
|
|
59
|
+
it('should fetch state if event type is not stateless', async () => {
|
|
60
|
+
const spy = jest.spyOn(state_1.State.prototype, 'fetchState');
|
|
61
|
+
await (0, state_1.createAdapterState)(event, initialState);
|
|
62
|
+
expect(spy).toHaveBeenCalled();
|
|
63
|
+
});
|
|
64
|
+
it('should not fetch state if event type is stateless', async () => {
|
|
65
|
+
const statelessEvent = Object.assign(Object.assign({}, event), { payload: Object.assign(Object.assign({}, event.payload), { event_type: constants_1.STATELESS_EVENT_TYPES[0] }) });
|
|
66
|
+
const spy = jest.spyOn(state_1.State.prototype, 'fetchState');
|
|
67
|
+
await (0, state_1.createAdapterState)(statelessEvent, initialState);
|
|
68
|
+
expect(spy).not.toHaveBeenCalled();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('AdapterState', () => {
|
|
72
|
+
let adapterState;
|
|
73
|
+
beforeEach(() => {
|
|
74
|
+
adapterState = new state_1.State(event, initialState);
|
|
75
|
+
});
|
|
76
|
+
it('should initialize with given state', () => {
|
|
77
|
+
expect(adapterState.state).toEqual(Object.assign(Object.assign({}, initialState), { lastSyncStarted: '', lastSuccessfulSyncStarted: '' }));
|
|
78
|
+
});
|
|
79
|
+
it('should update state via postState', async () => {
|
|
80
|
+
const newState = Object.assign(Object.assign({}, initialState), { customField: 'updated' });
|
|
81
|
+
mockedAxios.post.mockResolvedValue({ data: {} });
|
|
82
|
+
await adapterState.postState(newState);
|
|
83
|
+
expect(adapterState.state).toEqual(newState);
|
|
84
|
+
expect(mockedAxios.post).toHaveBeenCalledWith('worker_data_url.update', { state: JSON.stringify(newState) }, {
|
|
85
|
+
headers: { Authorization: 'service_account_token' },
|
|
86
|
+
params: { sync_unit: 'sync_unit_id' },
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
it('should handle non-404 error in fetchState', async () => {
|
|
90
|
+
const error = new Error('Network error');
|
|
91
|
+
mockedAxios.post.mockRejectedValue(error);
|
|
92
|
+
const state = await adapterState.fetchState(initialState);
|
|
93
|
+
expect(state).toBe(error);
|
|
94
|
+
expect(mockedAxios.post).toHaveBeenCalledWith('worker_data_url.get', {}, {
|
|
95
|
+
headers: { Authorization: 'service_account_token' },
|
|
96
|
+
params: { sync_unit: 'sync_unit_id' },
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const uploader_1 = require("../src/uploader");
|
|
4
|
+
// mock uploader.upload method
|
|
5
|
+
jest.mock('../src/uploader', () => {
|
|
6
|
+
return {
|
|
7
|
+
Uploader: jest.fn().mockImplementation(() => {
|
|
8
|
+
return {
|
|
9
|
+
upload: jest.fn().mockResolvedValue({
|
|
10
|
+
artifact: { key: 'value' },
|
|
11
|
+
error: undefined,
|
|
12
|
+
}),
|
|
13
|
+
};
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
describe('uploader.ts', () => {
|
|
18
|
+
const uploader = new uploader_1.Uploader('https://example.com', 'test-token', false);
|
|
19
|
+
it('should upload the file to the DevRev platform and return the artifact information', async () => {
|
|
20
|
+
const filename = 'filename';
|
|
21
|
+
const entity = 'entity';
|
|
22
|
+
const fetchedObjects = [{ key: 'value' }];
|
|
23
|
+
const uploadResponse = await uploader.upload(filename, entity, fetchedObjects);
|
|
24
|
+
expect(uploadResponse).toEqual({
|
|
25
|
+
artifact: { key: 'value' },
|
|
26
|
+
error: undefined,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
package/package.json
CHANGED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const types_1 = require("../types");
|
|
4
|
-
const index_1 = require("./index");
|
|
5
|
-
jest.useFakeTimers();
|
|
6
|
-
const defaultEvent = {
|
|
7
|
-
context: {
|
|
8
|
-
secrets: {
|
|
9
|
-
service_account_token: 'mockToken',
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
payload: {
|
|
13
|
-
connection_data: {
|
|
14
|
-
org_id: 'mockOrgId',
|
|
15
|
-
org_name: 'mockOrgName',
|
|
16
|
-
key: 'mockKey',
|
|
17
|
-
key_type: 'mockKeyType',
|
|
18
|
-
},
|
|
19
|
-
event_context: {
|
|
20
|
-
mode: 'INITIAL',
|
|
21
|
-
uuid: 'mockUuid',
|
|
22
|
-
callback_url: 'mockCallbackUrl',
|
|
23
|
-
dev_org_id: 'DEV-TESTORG',
|
|
24
|
-
dev_user_id: 'DEV-TESTUSER',
|
|
25
|
-
external_system_id: 'TESTSYSTEM',
|
|
26
|
-
sync_run_id: 'mockSyncRunId',
|
|
27
|
-
},
|
|
28
|
-
event_type: types_1.EventType.ExtractionExternalSyncUnitsStart,
|
|
29
|
-
},
|
|
30
|
-
execution_metadata: {
|
|
31
|
-
devrev_endpoint: 'http://api.dev.devrev-eng.ai',
|
|
32
|
-
},
|
|
33
|
-
input_data: {
|
|
34
|
-
global_values: {},
|
|
35
|
-
event_sources: {},
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
describe('Adapter', () => {
|
|
39
|
-
let adapter;
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
// Initialize the Adapter instance with mock data
|
|
42
|
-
adapter = new index_1.Adapter(defaultEvent);
|
|
43
|
-
});
|
|
44
|
-
afterEach(async () => {
|
|
45
|
-
// Clear all timers
|
|
46
|
-
jest.clearAllTimers();
|
|
47
|
-
// Clear all instances
|
|
48
|
-
jest.clearAllMocks();
|
|
49
|
-
});
|
|
50
|
-
it('should add artifact to the list of artifacts', async () => {
|
|
51
|
-
const artifact = {
|
|
52
|
-
id: 'mockId',
|
|
53
|
-
item_type: 'mockItemType',
|
|
54
|
-
item_count: 1,
|
|
55
|
-
// Mock artifact data
|
|
56
|
-
};
|
|
57
|
-
adapter.update({ artifact: artifact });
|
|
58
|
-
const artifacts = adapter.getArtifacts();
|
|
59
|
-
expect(artifacts).toContain(artifact);
|
|
60
|
-
// Run all timers
|
|
61
|
-
jest.runAllTimers();
|
|
62
|
-
});
|
|
63
|
-
it('should set extractor state if provided', async () => {
|
|
64
|
-
const state = {
|
|
65
|
-
testing: false,
|
|
66
|
-
};
|
|
67
|
-
adapter = new index_1.Adapter(Object.assign({}, defaultEvent), state);
|
|
68
|
-
expect(adapter['extractorState']).toEqual(state);
|
|
69
|
-
const newState = {
|
|
70
|
-
testing: true,
|
|
71
|
-
};
|
|
72
|
-
adapter.update({ extractor_state: newState });
|
|
73
|
-
expect(adapter['extractorState']).toEqual(newState);
|
|
74
|
-
// Run all timers
|
|
75
|
-
jest.runAllTimers();
|
|
76
|
-
});
|
|
77
|
-
it('update both an artifact and extractor state', async () => {
|
|
78
|
-
const artifact = {
|
|
79
|
-
id: 'mockId',
|
|
80
|
-
item_type: 'mockItemType',
|
|
81
|
-
item_count: 1,
|
|
82
|
-
};
|
|
83
|
-
const state = {
|
|
84
|
-
willUpdateToTrue: false,
|
|
85
|
-
willAdd4: 0,
|
|
86
|
-
};
|
|
87
|
-
adapter.update({ artifact: artifact, extractor_state: state });
|
|
88
|
-
const artifacts = adapter.getArtifacts();
|
|
89
|
-
expect(artifacts).toContain(artifact);
|
|
90
|
-
expect(adapter['extractorState']).toEqual(state);
|
|
91
|
-
const newState = {
|
|
92
|
-
willUpdateToTrue: true,
|
|
93
|
-
willAdd4: 4,
|
|
94
|
-
newField: 'newField',
|
|
95
|
-
};
|
|
96
|
-
const newArtifact = {
|
|
97
|
-
id: 'newMockId',
|
|
98
|
-
item_type: 'newMockItemType',
|
|
99
|
-
item_count: 2,
|
|
100
|
-
};
|
|
101
|
-
adapter.update({ artifact: newArtifact, extractor_state: newState });
|
|
102
|
-
// Run all timers
|
|
103
|
-
jest.runAllTimers();
|
|
104
|
-
});
|
|
105
|
-
});
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"initial_object_mappings": [
|
|
3
|
-
{
|
|
4
|
-
"external_type": "contacts",
|
|
5
|
-
"possible_targets": {
|
|
6
|
-
"rev_user": {}
|
|
7
|
-
},
|
|
8
|
-
"default_target": "rev_user",
|
|
9
|
-
"allow_item_type_decisions": true
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"external_type": "users",
|
|
13
|
-
"possible_targets": {
|
|
14
|
-
"dev_user": {}
|
|
15
|
-
},
|
|
16
|
-
"default_target": "dev_user",
|
|
17
|
-
"allow_item_type_decisions": true
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"external_type": "tickets",
|
|
21
|
-
"possible_targets": {
|
|
22
|
-
"work.ticket": {}
|
|
23
|
-
},
|
|
24
|
-
"default_target": "work.ticket",
|
|
25
|
-
"allow_item_type_decisions": true
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"external_type": "conversations",
|
|
29
|
-
"possible_targets": {
|
|
30
|
-
"comment": {}
|
|
31
|
-
},
|
|
32
|
-
"default_target": "comment",
|
|
33
|
-
"allow_item_type_decisions": true
|
|
34
|
-
}
|
|
35
|
-
],
|
|
36
|
-
"external_system_short_name": "source-system"
|
|
37
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const helpers_1 = require("../src/adapter/helpers");
|
|
4
|
-
const types_1 = require("../src/types");
|
|
5
|
-
describe('createFormData', () => {
|
|
6
|
-
it('should create a FormData object', () => {
|
|
7
|
-
const preparedArtifact = {
|
|
8
|
-
form_data: [{ key: 'key', value: 'value' }],
|
|
9
|
-
};
|
|
10
|
-
const fetchedObjects = [{ key: 'value' }];
|
|
11
|
-
const formData = (0, helpers_1.createFormData)(preparedArtifact, fetchedObjects);
|
|
12
|
-
expect(formData).toBeInstanceOf(FormData);
|
|
13
|
-
expect(formData.get('key')).toBe('value');
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
describe('createArtifact', () => {
|
|
17
|
-
it('should create an Artifact object', () => {
|
|
18
|
-
const preparedArtifact = { id: 'id' };
|
|
19
|
-
const fetchedObjects = [{ key: 'value' }];
|
|
20
|
-
const entity = 'entity';
|
|
21
|
-
const artifact = (0, helpers_1.createArtifact)(preparedArtifact, fetchedObjects, entity);
|
|
22
|
-
expect(artifact).toEqual({
|
|
23
|
-
item_count: 1,
|
|
24
|
-
id: 'id',
|
|
25
|
-
item_type: 'entity',
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
describe('getTimeoutExtractorEventType', () => {
|
|
30
|
-
it('should return the correct ExtractorEventType', () => {
|
|
31
|
-
expect((0, helpers_1.getTimeoutExtractorEventType)(types_1.EventType.ExtractionMetadataStart)).toBe(types_1.ExtractorEventType.ExtractionMetadataError);
|
|
32
|
-
expect((0, helpers_1.getTimeoutExtractorEventType)(types_1.EventType.ExtractionDataStart)).toBe(types_1.ExtractorEventType.ExtractionDataProgress);
|
|
33
|
-
expect((0, helpers_1.getTimeoutExtractorEventType)(types_1.EventType.ExtractionDataContinue)).toBe(types_1.ExtractorEventType.ExtractionDataProgress);
|
|
34
|
-
expect((0, helpers_1.getTimeoutExtractorEventType)(types_1.EventType.ExtractionAttachmentsStart)).toBe(types_1.ExtractorEventType.ExtractionAttachmentsProgress);
|
|
35
|
-
expect((0, helpers_1.getTimeoutExtractorEventType)(types_1.EventType.ExtractionAttachmentsContinue)).toBe(types_1.ExtractorEventType.ExtractionAttachmentsProgress);
|
|
36
|
-
expect((0, helpers_1.getTimeoutExtractorEventType)(types_1.EventType.ExtractionExternalSyncUnitsStart)).toBe(types_1.ExtractorEventType.ExtractionExternalSyncUnitsError);
|
|
37
|
-
});
|
|
38
|
-
});
|