mcdev 8.2.1 → 8.3.0

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 (123) hide show
  1. package/.github/ISSUE_TEMPLATE/bug.yml +1 -0
  2. package/.github/workflows/code-test.yml +1 -1
  3. package/.github/workflows/coverage-base-update.yml +1 -1
  4. package/.github/workflows/coverage-develop-branch.yml +1 -1
  5. package/.github/workflows/coverage-main-branch.yml +1 -1
  6. package/.github/workflows/coverage.yml +1 -1
  7. package/.github/workflows/npm-publish.yml +9 -5
  8. package/@types/lib/MetadataTypeDefinitions.d.ts +4 -0
  9. package/@types/lib/MetadataTypeDefinitions.d.ts.map +1 -1
  10. package/@types/lib/MetadataTypeInfo.d.ts +4 -0
  11. package/@types/lib/MetadataTypeInfo.d.ts.map +1 -1
  12. package/@types/lib/Retriever.d.ts.map +1 -1
  13. package/@types/lib/index.d.ts +20 -9
  14. package/@types/lib/index.d.ts.map +1 -1
  15. package/@types/lib/metadataTypes/Asset.d.ts +3 -3
  16. package/@types/lib/metadataTypes/Asset.d.ts.map +1 -1
  17. package/@types/lib/metadataTypes/Automation.d.ts +7 -7
  18. package/@types/lib/metadataTypes/Automation.d.ts.map +1 -1
  19. package/@types/lib/metadataTypes/DataExtension.d.ts +9 -9
  20. package/@types/lib/metadataTypes/DataExtension.d.ts.map +1 -1
  21. package/@types/lib/metadataTypes/DataExtensionField.d.ts +7 -0
  22. package/@types/lib/metadataTypes/DataExtensionField.d.ts.map +1 -1
  23. package/@types/lib/metadataTypes/DataFilter.d.ts +326 -0
  24. package/@types/lib/metadataTypes/DataFilter.d.ts.map +1 -0
  25. package/@types/lib/metadataTypes/DataFilterHidden.d.ts +164 -0
  26. package/@types/lib/metadataTypes/DataFilterHidden.d.ts.map +1 -0
  27. package/@types/lib/metadataTypes/Filter.d.ts +181 -6
  28. package/@types/lib/metadataTypes/Filter.d.ts.map +1 -1
  29. package/@types/lib/metadataTypes/FilterDefinition.d.ts +318 -0
  30. package/@types/lib/metadataTypes/FilterDefinition.d.ts.map +1 -0
  31. package/@types/lib/metadataTypes/FilterDefinitionHidden.d.ts +156 -0
  32. package/@types/lib/metadataTypes/FilterDefinitionHidden.d.ts.map +1 -0
  33. package/@types/lib/metadataTypes/ImportFile.d.ts.map +1 -1
  34. package/@types/lib/metadataTypes/Journey.d.ts +18 -0
  35. package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
  36. package/@types/lib/metadataTypes/MobileKeyword.d.ts +2 -2
  37. package/@types/lib/metadataTypes/MobileKeyword.d.ts.map +1 -1
  38. package/@types/lib/metadataTypes/User.d.ts +1 -1
  39. package/@types/lib/metadataTypes/User.d.ts.map +1 -1
  40. package/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts +230 -0
  41. package/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts.map +1 -0
  42. package/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts +230 -0
  43. package/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts.map +1 -0
  44. package/@types/lib/metadataTypes/definitions/Filter.definition.d.ts +203 -31
  45. package/@types/lib/metadataTypes/definitions/FilterDefinition.definition.d.ts +218 -0
  46. package/@types/lib/metadataTypes/definitions/FilterDefinition.definition.d.ts.map +1 -0
  47. package/@types/lib/metadataTypes/definitions/FilterDefinitionHidden.definition.d.ts +218 -0
  48. package/@types/lib/metadataTypes/definitions/FilterDefinitionHidden.definition.d.ts.map +1 -0
  49. package/@types/lib/metadataTypes/definitions/Journey.definition.d.ts +18 -0
  50. package/@types/lib/util/devops.d.ts +1 -0
  51. package/@types/lib/util/devops.d.ts.map +1 -1
  52. package/@types/lib/util/replaceContentBlockReference.d.ts +3 -3
  53. package/@types/lib/util/replaceContentBlockReference.d.ts.map +1 -1
  54. package/@types/lib/util/util.d.ts.map +1 -1
  55. package/@types/lib/util/validations.d.ts.map +1 -1
  56. package/@types/types/mcdev.d.d.ts +296 -0
  57. package/@types/types/mcdev.d.d.ts.map +1 -1
  58. package/lib/MetadataTypeDefinitions.js +4 -0
  59. package/lib/MetadataTypeInfo.js +4 -0
  60. package/lib/Retriever.js +3 -0
  61. package/lib/index.js +87 -3
  62. package/lib/metadataTypes/DataExtensionField.js +21 -0
  63. package/lib/metadataTypes/DataFilter.js +653 -0
  64. package/lib/metadataTypes/DataFilterHidden.js +18 -0
  65. package/lib/metadataTypes/Filter.js +315 -1
  66. package/lib/metadataTypes/ImportFile.js +11 -1
  67. package/lib/metadataTypes/Journey.js +111 -7
  68. package/lib/metadataTypes/definitions/Automation.definition.js +1 -0
  69. package/lib/metadataTypes/definitions/DataFilter.definition.js +168 -0
  70. package/lib/metadataTypes/definitions/DataFilterHidden.definition.js +169 -0
  71. package/lib/metadataTypes/definitions/Filter.definition.js +136 -22
  72. package/lib/metadataTypes/definitions/Journey.definition.js +20 -1
  73. package/lib/util/devops.js +14 -4
  74. package/lib/util/util.js +7 -2
  75. package/lib/util/validations.js +7 -1
  76. package/package.json +10 -10
  77. package/test/general.test.js +17 -19
  78. package/test/mockRoot/.mcdevrc.json +4 -1
  79. package/test/mockRoot/deploy/testInstance/testBU/dataFilter/testExisting_dataFilter.dataFilter-meta.json +19 -0
  80. package/test/mockRoot/deploy/testInstance/testBU/dataFilter/testNew_dataFilter.dataFilter-meta.json +19 -0
  81. package/test/mockRoot/deploy/testInstance/testBU/filter/testExisting_filter.filter-meta.json +10 -0
  82. package/test/mockRoot/deploy/testInstance/testBU/filter/testNew_filter.filter-meta.json +11 -0
  83. package/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_updatecontact.journey-meta.json +108 -0
  84. package/test/resources/9999999/automation/v1/filters/a0f1a1bc-4ea1-44b3-8fe1-ce40ef35c1c0/patch-response.json +18 -0
  85. package/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/delete-response.txt +0 -0
  86. package/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/get-response.json +15 -0
  87. package/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/patch-response.json +15 -0
  88. package/test/resources/9999999/automation/v1/filters/get-response.json +22 -0
  89. package/test/resources/9999999/dataFilter/build-expected.json +19 -0
  90. package/test/resources/9999999/dataFilter/get-expected.json +23 -0
  91. package/test/resources/9999999/dataFilter/patch-expected.json +20 -0
  92. package/test/resources/9999999/dataFilter/post-expected.json +20 -0
  93. package/test/resources/9999999/dataFilter/template-expected.json +19 -0
  94. package/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,filteract,filterdef,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,useriniti-response.xml +765 -0
  95. package/test/resources/9999999/dataFolder/retrieve-ContentTypeINfilteractivity,hidden-response.xml +139 -0
  96. package/test/resources/9999999/dataFolder/retrieve-ContentTypeINfilterdefinition,hidden-response.xml +116 -0
  97. package/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/delete-response.txt +1 -0
  98. package/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/get-response.json +19 -0
  99. package/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/patch-response.json +15 -0
  100. package/test/resources/9999999/email/v1/filters/filterdefinition/category/5318/get-response.json +27 -0
  101. package/test/resources/9999999/email/v1/filters/filterdefinition/category/8502/get-response.json +7 -0
  102. package/test/resources/9999999/email/v1/filters/filterdefinition/category/8503/get-response.json +7 -0
  103. package/test/resources/9999999/email/v1/filters/filterdefinition/post-response.json +15 -0
  104. package/test/resources/9999999/filter/build-expected.json +10 -0
  105. package/test/resources/9999999/filter/get-expected.json +11 -0
  106. package/test/resources/9999999/filter/patch-expected.json +11 -0
  107. package/test/resources/9999999/filter/post-expected.json +11 -0
  108. package/test/resources/9999999/filter/template-expected.json +10 -0
  109. package/test/resources/9999999/filterActivity/create-response.xml +46 -0
  110. package/test/resources/9999999/filterActivity/retrieve-CustomerKey=testExisting_filter-response.xml +30 -0
  111. package/test/resources/9999999/filterDefinition/retrieve-CustomerKey=testExisting_dataFilter-response.xml +30 -0
  112. package/test/resources/9999999/interaction/v1/interactions/get-response.json +45 -3
  113. package/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_updatecontact/get-response.json +119 -0
  114. package/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_updatecontact/put-response.json +106 -0
  115. package/test/resources/9999999/journey/get-updatecontact-expected.json +108 -0
  116. package/test/resources/9999999/journey/put-updatecontact-expected.json +108 -0
  117. package/test/type.automation.test.js +14 -14
  118. package/test/type.dataFilter.test.js +174 -0
  119. package/test/type.filter.test.js +170 -0
  120. package/test/type.journey.test.js +59 -7
  121. package/test/type.query.test.js +2 -2
  122. package/test/utils.js +8 -0
  123. package/types/mcdev.d.js +101 -0
