mcdev 8.1.0 → 8.2.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 (47) hide show
  1. package/.github/ISSUE_TEMPLATE/bug.yml +1 -0
  2. package/.github/workflows/code-test.yml +2 -2
  3. package/.github/workflows/coverage-base-update.yml +3 -3
  4. package/.github/workflows/coverage-develop-branch.yml +3 -3
  5. package/.github/workflows/coverage-main-branch.yml +3 -3
  6. package/.github/workflows/coverage.yml +4 -4
  7. package/.github/workflows/npm-publish.yml +4 -4
  8. package/@types/lib/MetadataTypeDefinitions.d.ts +2 -0
  9. package/@types/lib/MetadataTypeDefinitions.d.ts.map +1 -1
  10. package/@types/lib/MetadataTypeInfo.d.ts +2 -0
  11. package/@types/lib/MetadataTypeInfo.d.ts.map +1 -1
  12. package/@types/lib/index.d.ts.map +1 -1
  13. package/@types/lib/metadataTypes/Asset.d.ts.map +1 -1
  14. package/@types/lib/metadataTypes/Journey.d.ts.map +1 -1
  15. package/@types/lib/metadataTypes/MetadataType.d.ts.map +1 -1
  16. package/@types/lib/metadataTypes/TriggeredSendSummary.d.ts +257 -0
  17. package/@types/lib/metadataTypes/TriggeredSendSummary.d.ts.map +1 -0
  18. package/@types/lib/metadataTypes/definitions/TriggeredSendSummary.definition.d.ts +208 -0
  19. package/@types/lib/metadataTypes/definitions/TriggeredSendSummary.definition.d.ts.map +1 -0
  20. package/@types/lib/util/devops.d.ts +2 -1
  21. package/@types/lib/util/devops.d.ts.map +1 -1
  22. package/@types/lib/util/util.d.ts +2 -1
  23. package/@types/lib/util/util.d.ts.map +1 -1
  24. package/lib/MetadataTypeDefinitions.js +2 -0
  25. package/lib/MetadataTypeInfo.js +2 -0
  26. package/lib/cli.js +5 -0
  27. package/lib/index.js +26 -4
  28. package/lib/metadataTypes/Asset.js +30 -7
  29. package/lib/metadataTypes/Automation.js +1 -1
  30. package/lib/metadataTypes/Folder.js +1 -1
  31. package/lib/metadataTypes/Journey.js +5 -2
  32. package/lib/metadataTypes/MetadataType.js +8 -2
  33. package/lib/metadataTypes/TriggeredSendSummary.js +102 -0
  34. package/lib/metadataTypes/definitions/TriggeredSendSummary.definition.js +211 -0
  35. package/lib/util/devops.js +25 -8
  36. package/lib/util/util.js +13 -4
  37. package/package.json +10 -10
  38. package/test/mockRoot/.mcdevrc.json +1 -1
  39. package/test/resources/1111111/dataFolder/retrieve-ContentTypeINdataextension,hidden,queryactivity,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml +26 -0
  40. package/test/resources/9999999/automation/create-testNew_automation-expected.md +1 -1
  41. package/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md +1 -1
  42. package/test/resources/9999999/automation/update-testExisting_automation-expected.md +1 -1
  43. package/test/resources/9999999/triggeredSendSummary/get-expected.json +24 -0
  44. package/test/resources/9999999/triggeredSendSummary/retrieve-response.xml +49 -0
  45. package/test/type.dataExtension.test.js +41 -0
  46. package/test/type.journey.test.js +37 -2
  47. package/test/type.triggeredSendSummary.test.js +45 -0
