diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md
index de168d7b0..d9363cd3c 100644
--- a/docs/dist/documentation.md
+++ b/docs/dist/documentation.md
@@ -3167,6 +3167,7 @@ Provides default functionality that can be overwritten by child metadata type cl
* [.getSOAPErrorMsg(ex)](#MetadataType.getSOAPErrorMsg) ⇒ string
* [.retrieveSOAP(retrieveDir, [requestParams], [singleRetrieve], [additionalFields])](#MetadataType.retrieveSOAP) ⇒ Promise.<TYPE.MetadataTypeMapObj>
* [.retrieveREST(retrieveDir, uri, [templateVariables], [singleRetrieve])](#MetadataType.retrieveREST) ⇒ Promise.<{metadata: (TYPE.MetadataTypeMap\|TYPE.MetadataTypeItem), type: string}>
+ * [.runDocumentOnRetrieve([singleRetrieve], metadataMap)](#MetadataType.runDocumentOnRetrieve) ⇒ Promise.<void>
* [.parseResponseBody(body, [singleRetrieve])](#MetadataType.parseResponseBody) ⇒ TYPE.MetadataTypeMap
* [.deleteFieldByDefinition(metadataEntry, fieldPath, definitionProperty, origin)](#MetadataType.deleteFieldByDefinition) ⇒ void
* [.removeNotCreateableFields(metadataEntry)](#MetadataType.removeNotCreateableFields) ⇒ void
@@ -3632,6 +3633,19 @@ Retrieves Metadata for Rest Types
| [templateVariables] | TYPE.TemplateMap
| variables to be replaced in the metadata |
| [singleRetrieve] | string
\| number
| key of single item to filter by |
+
+
+### MetadataType.runDocumentOnRetrieve([singleRetrieve], metadataMap) ⇒ Promise.<void>
+helper for [retrieveREST](retrieveREST) and [retrieveSOAP](retrieveSOAP)
+
+**Kind**: static method of [MetadataType
](#MetadataType)
+**Returns**: Promise.<void>
- -
+
+| Param | Type | Description |
+| --- | --- | --- |
+| [singleRetrieve] | string
\| number
| key of single item to filter by |
+| metadataMap | TYPE.MetadataTypeMap
| saved metadata |
+
### MetadataType.parseResponseBody(body, [singleRetrieve]) ⇒ TYPE.MetadataTypeMap
diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js
index 50e114595..8232a2e11 100644
--- a/lib/metadataTypes/Automation.js
+++ b/lib/metadataTypes/Automation.js
@@ -78,9 +78,8 @@ class Automation extends MetadataType {
`Downloaded: ${this.definition.type} (${Object.keys(metadataMap).length})` +
Util.getKeysString(key)
);
- if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) {
- await this.document(metadataMap);
- }
+
+ await this.runDocumentOnRetrieve(key, metadataMap);
}
return { metadata: metadataMap, type: this.definition.type };
}
diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js
index bfae1fdc3..cd50d099e 100644
--- a/lib/metadataTypes/DataExtension.js
+++ b/lib/metadataTypes/DataExtension.js
@@ -464,9 +464,7 @@ class DataExtension extends MetadataType {
`Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` +
Util.getKeysString(key)
);
- if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) {
- await this.document(savedMetadata);
- }
+ await this.runDocumentOnRetrieve(key, savedMetadata);
}
return { metadata: metadata, type: 'dataExtension' };
}
diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js
index 4658a7484..69b582593 100644
--- a/lib/metadataTypes/MetadataType.js
+++ b/lib/metadataTypes/MetadataType.js
@@ -1016,12 +1016,7 @@ class MetadataType {
`Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` +
Util.getKeysString(singleRetrieve)
);
- if (
- this.buObject &&
- this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)
- ) {
- await this.document(savedMetadata);
- }
+ await this.runDocumentOnRetrieve(singleRetrieve, savedMetadata);
}
return { metadata: metadata, type: this.definition.type };
}
@@ -1063,6 +1058,7 @@ class MetadataType {
`Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` +
Util.getKeysString(singleRetrieve)
);
+ await this.runDocumentOnRetrieve(singleRetrieve, savedMetadata);
}
return {
@@ -1071,6 +1067,34 @@ class MetadataType {
};
}
+ /**
+ * helper for {@link retrieveREST} and {@link retrieveSOAP}
+ *
+ * @param {string|number} [singleRetrieve] key of single item to filter by
+ * @param {TYPE.MetadataTypeMap} metadataMap saved metadata
+ * @returns {Promise.} -
+ */
+ static async runDocumentOnRetrieve(singleRetrieve, metadataMap) {
+ if (
+ this.buObject &&
+ this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)
+ ) {
+ if (!singleRetrieve || (singleRetrieve && !this.definition.documentInOneFile)) {
+ const count = Object.keys(metadataMap).length;
+ Util.logger.debug(
+ ` - Running document for ${count} record${count === 1 ? '' : 's'}`
+ );
+ await this.document(metadataMap);
+ } else {
+ Util.logger.info(
+ Util.getGrayMsg(
+ ` - Skipped running document because you supplied keys and ${this.definition.type} is documented in a single file for all.`
+ )
+ );
+ }
+ }
+ }
+
/**
* Builds map of metadata entries mapped to their keyfields
*
diff --git a/lib/metadataTypes/Role.js b/lib/metadataTypes/Role.js
index d6d4d7c85..63e5d2533 100644
--- a/lib/metadataTypes/Role.js
+++ b/lib/metadataTypes/Role.js
@@ -102,9 +102,8 @@ class Role extends MetadataType {
`Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` +
Util.getKeysString(key)
);
- if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) {
- await this.document(savedMetadata);
- }
+
+ await this.runDocumentOnRetrieve(key, savedMetadata);
}
return { metadata: parsed, type: this.definition.type };
}
diff --git a/lib/metadataTypes/User.js b/lib/metadataTypes/User.js
index e2343fc1a..59701f082 100644
--- a/lib/metadataTypes/User.js
+++ b/lib/metadataTypes/User.js
@@ -731,13 +731,7 @@ class User extends MetadataType {
)
);
}
- if (
- !singleRetrieve &&
- this.buObject &&
- this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)
- ) {
- await this.document(savedMetadata);
- }
+ await this.runDocumentOnRetrieve(singleRetrieve, savedMetadata);
}
return { metadata: metadata, type: this.definition.type };
}
@@ -944,14 +938,6 @@ class User extends MetadataType {
return;
}
- // if ran as part of retrieve/deploy with key, exit here
- if (metadata && Object.keys(metadata).length === 1) {
- Util.logger.debug(
- 'Only 1 user found. Skipping documentation, assuming we ran retrieve-by-key.'
- );
- return;
- }
-
if (!metadata) {
// load users from disk if document was called directly and not part of a retrieve
try {
diff --git a/lib/metadataTypes/definitions/User.definition.js b/lib/metadataTypes/definitions/User.definition.js
index adae97e17..34d3b5e0b 100644
--- a/lib/metadataTypes/definitions/User.definition.js
+++ b/lib/metadataTypes/definitions/User.definition.js
@@ -17,6 +17,7 @@ module.exports = {
typeDescription: 'Marketing Cloud users',
typeName: 'User',
typeRetrieveByDefault: false,
+ documentInOneFile: true,
stringifyFieldsBeforeTemplate: ['DefaultBusinessUnit', 'c__AssociatedBusinessUnits'],
fields: {
AccountUserID: {
diff --git a/test/resources/1111111/user/retrieve-expected.md b/test/resources/1111111/user/retrieve-expected.md
new file mode 100644
index 000000000..50eb1b2ec
--- /dev/null
+++ b/test/resources/1111111/user/retrieve-expected.md
@@ -0,0 +1,19 @@
+# User Overview - testInstance
+
+## Users (1)
+
+| Name | Last successful Login | Active | Access Locked out | API User | Must change PW | Default BU | BU Access | Roles | Login | ID | Key | E-Mail | Notification E-Mail | Timezone | SFMC Locale | Modified Date | Modified By | Created Date |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+| user test | 96 days | ✓ | - | - | - | _ParentBU_ (1111111) | _ParentBU_ (1111111),
testBU (9999999) | Administrator,
Content Creator,
Marketing Cloud Administrator | user_test@accenture.asgr | 700301950 | testExisting_user | user_test@accenture.com | user_test@accenture.com | GMT+01:00 | en-GB | 2022-06-21 01:43:02.64 | 123456 | 2019-09-06 01:59:07.097 |
+
+
+## Inactivated Users (0)
+
+| Name | Last successful Login | Active | Access Locked out | API User | Must change PW | Default BU | BU Access | Roles | Login | ID | Key | E-Mail | Notification E-Mail | Timezone | SFMC Locale | Modified Date | Modified By | Created Date |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
+
+
+## Installed Packages (0)
+
+| Name | Last successful Login | Active | Access Locked out | API User | Must change PW | Default BU | BU Access | Roles | Login | ID | Key | E-Mail | Notification E-Mail | Timezone | SFMC Locale | Modified Date | Modified By | Created Date |
+| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
diff --git a/test/resources/9999999/dataExtension/retrieve-expected.md b/test/resources/9999999/dataExtension/retrieve-expected.md
new file mode 100644
index 000000000..fda321a2d
--- /dev/null
+++ b/test/resources/9999999/dataExtension/retrieve-expected.md
@@ -0,0 +1,18 @@
+## testExisting_dataExtension
+
+**Description:** bla bla
+
+**Folder:** Data Extensions/
+
+**Fields in table:** 4
+
+**Sendable:** Yes (`ContactKey` to `Subscriber Key`)
+
+**Testable:** Yes
+
+| Name | FieldType | MaxLength | IsPrimaryKey | IsNullable | DefaultValue |
+| --- | --- | --- | --- | --- | --- |
+| FirstName | Text | 50 | - | + | |
+| LastName | Text | 50 | - | + | |
+| EmailAddress | EmailAddress | 254 | - | - | |
+| ContactKey | Text | 50 | + | - | |
diff --git a/test/type.dataExtension.test.js b/test/type.dataExtension.test.js
index b91a2f496..968a0d164 100644
--- a/test/type.dataExtension.test.js
+++ b/test/type.dataExtension.test.js
@@ -1,4 +1,8 @@
-const assert = require('chai').assert;
+const chai = require('chai');
+const chaiFiles = require('chai-files');
+const assert = chai.assert;
+const expect = chai.expect;
+const file = chaiFiles.file;
const cache = require('../lib/util/cache');
const testUtils = require('./utils');
const handler = require('../lib/index');
@@ -29,6 +33,13 @@ describe('type: dataExtension', () => {
'returned metadata was not equal expected'
);
+ // check if MD file was created and equals expectations
+ expect(
+ file(testUtils.getActualDoc('testExisting_dataExtension', 'dataExtension'))
+ ).to.equal(
+ file(testUtils.getExpectedFile('9999999', 'dataExtension', 'retrieve', 'md'))
+ );
+
assert.equal(
testUtils.getAPIHistoryLength(),
5,
diff --git a/test/type.user.test.js b/test/type.user.test.js
index 26be1696c..697c5a5f7 100644
--- a/test/type.user.test.js
+++ b/test/type.user.test.js
@@ -1,4 +1,9 @@
-const assert = require('chai').assert;
+const chai = require('chai');
+const chaiFiles = require('chai-files');
+const assert = chai.assert;
+chai.use(chaiFiles);
+const expect = chai.expect;
+const file = chaiFiles.file;
const cache = require('../lib/util/cache');
const testUtils = require('./utils');
const handler = require('../lib/index');
@@ -29,6 +34,11 @@ describe('type: user', () => {
'returned metadata was not equal expected'
);
+ // check if MD file was created and equals expectations
+ expect(file(`./docs/user/testInstance.users.md`)).to.equal(
+ file(testUtils.getExpectedFile('1111111', 'user', 'retrieve', 'md'))
+ );
+
assert.equal(
testUtils.getAPIHistoryLength(),
6,
@@ -36,6 +46,22 @@ describe('type: user', () => {
);
return;
});
+ it('Should retrieve a specific user but not run document', async () => {
+ // WHEN
+ await handler.retrieve('testInstance/_ParentBU_', ['user'], ['testExisting_user']);
+ // THEN
+ assert.equal(process.exitCode, false, 'retrieve should not have thrown an error');
+
+ // because user is single-document-type we would not want to find an md file when we retrieve specific keys. only the generic retrieve updates it
+ expect(file(`./docs/user/testInstance.users.md`)).to.not.exist;
+
+ assert.equal(
+ testUtils.getAPIHistoryLength(),
+ 4,
+ 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests'
+ );
+ return;
+ });
});
describe('Deploy ================', () => {
beforeEach(() => {
@@ -74,6 +100,9 @@ describe('type: user', () => {
await testUtils.getExpectedJson('1111111', 'user', 'update'),
'returned metadata was not equal expected for update'
);
+ // because user is single-document-type we would not want to find an md file getting created by deploy. only retrieve updates it
+ expect(file(`./docs/user/testInstance.users.md`)).to.not.exist;
+
assert.equal(
testUtils.getAPIHistoryLength(),
9,
diff --git a/test/utils.js b/test/utils.js
index 5f1e64809..6f0a628e1 100644
--- a/test/utils.js
+++ b/test/utils.js
@@ -22,6 +22,16 @@ const resourceFactory = require('./resourceFactory');
*/
exports.getActualJson = (customerKey, type, buName = 'testBU') =>
File.readJSON(`./retrieve/testInstance/${buName}/${type}/${customerKey}.${type}-meta.json`);
+/**
+ * gets file from Retrieve folder
+ *
+ * @param {string} customerKey of metadata
+ * @param {string} type of metadata
+ * @param {string} [buName] used when we need to test on ParentBU
+ * @returns {Promise.} file in string form
+ */
+exports.getActualDoc = (customerKey, type, buName = 'testBU') =>
+ `./retrieve/testInstance/${buName}/${type}/${customerKey}.${type}-doc.md`;
/**
* gets file from Retrieve folder
*