@@ -0,0 +1,174 @@
1
+ import * as chai from 'chai';
2
+ const assert = chai.assert;
3
+
4
+ import chaiFiles from 'chai-files';
5
+ import cache from '../lib/util/cache.js';
6
+ import * as testUtils from './utils.js';
7
+ import handler from '../lib/index.js';
8
+ chai.use(chaiFiles);
9
+
10
+ describe('type: dataFilter', () => {
11
+ beforeEach(() => {
12
+ testUtils.mockSetup();
13
+ });
14
+
15
+ afterEach(() => {
16
+ testUtils.mockReset();
17
+ });
18
+
19
+ describe('Retrieve ================', () => {
20
+ it('Should retrieve a dataFilter', async () => {
21
+ // WHEN
22
+ await handler.retrieve('testInstance/testBU', ['dataFilter']);
23
+ // THEN
24
+ assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error');
25
+ // get results from cache
26
+ const result = cache.getCache();
27
+ assert.equal(
28
+ result.dataFilter ? Object.keys(result.dataFilter).length : 0,
29
+ 1,
30
+ 'unexpected number of items retrieved'
31
+ );
32
+ assert.deepEqual(
33
+ await testUtils.getActualJson('testExisting_dataFilter', 'dataFilter'),
34
+ await testUtils.getExpectedJson('9999999', 'dataFilter', 'get'),
35
+ 'returned JSON was not equal expected'
36
+ );
37
+
38
+ assert.equal(
39
+ testUtils.getAPIHistoryLength(),
40
+ 6,
41
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
42
+ );
43
+ return;
44
+ });
45
+
46
+ it('Should retrieve a dataFilter by key', async () => {
47
+ // WHEN
48
+ await handler.retrieve(
49
+ 'testInstance/testBU',
50
+ ['dataFilter'],
51
+ ['testExisting_dataFilter']
52
+ );
53
+ // THEN
54
+ assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error');
55
+ // get results from cache
56
+ const result = cache.getCache();
57
+ assert.equal(
58
+ result.dataFilter ? Object.keys(result.dataFilter).length : 0,
59
+ 1,
60
+ 'only one dataFilter expected'
61
+ );
62
+ assert.deepEqual(
63
+ await testUtils.getActualJson('testExisting_dataFilter', 'dataFilter'),
64
+ await testUtils.getExpectedJson('9999999', 'dataFilter', 'get'),
65
+ 'returned JSON was not equal expected'
66
+ );
67
+ assert.equal(
68
+ testUtils.getAPIHistoryLength(),
69
+ 7,
70
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
71
+ );
72
+ return;
73
+ });
74
+ });
75
+
76
+ describe('Deploy ================', () => {
77
+ beforeEach(() => {
78
+ testUtils.mockSetup(true);
79
+ });
80
+
81
+ it('Should create & upsert a dataFilter', async () => {
82
+ // WHEN
83
+
84
+ await handler.deploy('testInstance/testBU', ['dataFilter']);
85
+ // THEN
86
+ assert.equal(process.exitCode, 0, 'deploy should not have thrown an error');
87
+ // get results from cache
88
+ const result = cache.getCache();
89
+ assert.equal(
90
+ result.dataFilter ? Object.keys(result.dataFilter).length : 0,
91
+ 2,
92
+ 'unexptected number of dataFilters in cache'
93
+ );
94
+ // confirm created item
95
+ assert.deepEqual(
96
+ await testUtils.getActualJson('testNew_dataFilter', 'dataFilter'),
97
+ await testUtils.getExpectedJson('9999999', 'dataFilter', 'post'),
98
+ 'returned new-JSON was not equal expected for insert dataFilter'
99
+ );
100
+ // confirm updated item
101
+ assert.deepEqual(
102
+ await testUtils.getActualJson('testExisting_dataFilter', 'dataFilter'),
103
+ await testUtils.getExpectedJson('9999999', 'dataFilter', 'patch'),
104
+ 'returned existing-JSON was not equal expected for update dataFilter'
105
+ );
106
+ // check number of API calls
107
+ assert.equal(
108
+ testUtils.getAPIHistoryLength(),
109
+ 8,
110
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
111
+ );
112
+ return;
113
+ });
114
+ });
115
+
116
+ describe('Templating ================', () => {
117
+ it('Should create a dataFilter template via buildTemplate and build it', async () => {
118
+ // download first before we test buildTemplate
119
+ await handler.retrieve('testInstance/testBU', ['dataFilter']);
120
+ // buildTemplate
121
+ const result = await handler.buildTemplate(
122
+ 'testInstance/testBU',
123
+ 'dataFilter',
124
+ ['testExisting_dataFilter'],
125
+ ['testSourceMarket']
126
+ );
127
+ assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error');
128
+ assert.equal(
129
+ result.dataFilter ? Object.keys(result.dataFilter).length : 0,
130
+ 1,
131
+ 'only one dataFilter expected'
132
+ );
133
+ assert.deepEqual(
134
+ await testUtils.getActualTemplateJson('testExisting_dataFilter', 'dataFilter'),
135
+ await testUtils.getExpectedJson('9999999', 'dataFilter', 'template'),
136
+ 'returned template JSON was not equal expected'
137
+ );
138
+ // buildDefinition
139
+ await handler.buildDefinition(
140
+ 'testInstance/testBU',
141
+ 'dataFilter',
142
+ ['testExisting_dataFilter'],
143
+ ['testTargetMarket']
144
+ );
145
+ assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error');
146
+ assert.deepEqual(
147
+ await testUtils.getActualDeployJson('testTemplated_dataFilter', 'dataFilter'),
148
+ await testUtils.getExpectedJson('9999999', 'dataFilter', 'build'),
149
+ 'returned deployment JSON was not equal expected'
150
+ );
151
+ assert.equal(
152
+ testUtils.getAPIHistoryLength(),
153
+ 6,
154
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
155
+ );
156
+ return;
157
+ });
158
+ });
159
+
160
+ describe('Delete ================', () => {
161
+ it('Should delete the item', async () => {
162
+ // WHEN
163
+ const isDeleted = await handler.deleteByKey(
164
+ 'testInstance/testBU',
165
+ 'dataFilter',
166
+ 'testExisting_dataFilter'
167
+ );
168
+ // THEN
169
+ assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error');
170
+ assert.equal(isDeleted, true, 'deleteByKey should have returned true');
171
+ return;
172
+ });
173
+ });
174
+ });
@@ -0,0 +1,170 @@
1
+ import * as chai from 'chai';
2
+ const assert = chai.assert;
3
+
4
+ import chaiFiles from 'chai-files';
5
+ import cache from '../lib/util/cache.js';
6
+ import * as testUtils from './utils.js';
7
+ import handler from '../lib/index.js';
8
+ chai.use(chaiFiles);
9
+
10
+ describe('type: filter', () => {
11
+ beforeEach(() => {
12
+ testUtils.mockSetup();
13
+ });
14
+
15
+ afterEach(() => {
16
+ testUtils.mockReset();
17
+ });
18
+
19
+ describe('Retrieve ================', () => {
20
+ it('Should retrieve a filter', async () => {
21
+ // WHEN
22
+ await handler.retrieve('testInstance/testBU', ['filter']);
23
+ // THEN
24
+ assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error');
25
+ // get results from cache
26
+ const result = cache.getCache();
27
+ assert.equal(
28
+ result.filter ? Object.keys(result.filter).length : 0,
29
+ 1,
30
+ 'unexpected number of items retrieved'
31
+ );
32
+ assert.deepEqual(
33
+ await testUtils.getActualJson('testExisting_filter', 'filter'),
34
+ await testUtils.getExpectedJson('9999999', 'filter', 'get'),
35
+ 'returned JSON was not equal expected'
36
+ );
37
+
38
+ assert.equal(
39
+ testUtils.getAPIHistoryLength(),
40
+ 14,
41
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
42
+ );
43
+ return;
44
+ });
45
+
46
+ it('Should retrieve a filter by key', async () => {
47
+ // WHEN
48
+ await handler.retrieve('testInstance/testBU', ['filter'], ['testExisting_filter']);
49
+ // THEN
50
+ assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error');
51
+ // get results from cache
52
+ const result = cache.getCache();
53
+ assert.equal(
54
+ result.filter ? Object.keys(result.filter).length : 0,
55
+ 1,
56
+ 'only one filter expected'
57
+ );
58
+ assert.deepEqual(
59
+ await testUtils.getActualJson('testExisting_filter', 'filter'),
60
+ await testUtils.getExpectedJson('9999999', 'filter', 'get'),
61
+ 'returned JSON was not equal expected'
62
+ );
63
+ assert.equal(
64
+ testUtils.getAPIHistoryLength(),
65
+ 15,
66
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
67
+ );
68
+ return;
69
+ });
70
+ });
71
+
72
+ describe('Deploy ================', () => {
73
+ beforeEach(() => {
74
+ testUtils.mockSetup(true);
75
+ });
76
+
77
+ it('Should create & upsert a filter', async () => {
78
+ // WHEN
79
+
80
+ await handler.deploy('testInstance/testBU', ['filter']);
81
+ // THEN
82
+ assert.equal(process.exitCode, 0, 'deploy should not have thrown an error');
83
+ // get results from cache
84
+ const result = cache.getCache();
85
+ assert.equal(
86
+ result.filter ? Object.keys(result.filter).length : 0,
87
+ 2,
88
+ 'unexptected number of filters in cache'
89
+ );
90
+ // confirm created item
91
+ assert.deepEqual(
92
+ await testUtils.getActualJson('testNew_filter', 'filter'),
93
+ await testUtils.getExpectedJson('9999999', 'filter', 'post'),
94
+ 'returned new-JSON was not equal expected for insert filter'
95
+ );
96
+ // confirm updated item
97
+ assert.deepEqual(
98
+ await testUtils.getActualJson('testExisting_filter', 'filter'),
99
+ await testUtils.getExpectedJson('9999999', 'filter', 'patch'),
100
+ 'returned existing-JSON was not equal expected for update filter'
101
+ );
102
+ // check number of API calls
103
+ assert.equal(
104
+ testUtils.getAPIHistoryLength(),
105
+ 17,
106
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
107
+ );
108
+ return;
109
+ });
110
+ });
111
+
112
+ describe('Templating ================', () => {
113
+ it('Should create a filter template via buildTemplate and build it', async () => {
114
+ // download first before we test buildTemplate
115
+ await handler.retrieve('testInstance/testBU', ['filter']);
116
+ // buildTemplate
117
+ const result = await handler.buildTemplate(
118
+ 'testInstance/testBU',
119
+ 'filter',
120
+ ['testExisting_filter'],
121
+ ['testSourceMarket']
122
+ );
123
+ assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error');
124
+ assert.equal(
125
+ result.filter ? Object.keys(result.filter).length : 0,
126
+ 1,
127
+ 'only one filter expected'
128
+ );
129
+ assert.deepEqual(
130
+ await testUtils.getActualTemplateJson('testExisting_filter', 'filter'),
131
+ await testUtils.getExpectedJson('9999999', 'filter', 'template'),
132
+ 'returned template JSON was not equal expected'
133
+ );
134
+ // buildDefinition
135
+ await handler.buildDefinition(
136
+ 'testInstance/testBU',
137
+ 'filter',
138
+ ['testExisting_filter'],
139
+ ['testTargetMarket']
140
+ );
141
+ assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error');
142
+ assert.deepEqual(
143
+ await testUtils.getActualDeployJson('testTemplated_filter', 'filter'),
144
+ await testUtils.getExpectedJson('9999999', 'filter', 'build'),
145
+ 'returned deployment JSON was not equal expected'
146
+ );
147
+ assert.equal(
148
+ testUtils.getAPIHistoryLength(),
149
+ 14,
150
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
151
+ );
152
+ return;
153
+ });
154
+ });
155
+
156
+ describe('Delete ================', () => {
157
+ it('Should delete the item', async () => {
158
+ // WHEN
159
+ const isDeleted = await handler.deleteByKey(
160
+ 'testInstance/testBU',
161
+ 'filter',
162
+ 'testExisting_filter'
163
+ );
164
+ // THEN
165
+ assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error');
166
+ assert.equal(isDeleted, true, 'deleteByKey should have returned true');
167
+ return;
168
+ });
169
+ });
170
+ });
@@ -26,7 +26,7 @@ describe('type: journey', () => {
26
26
  const result = cache.getCache();
27
27
  assert.equal(
28
28
  result.journey ? Object.keys(result.journey).length : 0,
29
- 4,
29
+ 5,
30
30
  'unexpected number of journeys'
31
31
  );
32
32
  assert.deepEqual(
@@ -46,7 +46,7 @@ describe('type: journey', () => {
46
46
  );
47
47
  assert.equal(
48
48
  testUtils.getAPIHistoryLength(),
49
- 27,
49
+ 29,
50
50
  'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
51
51
  );
52
52
  return;
@@ -111,6 +111,36 @@ describe('type: journey', () => {
111
111
  return;
112
112
  });
113
113
 
114
+ it('Should retrieve a journey containing an UPDATECONTACTDATA activity with key', async () => {
115
+ // WHEN
116
+ await handler.retrieve(
117
+ 'testInstance/testBU',
118
+ ['journey'],
119
+ ['testExisting_journey_updatecontact']
120
+ );
121
+ // THEN
122
+ assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error');
123
+ // get results from cache
124
+ const result = cache.getCache();
125
+ assert.equal(
126
+ result.journey ? Object.keys(result.journey).length : 0,
127
+ 1,
128
+ 'only 1 journeys expected'
129
+ );
130
+
131
+ assert.deepEqual(
132
+ await testUtils.getActualJson('testExisting_journey_updatecontact', 'journey'),
133
+ await testUtils.getExpectedJson('9999999', 'journey', 'get-updatecontact'),
134
+ 'returned JSON was not equal expected'
135
+ );
136
+ assert.equal(
137
+ testUtils.getAPIHistoryLength(),
138
+ 20,
139
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
140
+ );
141
+ return;
142
+ });
143
+
114
144
  it('Should retrieve a Transactional Email journey with key', async () => {
115
145
  // WHEN
116
146
  await handler.retrieve('testInstance/testBU', ['journey'], ['testExisting_temail']);
@@ -425,6 +455,29 @@ describe('type: journey', () => {
425
455
  );
426
456
  return;
427
457
  });
458
+
459
+ it('Should update a journey with UPDATECONTACT activity', async () => {
460
+ // WHEN
461
+ await handler.deploy(
462
+ 'testInstance/testBU',
463
+ ['journey'],
464
+ ['testExisting_journey_updatecontact']
465
+ );
466
+ // THEN
467
+ assert.equal(process.exitCode, 0, 'deploy should not have thrown an error');
468
+ // // confirm updated item
469
+ assert.deepEqual(
470
+ await testUtils.getActualJson('testExisting_journey_updatecontact', 'journey'),
471
+ await testUtils.getExpectedJson('9999999', 'journey', 'put-updatecontact'),
472
+ 'returned metadata was not equal expected for update journey with updatecontact activity'
473
+ );
474
+ assert.equal(
475
+ testUtils.getAPIHistoryLength(),
476
+ 22,
477
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
478
+ );
479
+ return;
480
+ });
428
481
  });
429
482
 
430
483
  describe('Templating ================', () => {
@@ -466,7 +519,7 @@ describe('type: journey', () => {
466
519
 
467
520
  assert.equal(
468
521
  testUtils.getAPIHistoryLength(),
469
- 27,
522
+ 29,
470
523
  'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
471
524
  );
472
525
  return;
@@ -662,7 +715,7 @@ describe('type: journey', () => {
662
715
 
663
716
  assert.equal(
664
717
  testUtils.getAPIHistoryLength(),
665
- 33,
718
+ 35,
666
719
  'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
667
720
  );
668
721
  return;
@@ -697,7 +750,7 @@ describe('type: journey', () => {
697
750
 
698
751
  assert.equal(
699
752
  testUtils.getAPIHistoryLength(),
700
- 33,
753
+ 35,
701
754
  'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
702
755
  );
703
756
  return;
@@ -732,7 +785,7 @@ describe('type: journey', () => {
732
785
 
733
786
  assert.equal(
734
787
  testUtils.getAPIHistoryLength(),
735
- 33,
788
+ 35,
736
789
  'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
737
790
  );
738
791
  return;
@@ -1329,7 +1382,6 @@ describe('type: journey', () => {
1329
1382
  ['testExisting_temail', 'testExisting_journey_Multistep'],
1330
1383
  'should have found the right journeys that need updating'
1331
1384
  );
1332
-
1333
1385
  assert.equal(
1334
1386
  testUtils.getAPIHistoryLength(),
1335
1387
  42,
@@ -648,7 +648,7 @@ describe('type: query', () => {
648
648
  // check number of API calls
649
649
  assert.equal(
650
650
  testUtils.getAPIHistoryLength(),
651
- 46,
651
+ 47,
652
652
  'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
653
653
  );
654
654
  return;
@@ -690,7 +690,7 @@ describe('type: query', () => {
690
690
  // check number of API calls
691
691
  assert.equal(
692
692
  testUtils.getAPIHistoryLength(),
693
- 48,
693
+ 49,
694
694
  'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
695
695
  );
696
696
  return;
package/test/utils.js CHANGED
@@ -7,6 +7,7 @@ import auth from '../lib/util/auth.js';
7
7
  import { Util } from '../lib/util/util.js';
8
8
  import cache from '../lib/util/cache.js';
9
9
  import ReplaceContentBlockReference from '../lib/util/replaceContentBlockReference.js';
10
+ import MetadataTypes from '../lib/MetadataTypeInfo.js';
10
11
 
11
12
  import { fileURLToPath } from 'node:url';
12
13
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -191,6 +192,13 @@ export function getExpectedFile(mid, type, action, ext) {
191
192
  */
192
193
  export function mockSetup(isDeploy) {
193
194
  cache.clearCache();
195
+ // clear local caches
196
+ for (const type of Object.keys(MetadataTypes)) {
197
+ if (MetadataTypes[type].cache) {
198
+ // we rarely use a local cache in types which also needs to be reset
199
+ MetadataTypes[type].cache = {};
200
+ }
201
+ }
194
202
  // no need to execute this again if we ran it a 2nd time for deploy - already done in standard setup
195
203
  if (!isDeploy) {
196
204
  // reset all options to default
package/types/mcdev.d.js CHANGED
@@ -385,6 +385,96 @@
385
385
  * @property {string} [downloadBUs] used by mcdev init to directly push to a remote
386
386
  */
387
387
 
388
+ /**
389
+ * @typedef {object} FilterItem
390
+ * @property {number} categoryId folder id
391
+ * @property {string} [createdDate] -
392
+ * @property {string} customerKey key
393
+ * @property {string} destinationObjectId DE/List ID
394
+ * @property {1|2|3|4} destinationTypeId 1:SubscriberList, 2:DataExtension, 3:GroupWizard, 4:BehavioralData
395
+ * @property {string} filterActivityId ?
396
+ * @property {string} filterDefinitionId ObjectID of filterDefinition
397
+ * @property {string} modifiedDate -
398
+ * @property {string} name name
399
+ * @property {string} [description] -
400
+ * @property {string} sourceObjectId DE/List ID
401
+ * @property {null} resultGroupFolderId required for upsert; unknown purpose; set to null
402
+ * @property {null} resultGroupName required for upsert; unknown purpose; set to null
403
+ * @property {null} sourceId required for upsert; unknown purpose; set to null
404
+ * @property {1|2|3|4} sourceTypeId 1:SubscriberList, 2:DataExtension, 3:GroupWizard, 4:BehavioralData
405
+ * @property {1|2|3|4} [filterDefinitionSourceTypeId] seems to be a duplicate of sourceTypeId?
406
+ * @property {string} [resultDEDescription] description of destination DE
407
+ * @property {string} [resultDEName] name of destination DE
408
+ * @property {string} [resultDEKey] key of destination DE
409
+ * @property {number} statusId ?
410
+ * @property {string} [r__dataFilter_key] relationship to filterDefinition
411
+ * @property {string} [r__source_dataExtension_key] relationship to dataExtension source
412
+ * @property {string} [r__destination_dataExtension_key] relationship to dataExtension destination
413
+ * @property {string} [r__folder_Path] relationship to folder
414
+ * @typedef {Object.<string, FilterItem>} FilterMap
415
+ */
416
+
417
+ /**
418
+ * /automation/v1/filterdefinitions/<id> (not used)
419
+ *
420
+ * @typedef {object} AutomationFilterDefinitionItem
421
+ * @property {string} id object id
422
+ * @property {string} key external key
423
+ * @property {string} createdDate -
424
+ * @property {number} createdBy user id
425
+ * @property {string} createdName -
426
+ * @property {string} [description] (omitted by API if empty)
427
+ * @property {string} modifiedDate -
428
+ * @property {number} modifiedBy user id
429
+ * @property {string} modifiedName -
430
+ * @property {string} name name
431
+ * @property {string} categoryId folder id
432
+ * @property {string} filterDefinitionXml from REST API defines the filter in XML form
433
+ * @property {1|2} derivedFromType 1:list/profile attributes/measures, 2: dataExtension
434
+ * @property {boolean} isSendable ?
435
+ */
436
+ /**
437
+ * /email/v1/filters/filterdefinition/<id>
438
+ *
439
+ * @typedef {object} DataFilterItem
440
+ * @property {string} id object id
441
+ * @property {string} key external key
442
+ * @property {string} createdDate date
443
+ * @property {number} createdBy user id
444
+ * @property {string} createdName name
445
+ * @property {string} [description] (omitted by API if empty)
446
+ * @property {string} lastUpdated date
447
+ * @property {number} lastUpdatedBy user id
448
+ * @property {string} lastUpdatedName name
449
+ * @property {string} name name
450
+ * @property {string} categoryId folder id
451
+ * @property {string} filterDefinitionXml from REST API defines the filter in XML form
452
+ * @property {1|2} derivedFromType 1:list/profile attributes/measures, 2: dataExtension
453
+ * @property {string} derivedFromObjectId Id of DataExtension - present if derivedFromType=2
454
+ * @property {'DataExtension'|'SubscriberAttributes'} derivedFromObjectTypeName -
455
+ * @property {string} [derivedFromObjectName] name of DataExtension
456
+ * @property {boolean} isSendable ?
457
+ * @property {object} [c__filterDefinition] copied from SOAP API, defines the filter in readable form
458
+ * @property {FilterConditionSet} c__filterDefinition.ConditionSet -
459
+ * @property {string} [r__source_list_PathName] relationship to list source (if derivedFromType=1)
460
+ * @property {string} [r__source_dataExtension_key] relationship to dataExtension source (if derivedFromType=2)
461
+ */
462
+ /**
463
+ * @typedef {object} FilterConditionSet
464
+ * @property {FilterCondition | FilterCondition[]} Condition -
465
+ * @property {FilterConditionSet} ConditionSet -
466
+ */
467
+ /**
468
+ * @typedef {object} FilterCondition
469
+ * @property {'IsEmpty'|'IsNotEmpty'|'Equals'} Operator comparison operator (actually \@_Operator)
470
+ * @property {string} [ID] object id of field (actually \@_ID)
471
+ * @property {string} [Value] filter value to compare against
472
+ * @property {string} [r__dataExtensionField_name] name of field
473
+ */
474
+ /**
475
+ * @typedef {Object.<string, DataFilterItem>} DataFilterMap
476
+ */
477
+
388
478
  /**
389
479
  * @typedef {object} AuthObject
390
480
  * @property {string} client_id client_id client_id for sfmc-sdk auth
@@ -673,4 +763,15 @@ complex
673
763
  * @property {string} [deColumn] for bulk-creation only: instead of an array in addresses, specify the name of a DE column/field here
674
764
  */
675
765
 
766
+ /**
767
+ * @typedef {object} BuildFilter
768
+ * @property {BuildFilterKeys} [include] include key filters
769
+ * @property {BuildFilterKeys} [exclude] exclude key filters
770
+ */
771
+
772
+ /**
773
+ * @typedef {object} BuildFilterKeys
774
+ * @property {Object.<"*"|SupportedMetadataTypes, string[]>} [key] object with keys representing metadata types ("*" for all types, or specific type names) and values being arrays of string patterns to match against
775
+ */
776
+
676
777
  export default {};