@@ -0,0 +1,211 @@
1
+ export default {
2
+ bodyIteratorField: 'Results',
3
+ dependencies: [
4
+ 'triggeredSend',
5
+ 'folder-hidden',
6
+ 'folder-triggered_send',
7
+ 'folder-triggered_send_journeybuilder',
8
+ ],
9
+ dependencyGraph: {
10
+ triggeredSend: ['r__triggeredSend_key'],
11
+ },
12
+ filter: {},
13
+ hasExtended: false,
14
+ idField: 'ObjectID',
15
+ keepId: false,
16
+ keyIsFixed: true,
17
+ keyField: 'CustomerKey',
18
+ nameField: 'r__triggeredSend_name',
19
+ folderIdField: 'TriggeredSend.CategoryID',
20
+ createdDateField: null,
21
+ createdNameField: null,
22
+ lastmodDateField: null,
23
+ lastmodNameField: null,
24
+ restPagination: null,
25
+ maxKeyLength: 36,
26
+ type: 'triggeredSendSummary',
27
+ soapType: 'triggeredSendSummary',
28
+ typeDescription: 'Summary data for a Triggered Send',
29
+ typeRetrieveByDefault: false,
30
+ typeCdpByDefault: false,
31
+ typeName: 'Triggered Send Summary',
32
+ fields: {
33
+ Bounces: {
34
+ isCreateable: true,
35
+ isUpdateable: false,
36
+ retrieving: true,
37
+ templating: true,
38
+ },
39
+ Clicks: {
40
+ isCreateable: true,
41
+ isUpdateable: false,
42
+ retrieving: true,
43
+ templating: true,
44
+ },
45
+ 'Client.ID': {
46
+ isCreateable: false,
47
+ isUpdateable: false,
48
+ retrieving: false,
49
+ templating: false,
50
+ },
51
+ Conversions: {
52
+ isCreateable: true,
53
+ isUpdateable: false,
54
+ retrieving: true,
55
+ templating: true,
56
+ },
57
+ CustomerKey: {
58
+ isCreateable: true,
59
+ isUpdateable: true,
60
+ retrieving: true,
61
+ templating: true,
62
+ },
63
+ FTAFEmailsSent: {
64
+ isCreateable: true,
65
+ isUpdateable: false,
66
+ retrieving: true,
67
+ templating: true,
68
+ },
69
+ FTAFOptIns: {
70
+ isCreateable: true,
71
+ isUpdateable: false,
72
+ retrieving: true,
73
+ templating: true,
74
+ },
75
+ FTAFRequests: {
76
+ isCreateable: true,
77
+ isUpdateable: false,
78
+ retrieving: true,
79
+ templating: true,
80
+ },
81
+ ID: {
82
+ isCreateable: false,
83
+ isUpdateable: false,
84
+ retrieving: false,
85
+ templating: false,
86
+ },
87
+ InProcess: {
88
+ isCreateable: true,
89
+ isUpdateable: false,
90
+ retrieving: true,
91
+ templating: true,
92
+ },
93
+ NotSentDueToError: {
94
+ isCreateable: true,
95
+ isUpdateable: false,
96
+ retrieving: true,
97
+ templating: true,
98
+ },
99
+ NotSentDueToOptOut: {
100
+ isCreateable: true,
101
+ isUpdateable: false,
102
+ retrieving: true,
103
+ templating: true,
104
+ },
105
+ NotSentDueToUndeliverable: {
106
+ isCreateable: true,
107
+ isUpdateable: false,
108
+ retrieving: true,
109
+ templating: true,
110
+ },
111
+ ObjectID: {
112
+ isCreateable: false,
113
+ isUpdateable: false,
114
+ retrieving: false,
115
+ templating: false,
116
+ },
117
+ /* ObjectState: {
118
+ isCreateable: false,
119
+ isUpdateable: false,
120
+ retrieving: false,
121
+ templating: false,
122
+ }, */ // according to the documentation"Reserved for future use"
123
+ Opens: {
124
+ isCreateable: true,
125
+ isUpdateable: false,
126
+ retrieving: true,
127
+ templating: true,
128
+ },
129
+ OptOuts: {
130
+ isCreateable: true,
131
+ isUpdateable: false,
132
+ retrieving: true,
133
+ templating: true,
134
+ },
135
+ Owner: {
136
+ isCreateable: false,
137
+ isUpdateable: false,
138
+ retrieving: false,
139
+ templating: false,
140
+ },
141
+ PartnerKey: {
142
+ isCreateable: false,
143
+ isUpdateable: false,
144
+ retrieving: false,
145
+ templating: false,
146
+ },
147
+ PartnerProperties: {
148
+ isCreateable: false,
149
+ isUpdateable: false,
150
+ retrieving: false,
151
+ templating: false,
152
+ },
153
+ Queued: {
154
+ isCreateable: true,
155
+ isUpdateable: false,
156
+ retrieving: true,
157
+ templating: true,
158
+ },
159
+ Sent: {
160
+ isCreateable: true,
161
+ isUpdateable: false,
162
+ retrieving: true,
163
+ templating: true,
164
+ },
165
+ SurveyResponses: {
166
+ isCreateable: true,
167
+ isUpdateable: false,
168
+ retrieving: true,
169
+ templating: true,
170
+ },
171
+ UniqueClicks: {
172
+ isCreateable: true,
173
+ isUpdateable: false,
174
+ retrieving: true,
175
+ templating: true,
176
+ },
177
+ UniqueConversions: {
178
+ isCreateable: true,
179
+ isUpdateable: false,
180
+ retrieving: true,
181
+ templating: true,
182
+ },
183
+ UniqueOpens: {
184
+ isCreateable: true,
185
+ isUpdateable: false,
186
+ retrieving: true,
187
+ templating: true,
188
+ },
189
+ CorrelationID: {
190
+ isCreateable: false,
191
+ isUpdateable: false,
192
+ retrieving: false,
193
+ templating: false,
194
+ },
195
+ CreatedDate: {
196
+ isCreateable: false,
197
+ isUpdateable: false,
198
+ retrieving: false /** Listed in the type documentation but not retrievable */,
199
+ templating: false,
200
+ },
201
+ ModifiedDate: {
202
+ isCreateable: false,
203
+ isUpdateable: false,
204
+ retrieving: false /** Listed in the type documentation but not retrievable */,
205
+ templating: false,
206
+ },
207
+ r__triggeredSend_name: { skipValidation: true },
208
+ r__triggeredSend_key: { skipValidation: true },
209
+ r__folder_Path: { skipValidation: true },
210
+ },
211
+ };
@@ -195,10 +195,13 @@ const DevOps = {
195
195
  // - retrieve/cred/bu/asset/block/016aecc7-7063-4b78-93f4-aa119ea933c7.asset-block-meta.html
196
196
  // - retrieve/cred/bu/asset/message/003c1ef5-f538-473a-91da-26942024a64a/blocks/views.html.slots.[bottom-8frq7iw2k99].asset-message-meta.html
197
197
  // - retrieve/cred/bu/query/03efd5f1-ba1f-487a-9c9a-36aeb2ae5192.query-meta.sql
198
- file.externalKey =
199
- file.type === 'asset'
200
- ? file.file.split('/')[5].split('.')[0] // assets have an additional folder level for their subtype
201
- : file.file.split('/')[4].split('.')[0];
198
+ // assets have an additional folder level for their subtype
199
+ // keys could contain dots themselves
200
+ file.externalKey = file.file
201
+ .split('/')
202
+ [file.type === 'asset' ? 5 : 4].split('.')
203
+ .slice(0, -2)
204
+ .join('.');
202
205
  file.name = null;
203
206
  }
