Skip to content
This repository has been archived by the owner on Oct 23, 2022. It is now read-only.

Commit

Permalink
fix: handle properties of complex Metadata types
Browse files Browse the repository at this point in the history
`force-dev-tool changeset create` now handles properties of complex Metadata types.

Complex Metadata types can contain other Metadata types (e.g. a `CustomObject` can contain a `CustomField`) - changing **independent** children was already handled by `force-dev-tool changeset create` by creating a deployment with only the `CustomField` instead of the whole `CustomObject`.

However complex Metadata types can also have properties (e.g. a `CustomObject` has a `description`) and changing these properties was currently not handled.
When changing the `description` of a `CustomObject` force-dev-tool now creates a deployment with the `CustomObject` but only containing the properties without the named/independent child Metadata components.

The following exemplary changes should now be picked up correctly:

- changing the `description` of a CustomObject/Profile
- changing the `searchLayouts` of a CustomObject

This PR introduces a brand new suite for functional testing of `force-dev-tool changeset create` and is based on simulating a Git history with typical changes to Metadata.
See `test-functional/README.md` to get started.

This closes #13, closes #90, closes #137.
  • Loading branch information
froucher authored May 12, 2020
1 parent 56be084 commit ea74ef4
Show file tree
Hide file tree
Showing 261 changed files with 19,859 additions and 125 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ doc
coverage
npm-debug.log
.vagrant
.orgs.json
.sfdx
20 changes: 14 additions & 6 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [{
"type": "node",
"request": "launch",
"name": "Mocha Tests",
Expand All @@ -18,5 +18,13 @@
"${workspaceFolder}/test",
],
"internalConsoleOptions": "openOnSessionStart"
}]
}, {
"type": "node",
"request": "attach",
"name": "Attach by Process ID",
"processId": "${command:PickProcess}",
"skipFiles": [
"<node_internals>/**"
]
}]
}
59 changes: 59 additions & 0 deletions lib/metadata-file-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ MetadataFileContainer.prototype.diff = function(other) {
type: deletedComponent.type
}));
});
if (self.getMetadataType().childXmlNames) {
var selfContents = self.contentsWithoutChilds();
var otherContents = other.contentsWithoutChilds();
if (selfContents !== otherContents) {
other.updateContents(added, modified);
var component = other.getComponent();
modified.add(new MetadataComponent({
fullName: component.fullName,
fileName: filename,
type: component.type
}))
}
}
}

}
Expand Down Expand Up @@ -172,10 +185,56 @@ MetadataFileContainer.prototype.getGroupedAndSortedComponents = function() {
return map;
};

MetadataFileContainer.prototype.contentsWithoutChilds = function(includedChildComponents) {
var ret = this.contents.toString();

var childComponents = this.getMetadataType().childXmlNames;
if (childComponents) {
var parsed = new xmldoc.XmlDocument(this.contents);
var parentMetadata = '<' + parsed.name + ' xmlns="http://soap.sforce.com/2006/04/metadata">';
var tagIncludedChildNames = includedChildComponents ?
includedChildComponents.map(function(child) { return describeMetadataService.getType(child).tagName; }) : [];
var tagChildNames = childComponents.map(function(child) { return describeMetadataService.getType(child).tagName; })
.filter(function(child) { return !tagIncludedChildNames.includes(child); });
parsed.eachChild(function(child) {
var name = child.name;
if (!tagChildNames.includes(name)) {
parentMetadata += child.toString({
compressed: true,
trimmed: true,
preserveWhitespace: false
});
}
})
parentMetadata += '</' + parsed.name + '>';
//sax has an isssue with '&': https://github.com/isaacs/sax-js/issues/167

This comment has been minimized.

Copy link
@froucher

froucher May 18, 2020

Author Contributor
var document = new xmldoc.XmlDocument(parentMetadata.replace(new RegExp('&',"gm"), '&amp;'));
var indent4Spaces = function(str) {
return str.replace(/^(\s+)</gm, "$1$1<");
}
ret = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
indent4Spaces(document.toString({
compressed: false,
trimmed: false,
preserveWhitespace: !this.opts.ignoreWhitespace
}) + '\n');
}
return ret;
}

MetadataFileContainer.prototype.writeContents = function() {
var self = this;
self.contents = Buffer.from(self.toString());
return self;
}

MetadataFileContainer.prototype.updateContents = function(added, modified) {
var self = this;
var includedChildComponents = modified.manifestJSON.map(function(m) { return m.type; })
.concat(added.manifestJSON.map(function(m) { return m.type; })).filter(function(m) { return m !== undefined; });
var content = self.contentsWithoutChilds(includedChildComponents);
self.contents = Buffer.from(content.toString());
return self;
};

MetadataFileContainer.prototype.toString = function() {
Expand Down
Loading

0 comments on commit ea74ef4

Please sign in to comment.