Skip to content

Commit

Permalink
fix: decomposed metadata fragments do are not deploy without a parent
Browse files Browse the repository at this point in the history
  • Loading branch information
Codeneos committed Aug 17, 2023
1 parent dba71f4 commit a2e187c
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ describe('SalesforcePackageBuilder', () => {
// Trigger
'src/triggers/myTrigger.trigger': 'trigger MyTrigger on Account (before insert, before update, after insert, after update) { }',
'src/triggers/myTrigger.trigger-meta.xml': buildMetadataXml('ApexTrigger'),
// decomposd object
'src/objects/PetersCustomObject__c/fields/PetersField__c.field-meta.xml': buildXml('CustomField', { fullName: 'PetersField__c' }),
'src/objects/PetersCustomObject__c/listViews/What_A_View.listview-meta.xml': buildXml('ListView', { fullName: 'What_A_View' }),
'src/objects/PetersCustomObject__c/PetersCustomObject__c.object-meta.xml': buildXml('CustomObject', { fullName: 'PetersCustomObject__c' }),
// Destructive changes
'src/destructiveChangesPost.xml': buildXml('Package', { types: [ { name: 'ApexClass', members: [ 'a', 'b' ] } ] }),
'src/destructiveChangesPost2.xml': buildXml('Package', { types: [ { name: 'ApexClass', members: [ 'x', 'y' ] } ] }),
Expand Down Expand Up @@ -240,6 +244,74 @@ describe('SalesforcePackageBuilder', () => {
expect(manifest.types[0].members[0]).toEqual('myClass');
});
});
describe('#customObject', () => {
it('should add all fragments of an object as separate entries in manifest', async () => {
const packageBuilder = new SalesforcePackageBuilder(SalesforcePackageType.deploy, apiVersion, mockFs);
await packageBuilder.addFiles([ 'src/objects/PetersCustomObject__c']);
const manifest = packageBuilder.getManifest().toJson(apiVersion);

expect(manifest.types).toStrictEqual([
{ name:'CustomObject', members: [ 'PetersCustomObject__c' ] },
{ name:'CustomField', members: [ 'PetersCustomObject__c.PetersField__c' ] },
{ name:'ListView', members: [ 'PetersCustomObject__c.What_A_View' ] }
]);
});
it('should merge source from fragments into parent', async () => {
const packageBuilder = new SalesforcePackageBuilder(SalesforcePackageType.deploy, apiVersion, mockFs);
await packageBuilder.addFiles([ 'src/objects/PetersCustomObject__c']);

const sfPackage = await packageBuilder.getPackage().generateArchive();
const packageFiles = Object.keys(sfPackage.files);
const metadata = await sfPackage.file('objects/PetersCustomObject__c.object')?.async('string');
const parsedMetadata = metadata && XML.parse(metadata, { ignoreAttributes: true, ignoreNamespacePrefix: true });

expect(packageFiles).toStrictEqual([
'package.xml',
'objects/',
'objects/PetersCustomObject__c.object'
]);

expect(parsedMetadata).toStrictEqual({
CustomObject: {
fullName: 'PetersCustomObject__c',
fields: {
fullName: 'PetersField__c',
},
listViews: {
fullName: 'What_A_View',
}
}
});
});
it('should add parent tag without content when deploying fragment', async () => {
const packageBuilder = new SalesforcePackageBuilder(SalesforcePackageType.deploy, apiVersion, mockFs);
await packageBuilder.addFiles([ 'src/objects/PetersCustomObject__c/fields']);

const manifest = packageBuilder.getManifest().toJson(apiVersion);
const sfPackage = await packageBuilder.getPackage().generateArchive();
const packageFiles = Object.keys(sfPackage.files);
const metadata = await sfPackage.file('objects/PetersCustomObject__c.object')?.async('string');
const parsedMetadata = metadata && XML.parse(metadata, { ignoreAttributes: true, ignoreNamespacePrefix: true });

expect(manifest.types).toStrictEqual([
{ name:'CustomField', members: [ 'PetersCustomObject__c.PetersField__c' ] }
]);

expect(packageFiles).toStrictEqual([
'package.xml',
'objects/',
'objects/PetersCustomObject__c.object'
]);

expect(parsedMetadata).toStrictEqual({
CustomObject: {
fields: {
fullName: 'PetersField__c',
}
}
});
});
});
describe('#settings', () => {
it('should add all settings as Setting metadata type', async () => {
const settingsFsMock = new MemoryFileSystem({
Expand Down Expand Up @@ -401,11 +473,14 @@ describe('SalesforcePackageBuilder', () => {
'src/classes/myClass.cls-meta.xml',
'src/triggers/myTrigger.trigger-meta.xml',
]));
expect(manifest.list().length).toEqual(4);
expect(manifest.list().length).toEqual(7);
expect(manifest.list('AuraDefinitionBundle').length).toEqual(1);
expect(manifest.list('LightningComponentBundle').length).toEqual(1);
expect(manifest.list('ApexClass').length).toEqual(1);
expect(manifest.list('ApexTrigger').length).toEqual(1);
expect(manifest.list('CustomObject').length).toEqual(1);
expect(manifest.list('CustomField').length).toEqual(1);
expect(manifest.list('ListView').length).toEqual(1);
});
});
});
Expand Down
39 changes: 12 additions & 27 deletions packages/salesforce/src/deploymentPackageBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,19 +323,15 @@ export class SalesforcePackageBuilder {
const parentPackagePath = await this.getPackagePath(parentComponentMetaFile, parentType);

// Merge child metadata into parent metadata
if (this.type == SalesforcePackageType.deploy) {
if (this.type === SalesforcePackageType.deploy) {
await this.mergeMetadataFragment(parentPackagePath, sourceFile, parentType);
}

// Add as member to the package when not yet mentioned
if (this.type == SalesforcePackageType.destruct) {
if (this.type === SalesforcePackageType.destruct) {
this.mdPackage.addDestructiveChange(fragmentTypeName, `${parentComponentName}.${childComponentName}`);
} else {
if (fragmentType.isAddressable) {
this.mdPackage.addManifestEntry(fragmentTypeName, `${parentComponentName}.${childComponentName}`);
} else {
this.mdPackage.addManifestEntry(parentType.name, parentComponentName);
}
this.mdPackage.addManifestEntry(fragmentTypeName, `${parentComponentName}.${childComponentName}`);
this.mdPackage.addSourceMap(sourceFile, { componentType: fragmentTypeName, componentName: `${parentComponentName}.${childComponentName}`, packagePath: parentPackagePath });
}

Expand All @@ -357,17 +353,6 @@ export class SalesforcePackageBuilder {
return;
}

// Load existing XML
let existingPackageData = await this.readPackageData(packagePath);
if (!existingPackageData) {
// ensure parent files are included
const parentBaseName = path.posix.basename(packagePath);
const parentSourceFile = path.posix.join(fragmentFile, '..', '..', `${parentBaseName}-meta.xml`);
if (await this.fs.pathExists(parentSourceFile)) {
existingPackageData = await this.fs.readFileAsString(parentSourceFile);
}
}

// Merge child metadata into parent metadata
const metadata = await this.readComposedMetadata(packagePath, fragmentFile, metadataType);
this.mergeMetadata(metadata[metadataType.name], { [decomposition.directoryName]: fragmentMetadata });
Expand All @@ -379,15 +364,15 @@ export class SalesforcePackageBuilder {
return composedData.data;
}

let existingPackageData = await this.readPackageData(packagePath);
if (!existingPackageData) {
// ensure parent files are included
const parentBaseName = path.posix.basename(packagePath);
const parentSourceFile = path.posix.join(fragmentFile, '..', '..', `${parentBaseName}-meta.xml`);
if (await this.fs.pathExists(parentSourceFile)) {
existingPackageData = await this.fs.readFileAsString(parentSourceFile);
}
}
const existingPackageData = await this.readPackageData(packagePath);
// if (!existingPackageData) {
// // ensure parent files are included
// const parentBaseName = path.basename(packagePath);
// const parentSourceFile = path.join(fragmentFile, '..', '..', `${parentBaseName}-meta.xml`);
// if (await this.fs.pathExists(parentSourceFile)) {
// existingPackageData = await this.fs.readFileAsString(parentSourceFile);
// }
// }

const existingMetadata = existingPackageData
? XML.parse(existingPackageData, { trimValues: true })
Expand Down

0 comments on commit a2e187c

Please sign in to comment.