204
207
 
@@ -267,8 +270,14 @@ const DevOps = {
267
270
  }
268
271
  // Write into delta.json to serve as documentation
269
272
  const directoryDeltaPkg = 'logs/';
270
- await File.writeJSONToFile(directoryDeltaPkg, Util.logFileName + '-delta_package', delta);
271
- this.document(directoryDeltaPkg, delta);
273
+ await File.writeJSONToFile(
274
+ directoryDeltaPkg,
275
+ Util.logFileName +
276
+ '-delta_package-' +
277
+ filterPathsCSV.replaceAll(',', '-').replaceAll('/', '-'),
278
+ delta
279
+ );
280
+ this.document(directoryDeltaPkg, filterPathsCSV, delta);
272
281
  Util.logger.info(
273
282
  `- ✔️ Identified changes: Add/Update=${gitActionsCounter['add/update']}, Move=${gitActionsCounter['move']}, Delete=${gitActionsCounter['delete']}`
274
283
  );
@@ -572,10 +581,11 @@ const DevOps = {
572
581
  * create markdown file for deployment listing
573
582
  *
574
583
  * @param {string} directory -
584
+ * @param {string} filterPathsCSV -
575
585
  * @param {object} jsonReport -
576
586
  * @returns {void}
577
587
  */
578
- document(directory, jsonReport) {
588
+ document(directory, filterPathsCSV, jsonReport) {
579
589
  const tabled = jsonToTable(jsonReport);
580
590
  let output = `# Deployment Report\n\n`;
581
591
  let tableSeparator = '';
@@ -597,7 +607,14 @@ const DevOps = {
597
607
  }
598
608
  try {
599
609
  // write to disk (asynchronously)
600
- File.writeToFile(directory, Util.logFileName + '-delta_package', 'md', output);
610
+ File.writeToFile(
611
+ directory,
612
+ Util.logFileName +
613
+ '-delta_package-' +
614
+ filterPathsCSV.replaceAll(',', '-').replaceAll('/', '-'),
615
+ 'md',
616
+ output
617
+ );
601
618
  } catch (ex) {
602
619
  Util.logger.error(`DevOps.document():: error | ` + ex.message);
603
620
  }
package/lib/util/util.js CHANGED
@@ -1143,14 +1143,17 @@ export const Util = {
1143
1143
  * returns true if no LIKE filter is defined or if all filters match
1144
1144
  *
1145
1145
  * @param {MetadataTypeItem} metadata a single metadata item
1146
+ * @param {object} definition type definition
1146
1147
  * @param {object} [filters] only used in recursive calls
1147
1148
  * @returns {boolean} true if no LIKE filter is defined or if all filters match
1148
1149
  */
1149
- fieldsLike(metadata, filters) {
1150
+ fieldsLike(metadata, definition, filters) {
1150
1151
  if (metadata.json && metadata.codeArr) {
1151
1152
  // Compensate for CodeExtractItem format
1152
1153
  metadata = metadata.json;
1153
1154
  }
1155
+ // ensure we only convert "key" and "name" fields on the first call to this method
1156
+ const checkDefaultKeyAndName = filters ? false : true;
1154
1157
  filters ||= Util.OPTIONS.like;
1155
1158
  if (!filters) {
1156
1159
  return true;
@@ -1163,14 +1166,20 @@ export const Util = {
1163
1166
  ? filters[field].split(',')
1164
1167
  : filters[field];
1165
1168
  if (Array.isArray(metadata[field])) {
1166
- return metadata[field].some((f) => Util.fieldsLike(f, filter));
1169
+ return metadata[field].some((f) => Util.fieldsLike(f, definition, filter));
1167
1170
  } else {
1171
+ let fieldName;
1172
+ if (field === 'key' && checkDefaultKeyAndName) {
1173
+ fieldName = definition.keyField;
1174
+ } else if (field === 'name' && checkDefaultKeyAndName) {
1175
+ fieldName = definition.nameField;
1176
+ }
1168
1177
  if (typeof filter === 'string') {
1169
- return Util.stringLike(metadata[field], filter);
1178
+ return Util.stringLike(metadata[fieldName || field], filter);
1170
1179
  } else if (Array.isArray(filter)) {
1171
1180
  return filter.some((f) => Util.stringLike(metadata[field], f));
1172
1181
  } else if (typeof filter === 'object') {
1173
- return Util.fieldsLike(metadata[field], filter);
1182
+ return Util.fieldsLike(metadata[field], definition, filter);
1174
1183
  }
1175
1184
  }
1176
1185
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcdev",
3
- "version": "8.1.0",
3
+ "version": "8.2.0",
4
4
  "description": "Accenture Salesforce Marketing Cloud DevTools",
5
5
  "author": "Accenture: joern.berkefeld, douglas.midgley, robert.zimmermann, maciej.barnas",
6
6
  "license": "MIT",
@@ -80,21 +80,21 @@
80
80
  "p-limit": "6.2.0",
81
81
  "prettier": "3.5.3",
82
82
  "prettier-plugin-sql": "0.19.0",
83
- "semver": "7.7.1",
83
+ "semver": "7.7.3",
84
84
  "sfmc-sdk": "2.1.2",
85
- "simple-git": "3.27.0",
85
+ "simple-git": "3.29.0",
86
86
  "toposort": "2.0.2",
87
87
  "update-notifier": "7.3.1",
88
88
  "winston": "3.17.0",
89
89
  "yargs": "17.7.2",
90
- "yocto-spinner": "0.2.2"
90
+ "yocto-spinner": "1.0.0"
91
91
  },
92
92
  "devDependencies": {
93
93
  "@eslint/js": "9.28.0",
94
94
  "@types/fs-extra": "11.0.4",
95
95
  "@types/inquirer": "9.0.7",
96
96
  "@types/mocha": "10.0.8",
97
- "@types/node": "22.15.29",
97
+ "@types/node": "24.9.1",
98
98
  "@types/yargs": "17.0.33",
99
99
  "assert": "2.1.0",
100
100
  "axios-mock-adapter": "2.0.0",
@@ -104,17 +104,17 @@
104
104
  "eslint": "9.28.0",
105
105
  "eslint-config-ssjs": "2.0.0",
106
106
  "eslint-plugin-jsdoc": "50.7.1",
107
- "eslint-plugin-mocha": "11.0.0",
107
+ "eslint-plugin-mocha": "11.2.0",
108
108
  "eslint-plugin-prettier": "5.4.1",
109
109
  "eslint-plugin-unicorn": "59.0.1",
110
- "fast-xml-parser": "5.2.3",
110
+ "fast-xml-parser": "5.3.0",
111
111
  "globals": "16.2.0",
112
112
  "husky": "9.1.7",
113
- "lint-staged": "15.5.1",
114
- "mocha": "11.5.0",
113
+ "lint-staged": "16.2.6",
114
+ "mocha": "11.7.4",
115
115
  "mock-fs": "5.3.0",
116
116
  "npm-run-all": "4.1.5",
117
- "prettier-eslint": "16.4.1",
117
+ "prettier-eslint": "16.4.2",
118
118
  "typescript": "5.8.3"
119
119
  },
120
120
  "optionalDependencies": {
@@ -175,5 +175,5 @@
175
175
  "verification"
176
176
  ]
177
177
  },
178
- "version": "8.1.0"
178
+ "version": "8.2.0"
179
179
  }
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
5
+ xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
6
+ xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
7
+ xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
8
+ <soap:Header>
9
+ <wsa:Action>RetrieveResponse</wsa:Action>
10
+ <wsa:MessageID>urn:uuid:998a6923-b781-40be-abad-0506f0f97477</wsa:MessageID>
11
+ <wsa:RelatesTo>urn:uuid:a5d518cc-9bfb-45f1-a4a7-5d11cc1a8d44</wsa:RelatesTo>
12
+ <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
13
+ <wsse:Security>
14
+ <wsu:Timestamp wsu:Id="Timestamp-a6c00a2f-fcfa-4882-a72d-8b8983a8cc7e">
15
+ <wsu:Created>2025-09-05T16:29:03Z</wsu:Created>
16
+ <wsu:Expires>2025-09-05T16:34:03Z</wsu:Expires>
17
+ </wsu:Timestamp>
18
+ </wsse:Security>
19
+ </soap:Header>
20
+ <soap:Body>
21
+ <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI">
22
+ <OverallStatus>OK</OverallStatus>
23
+ <RequestID>ac40bccd-e8cd-4232-b1ee-e3cfbbfd0b89</RequestID>
24
+ </RetrieveResponseMsg>
25
+ </soap:Body>
26
+ </soap:Envelope>
@@ -13,7 +13,7 @@
13
13
  * Start: 2020-05-13 18:30:32.11-06:00 +01:00
14
14
  * End: 2079-06-06 21:00:00-06:00 +01:00
15
15
  * Timezone: W. Europe Standard Time
16
- * Recurrance: every 5 minutes until end date
16
+ * Recurrence: every 5 minutes until end date
17
17
 
18
18
  **Notifications:** _none_
19
19
 
@@ -13,7 +13,7 @@
13
13
  * Start: 2022-07-30 00:00:00 +01:00
14
14
  * End: 2022-07-30 00:00:00 +01:00
15
15
  * Timezone: W. Europe Standard Time
16
- * Recurrance: run only once
16
+ * Recurrence: run only once
17
17
 
18
18
  **Notifications:**
19
19
 
@@ -13,7 +13,7 @@
13
13
  * Start: 2022-07-30 00:00:00 +01:00
14
14
  * End: 2022-07-30 00:00:00 +01:00
15
15
  * Timezone: W. Europe Standard Time
16
- * Recurrance: run only once
16
+ * Recurrence: run only once
17
17
 
18
18
  **Notifications:**
19
19
 
@@ -0,0 +1,24 @@
1
+ {
2
+ "CustomerKey": "testExisting_triggeredSend",
3
+ "Sent": 10,
4
+ "NotSentDueToOptOut": 0,
5
+ "NotSentDueToUndeliverable": 0,
6
+ "Bounces": 0,
7
+ "Opens": 0,
8
+ "Clicks": 0,
9
+ "UniqueOpens": 0,
10
+ "UniqueClicks": 0,
11
+ "OptOuts": 0,
12
+ "SurveyResponses": 0,
13
+ "FTAFRequests": 0,
14
+ "FTAFEmailsSent": 0,
15
+ "FTAFOptIns": 0,
16
+ "Conversions": 0,
17
+ "UniqueConversions": 0,
18
+ "InProcess": 0,
19
+ "NotSentDueToError": 0,
20
+ "Queued": 0,
21
+ "r__folder_Path": "Triggered Sends",
22
+ "r__triggeredSend_name": "testExisting_triggeredSend",
23
+ "r__triggeredSend_key": "testExisting_triggeredSend"
24
+ }
@@ -0,0 +1,49 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
5
+ xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
6
+ xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
7
+ xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
8
+ <soap:Header>
9
+ <wsa:Action>RetrieveResponse</wsa:Action>
10
+ <wsa:MessageID>urn:uuid:8fe86c01-56d5-4c56-8ac2-991578c79485</wsa:MessageID>
11
+ <wsa:RelatesTo>urn:uuid:592f71ac-78a0-45a2-8cfe-37a91fc6cfd5</wsa:RelatesTo>
12
+ <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
13
+ <wsse:Security>
14
+ <wsu:Timestamp wsu:Id="Timestamp-675af14a-b6a1-44a5-b7e7-4a76c6d18424">
15
+ <wsu:Created>2023-02-01T10:29:21Z</wsu:Created>
16
+ <wsu:Expires>2023-02-01T10:34:21Z</wsu:Expires>
17
+ </wsu:Timestamp>
18
+ </wsse:Security>
19
+ </soap:Header>
20
+ <soap:Body>
21
+ <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI">
22
+ <OverallStatus>OK</OverallStatus>
23
+ <RequestID>a90dda5e-aeba-440a-82ce-74fb2abf5eb2</RequestID>
24
+ <Results xsi:type="TriggeredSendSummary">
25
+ <PartnerKey xsi:nil="true" />
26
+ <ObjectID>b3150cf0-6e78-e811-80d4-1402ec721c9d</ObjectID>
27
+ <CustomerKey>testExisting_triggeredSend</CustomerKey>
28
+ <Sent>10</Sent>
29
+ <NotSentDueToOptOut>0</NotSentDueToOptOut>
30
+ <NotSentDueToUndeliverable>0</NotSentDueToUndeliverable>
31
+ <Bounces>0</Bounces>
32
+ <Opens>0</Opens>
33
+ <Clicks>0</Clicks>
34
+ <UniqueOpens>0</UniqueOpens>
35
+ <UniqueClicks>0</UniqueClicks>
36
+ <OptOuts>0</OptOuts>
37
+ <SurveyResponses>0</SurveyResponses>
38
+ <FTAFRequests>0</FTAFRequests>
39
+ <FTAFEmailsSent>0</FTAFEmailsSent>
40
+ <FTAFOptIns>0</FTAFOptIns>
41
+ <Conversions>0</Conversions>
42
+ <UniqueConversions>0</UniqueConversions>
43
+ <InProcess>0</InProcess>
44
+ <NotSentDueToError>0</NotSentDueToError>
45
+ <Queued>0</Queued>
46
+ </Results>
47
+ </RetrieveResponseMsg>
48
+ </soap:Body>
49
+ </soap:Envelope>
@@ -91,6 +91,47 @@ describe('type: dataExtension', () => {
91
91
  );
92
92
  return;
93
93
  });
94
+
95
+ it('Should not fail if shared dataExtension cannot be retrieved', async () => {
96
+ // WHEN
97
+ await handler.retrieve('testInstance/_ParentBU_', ['dataExtension', 'query']);
98
+ // THEN
99
+ assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error');
100
+ // get results from cache
101
+ const result = cache.getCache();
102
+ assert.equal(
103
+ result.dataExtension ? Object.keys(result.dataExtension).length : 0,
104
+ 1,
105
+ 'only one dataExtension expected'
106
+ );
107
+ assert.deepEqual(
108
+ await testUtils.getActualJson(
109
+ 'testExisting_dataExtensionShared',
110
+ 'dataExtension',
111
+ '_ParentBU_'
112
+ ),
113
+ await testUtils.getExpectedJson('1111111', 'dataExtension', 'retrieve'),
114
+
115
+ 'returned metadata was not equal expected'
116
+ );
117
+ // check if MD file was created and equals expectations
118
+ expect(
119
+ await testUtils.getActualDoc(
120
+ 'testExisting_dataExtensionShared',
121
+ 'dataExtension',
122
+ '_ParentBU_'
123
+ )
124
+ ).to.equal(
125
+ await testUtils.getExpectedFile('1111111', 'dataExtension', 'retrieve', 'md')
126
+ );
127
+
128
+ assert.equal(
129
+ testUtils.getAPIHistoryLength(),
130
+ 7,
131
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
132
+ );
133
+ return;
134
+ });
94
135
  });
95
136
 
96
137
  describe('Deploy ================', () => {
@@ -1132,13 +1132,19 @@ describe('type: journey', () => {
1132
1132
  it('Should not validate a transactional journey by key', async () => {
1133
1133
  handler.setOptions({ skipStatusCheck: true });
1134
1134
  // WHEN
1135
- await handler.validate(
1135
+ const validate = await handler.validate(
1136
1136
  'testInstance/testBU',
1137
1137
  ['journey'],
1138
1138
  ['testExisting_temail_notPublished']
1139
1139
  );
1140
1140
  // THEN
1141
- assert.equal(process.exitCode, 1, 'validate should not have thrown an error');
1141
+ assert.equal(process.exitCode, 0, 'validate should not have thrown an error');
1142
+ // retrieve result
1143
+ assert.deepEqual(
1144
+ validate['testInstance/testBU']?.journey,
1145
+ [],
1146
+ 'should not have validated any journey'
1147
+ );
1142
1148
 
1143
1149
  assert.equal(
1144
1150
  testUtils.getAPIHistoryLength(),
@@ -1148,6 +1154,35 @@ describe('type: journey', () => {
1148
1154
  return;
1149
1155
  });
1150
1156
 
1157
+ it('Should validate a multi-step journey but not the transactional journey by key', async () => {
1158
+ await testUtils.copyFile(
1159
+ 'interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json',
1160
+ 'interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response.json'
1161
+ );
1162
+ handler.setOptions({ skipStatusCheck: true });
1163
+ // WHEN
1164
+ const validate = await handler.validate(
1165
+ 'testInstance/testBU',
1166
+ ['journey'],
1167
+ ['testExisting_temail_notPublished', 'testExisting_journey_Multistep']
1168
+ );
1169
+ // THEN
1170
+ assert.equal(process.exitCode, 0, 'validate should not have thrown an error');
1171
+ // retrieve result
1172
+ assert.deepEqual(
1173
+ validate['testInstance/testBU']?.journey,
1174
+ ['testExisting_journey_Multistep'],
1175
+ 'should not have validated any journey'
1176
+ );
1177
+
1178
+ assert.equal(
1179
+ testUtils.getAPIHistoryLength(),
1180
+ 3,
1181
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
1182
+ );
1183
+ return;
1184
+ });
1185
+
1151
1186
  it('Should validate a journey by id but w/o version (auto-picks latest version)', async () => {
1152
1187
  await testUtils.copyFile(
1153
1188
  'interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json',
@@ -0,0 +1,45 @@
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: triggeredSendSummary', () => {
11
+ beforeEach(() => {
12
+ testUtils.mockSetup();
13
+ });
14
+
15
+ afterEach(() => {
16
+ testUtils.mockReset();
17
+ });
18
+
19
+ describe('Retrieve ================', () => {
20
+ it('Should retrieve a triggeredSendSummary', async () => {
21
+ // WHEN
22
+ await handler.retrieve('testInstance/testBU', ['triggeredSendSummary']);
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.triggeredSendSummary ? Object.keys(result.triggeredSendSummary).length : 0,
29
+ 1,
30
+ 'only 1 triggeredSendSummary expected'
31
+ );
32
+ assert.deepEqual(
33
+ await testUtils.getActualJson('testExisting_triggeredSend', 'triggeredSendSummary'),
34
+ await testUtils.getExpectedJson('9999999', 'triggeredSendSummary', 'get'),
35
+ 'returned JSON was not equal expected'
36
+ );
37
+ assert.equal(
38
+ testUtils.getAPIHistoryLength(),
39
+ 3,
40
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
41
+ );
42
+ return;
43
+ });
44
+ });
45
+ });