diff --git a/package.json b/package.json index 6f4dc668f..0fec4efac 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "@oclif/config": "^1.18.1", "@salesforce/command": "^4.2.0", "@salesforce/core": "^2.31.0", - "@salesforce/source-deploy-retrieve": "^5.9.3", + "@salesforce/source-deploy-retrieve": "^5.9.5", "@salesforce/source-tracking": "^1.0.0", "chalk": "^4.1.2", "cli-ux": "^5.6.3", @@ -173,8 +173,9 @@ "test:nuts:manifest:create": "mocha \"test/nuts/create.nut.ts\" --slow 4500 --timeout 600000 --retries 0", "test:nuts:mdapi": "mocha \"test/nuts/mdapi.nut.ts\" --slow 3000 --timeout 600000 --retries 0", "test:nuts:retrieve": "cross-env PLUGIN_SOURCE_SEED_FILTER=retrieve ts-node ./test/nuts/generateNuts.ts && mocha \"test/nuts/generated/*.nut.ts\" --slow 4500 --timeout 600000 --parallel --retries 0", - "test:nuts:specialTypes": "mocha \"test/nuts/territory2.nut.ts\" \"test/nuts/folderTypes.nut.ts\" --slow 4500 --timeout 600000 --retries 0 --parallel", + "test:nuts:specialTypes": "mocha \"test/nuts/territory2.nut.ts\" \"test/nuts/folderTypes.nut.ts\" \"test/nuts/translation.nut.ts\" --slow 4500 --timeout 600000 --retries 0 --parallel", "test:nuts:territory2": "mocha \"test/nuts/territory2.nut.ts\" --slow 4500 --timeout 600000 --retries 0", + "test:nuts:translations": "mocha \"test/nuts/translation.nut.ts\" --slow 4500 --timeout 600000 --retries 0", "test:nuts:tracking": "mocha \"test/nuts/trackingCommands/*.nut.ts\" --slow 3000 --timeout 600000 --parallel --retries 0", "test:nuts:tracking:basics": "mocha \"test/nuts/trackingCommands/basics.nut.ts\" --slow 3000 --timeout 600000 --retries 0", "test:nuts:tracking:conflicts": "mocha \"test/nuts/trackingCommands/conflicts.nut.ts\" --slow 3000 --timeout 600000 --retries 0", diff --git a/test/nuts/customTranslationProject/config/project-scratch-def.json b/test/nuts/customTranslationProject/config/project-scratch-def.json new file mode 100644 index 000000000..1e8b4448e --- /dev/null +++ b/test/nuts/customTranslationProject/config/project-scratch-def.json @@ -0,0 +1,16 @@ +{ + "orgName": "Custom Fields company", + "edition": "Developer", + "features": ["EnableSetPasswordInApi"], + "settings": { + "lightningExperienceSettings": { + "enableS1DesktopEnabled": true + }, + "mobileSettings": { + "enableS1EncryptedStoragePref2": false + }, + "languageSettings": { + "enableTranslationWorkbench": true + } + } +} diff --git a/test/nuts/customTranslationProject/force-app/main/default/layouts/customObject__c-customObject Layout.layout-meta.xml b/test/nuts/customTranslationProject/force-app/main/default/layouts/customObject__c-customObject Layout.layout-meta.xml new file mode 100644 index 000000000..fdd4bb50d --- /dev/null +++ b/test/nuts/customTranslationProject/force-app/main/default/layouts/customObject__c-customObject Layout.layout-meta.xml @@ -0,0 +1,59 @@ + + + + false + false + true + + + + Required + Name + + + Readonly + customField__c + + + + + Edit + OwnerId + + + + + + false + false + true + + + + Readonly + CreatedById + + + + + Readonly + LastModifiedById + + + + + + false + false + true + + + + + + false + false + false + false + false + diff --git a/test/nuts/customTranslationProject/force-app/main/default/objectTranslations/customObject__c-es/customField__c.fieldTranslation-meta.xml b/test/nuts/customTranslationProject/force-app/main/default/objectTranslations/customObject__c-es/customField__c.fieldTranslation-meta.xml new file mode 100644 index 000000000..125d3cd88 --- /dev/null +++ b/test/nuts/customTranslationProject/force-app/main/default/objectTranslations/customObject__c-es/customField__c.fieldTranslation-meta.xml @@ -0,0 +1,5 @@ + + + + customField__c + diff --git a/test/nuts/customTranslationProject/force-app/main/default/objectTranslations/customObject__c-es/customObject__c-es.objectTranslation-meta.xml b/test/nuts/customTranslationProject/force-app/main/default/objectTranslations/customObject__c-es/customObject__c-es.objectTranslation-meta.xml new file mode 100644 index 000000000..5283bb64b --- /dev/null +++ b/test/nuts/customTranslationProject/force-app/main/default/objectTranslations/customObject__c-es/customObject__c-es.objectTranslation-meta.xml @@ -0,0 +1,13 @@ + + + + false + + + + true + + + + + diff --git a/test/nuts/customTranslationProject/force-app/main/default/objects/customObject__c/customObject__c.object-meta.xml b/test/nuts/customTranslationProject/force-app/main/default/objects/customObject__c/customObject__c.object-meta.xml new file mode 100644 index 000000000..a309f2bfd --- /dev/null +++ b/test/nuts/customTranslationProject/force-app/main/default/objects/customObject__c/customObject__c.object-meta.xml @@ -0,0 +1,165 @@ + + + + Accept + Default + + + Accept + Large + Default + + + Accept + Small + Default + + + CancelEdit + Default + + + CancelEdit + Large + Default + + + CancelEdit + Small + Default + + + Clone + Default + + + Clone + Large + Default + + + Clone + Small + Default + + + Delete + Default + + + Delete + Large + Default + + + Delete + Small + Default + + + Edit + Default + + + Edit + Large + Default + + + Edit + Small + Default + + + List + Default + + + List + Large + Default + + + List + Small + Default + + + New + Default + + + New + Large + Default + + + New + Small + Default + + + SaveEdit + Default + + + SaveEdit + Large + Default + + + SaveEdit + Small + Default + + + Tab + Default + + + Tab + Large + Default + + + Tab + Small + Default + + + View + Default + + + View + Large + Default + + + View + Small + Default + + false + SYSTEM + Deployed + false + true + false + false + false + false + false + true + true + Private + + + + Text + + customObjects + + ReadWrite + Public + diff --git a/test/nuts/customTranslationProject/force-app/main/default/objects/customObject__c/fields/customField__c.field-meta.xml b/test/nuts/customTranslationProject/force-app/main/default/objects/customObject__c/fields/customField__c.field-meta.xml new file mode 100644 index 000000000..76c0b9db7 --- /dev/null +++ b/test/nuts/customTranslationProject/force-app/main/default/objects/customObject__c/fields/customField__c.field-meta.xml @@ -0,0 +1,8 @@ + + + customField__c + false + + false + AutoNumber + diff --git a/test/nuts/customTranslationProject/force-app/main/default/profiles/Admin.profile-meta.xml b/test/nuts/customTranslationProject/force-app/main/default/profiles/Admin.profile-meta.xml new file mode 100644 index 000000000..50d1d565e --- /dev/null +++ b/test/nuts/customTranslationProject/force-app/main/default/profiles/Admin.profile-meta.xml @@ -0,0 +1,734 @@ + + + false + + false + customObject__c.customField__c + true + + + customObject__c-customObject Layout + + + true + true + true + true + true + customObject__c + true + + Salesforce + + true + AIViewInsightObjects + + + true + ActivateContract + + + true + ActivateOrder + + + true + ActivitiesAccess + + + true + AddDirectMessageMembers + + + true + AllowUniversalSearch + + + true + AllowViewKnowledge + + + true + ApexRestServices + + + true + ApiEnabled + + + true + AssignPermissionSets + + + true + AssignTopics + + + true + AuthorApex + + + true + BulkMacrosAllowed + + + true + CanInsertFeedSystemFields + + + true + CanUseNewDashboardBuilder + + + true + CanVerifyComment + + + true + ChangeDashboardColors + + + true + ChatterEditOwnPost + + + true + ChatterEditOwnRecordPost + + + true + ChatterFileLink + + + true + ChatterInternalUser + + + true + ChatterInviteExternalUsers + + + true + ChatterOwnGroups + + + true + ConnectOrgToEnvironmentHub + + + true + ConsentApiUpdate + + + true + ContentAdministrator + + + true + ContentWorkspaces + + + true + ConvertLeads + + + true + CreateCustomizeDashboards + + + true + CreateCustomizeFilters + + + true + CreateCustomizeReports + + + true + CreateDashboardFolders + + + true + CreateLtngTempFolder + + + true + CreateReportFolders + + + true + CreateTopics + + + true + CreateWorkBadgeDefinition + + + true + CreateWorkspaces + + + true + CustomizeApplication + + + true + DataExport + + + true + DelegatedTwoFactor + + + true + DeleteActivatedContract + + + true + DeleteTopics + + + true + DistributeFromPersWksp + + + true + EditActivatedOrders + + + true + EditBrandTemplates + + + true + EditCaseComments + + + true + EditEvent + + + true + EditHtmlTemplates + + + true + EditKnowledge + + + true + EditMyDashboards + + + true + EditMyReports + + + true + EditOppLineItemUnitPrice + + + true + EditPublicDocuments + + + true + EditPublicFilters + + + true + EditPublicTemplates + + + true + EditReadonlyFields + + + true + EditTask + + + true + EditTopics + + + true + EmailMass + + + true + EmailSingle + + + true + EnableCommunityAppLauncher + + + true + EnableNotifications + + + true + ExportReport + + + true + FieldServiceAccess + + + true + GiveRecognitionBadge + + + true + ImportCustomObjects + + + true + ImportLeads + + + true + ImportPersonal + + + true + InstallPackaging + + + true + LightningConsoleAllowedForUser + + + true + LightningExperienceUser + + + true + ListEmailSend + + + true + ManageAnalyticSnapshots + + + true + ManageAuthProviders + + + true + ManageBusinessHourHolidays + + + true + ManageC360AConnections + + + true + ManageCMS + + + true + ManageCallCenters + + + true + ManageCases + + + true + ManageCategories + + + true + ManageCertificates + + + true + ManageContentPermissions + + + true + ManageContentProperties + + + true + ManageContentTypes + + + true + ManageCustomPermissions + + + true + ManageCustomReportTypes + + + true + ManageDashbdsInPubFolders + + + true + ManageDataCategories + + + true + ManageDataIntegrations + + + true + ManageDynamicDashboards + + + true + ManageEmailClientConfig + + + true + ManageEntitlements + + + true + ManageExchangeConfig + + + true + ManageHealthCheck + + + true + ManageHubConnections + + + true + ManageInteraction + + + true + ManageInternalUsers + + + true + ManageIpAddresses + + + true + ManageKnowledge + + + true + ManageKnowledgeImportExport + + + true + ManageLeads + + + true + ManageLoginAccessPolicies + + + true + ManageMobile + + + true + ManageNetworks + + + true + ManagePackageLicenses + + + true + ManagePasswordPolicies + + + true + ManageProfilesPermissionsets + + + true + ManagePropositions + + + true + ManagePvtRptsAndDashbds + + + true + ManageRecommendationStrategies + + + true + ManageReleaseUpdates + + + true + ManageRemoteAccess + + + true + ManageReportsInPubFolders + + + true + ManageRoles + + + true + ManageSearchPromotionRules + + + true + ManageSharing + + + true + ManageSolutions + + + true + ManageSubscriptions + + + true + ManageSynonyms + + + true + ManageTranslation + + + true + ManageUnlistedGroups + + + true + ManageUsers + + + true + MassInlineEdit + + + true + MergeTopics + + + true + ModerateChatter + + + true + ModifyAllData + + + true + ModifyDataClassification + + + true + ModifyMetadata + + + true + NewReportBuilder + + + true + OmnichannelInventorySync + + + true + Packaging2 + + + true + Packaging2Delete + + + true + PrivacyDataAccess + + + true + RemoveDirectMessageMembers + + + true + ResetPasswords + + + true + RunReports + + + true + ScheduleReports + + + true + SelectFilesFromSalesforce + + + true + SendCustomNotifications + + + true + SendExternalEmailAvailable + + + true + SendSitRequests + + + true + ShareInternalArticles + + + true + ShowCompanyNameAsUserBadge + + + true + SolutionImport + + + true + SubmitMacrosAllowed + + + true + SubscribeDashboardRolesGrps + + + true + SubscribeDashboardToOtherUsers + + + true + SubscribeReportRolesGrps + + + true + SubscribeReportToOtherUsers + + + true + SubscribeReportsRunAsUser + + + true + SubscribeToLightningDashboards + + + true + SubscribeToLightningReports + + + true + TransactionalEmailSend + + + true + TransferAnyCase + + + true + TransferAnyEntity + + + true + TransferAnyLead + + + true + UseOmnichannelInventoryAPIs + + + true + UseTeamReassignWizards + + + true + UseWebLink + + + true + ViewAllData + + + true + ViewAllProfiles + + + true + ViewAllUsers + + + true + ViewDataAssessment + + + true + ViewDataCategories + + + true + ViewDataLeakageEvents + + + true + ViewDeveloperName + + + true + ViewEventLogFiles + + + true + ViewFlowUsageAndFlowEventData + + + true + ViewHealthCheck + + + true + ViewHelpLink + + + true + ViewMyTeamsDashboards + + + true + ViewPlatformEvents + + + true + ViewPublicDashboards + + + true + ViewPublicReports + + + true + ViewRoles + + + true + ViewSetup + + + true + ViewUserPII + + + true + WorkCalibrationUser + + diff --git a/test/nuts/customTranslationProject/force-app/main/default/translations/es.translation-meta.xml b/test/nuts/customTranslationProject/force-app/main/default/translations/es.translation-meta.xml new file mode 100644 index 000000000..3f0ee803e --- /dev/null +++ b/test/nuts/customTranslationProject/force-app/main/default/translations/es.translation-meta.xml @@ -0,0 +1,60 @@ + + + + + LogACall + + + + NewAccount + + + + NewCase + + + + NewContact + + + + NewEvent + + + + NewGroup + + + + NewLead + + + + NewNote + + + + NewOpportunity + + + + NewTask + + + + SendEmail + + + + + screen_flows_prebuilt_crt + + + Flow Interview Log Entries + + + + Flow Interview Logs + + + diff --git a/test/nuts/customTranslationProject/sfdx-project.json b/test/nuts/customTranslationProject/sfdx-project.json new file mode 100644 index 000000000..21b701641 --- /dev/null +++ b/test/nuts/customTranslationProject/sfdx-project.json @@ -0,0 +1,12 @@ +{ + "packageDirectories": [ + { + "path": "force-app", + "default": true + } + ], + "name": "default", + "namespace": "", + "sfdcLoginUrl": "https://login.salesforce.com", + "sourceApiVersion": "51.0" +} diff --git a/test/nuts/translation.nut.ts b/test/nuts/translation.nut.ts new file mode 100644 index 000000000..db9df9818 --- /dev/null +++ b/test/nuts/translation.nut.ts @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import * as fs from 'fs'; +import * as path from 'path'; +import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; +import { expect } from 'chai'; +import { DeployCommandResult } from '../../src/formatters/deployResultFormatter'; +import { RetrieveCommandResult } from '../../src/formatters/retrieveResultFormatter'; + +describe('translations', () => { + let session: TestSession; + let projectPath: string; + let translationPath: string; + + before(async () => { + session = await TestSession.create({ + project: { + sourceDir: path.join(process.cwd(), 'test', 'nuts', 'customTranslationProject'), + }, + setupCommands: [ + 'sfdx force:org:create -f config/project-scratch-def.json --setdefaultusername --wait 10 --durationdays 1', + ], + }); + projectPath = path.join(session.project.dir, 'force-app', 'main', 'default'); + translationPath = path.join(projectPath, 'objectTranslations', 'customObject__c-es'); + }); + + after(async () => { + await session?.clean(); + }); + + describe('manifest', () => { + after(async () => { + await fs.promises.unlink(path.join(session.project.dir, 'package.xml')); + }); + + it('can generate manifest for translation types', async () => { + execCmd('force:source:manifest:create -p force-app --json', { ensureExitCode: 0 }); + expect(fs.existsSync(path.join(session.project.dir, 'package.xml'))).to.be.true; + }); + + it('deploy', () => { + const deployResults = execCmd('force:source:deploy -x package.xml --json', { + ensureExitCode: 0, + }).jsonOutput.result; + expect(deployResults.deployedSource.length).to.equal(6); + }); + + it('retrieve without local metadata', async () => { + // delete and recreate an empty dir + await fs.promises.rmdir(path.join(session.project.dir, 'force-app'), { recursive: true }); + await fs.promises.mkdir(path.join(session.project.dir, 'force-app')); + const retrieveResults = execCmd('force:source:retrieve -x package.xml --json', { + ensureExitCode: 0, + }).jsonOutput.result; + expect(retrieveResults.inboundFiles).to.have.length(7); + }); + }); + + describe('metadata', () => { + describe('deploy', () => { + it('can deploy all metadata items', async () => { + execCmd('force:source:deploy -m CustomFieldTranslation,CustomObjectTranslation --json', { + ensureExitCode: 0, + }); + }); + }); + + describe('retrieve', () => { + it('can retrieve all metadata items', async () => { + execCmd('force:source:retrieve -m CustomFieldTranslation,CustomObjectTranslation --json', { + ensureExitCode: 0, + }); + }); + }); + }); + + describe('sourcepath', () => { + describe('deploy', () => { + it('can deploy the whole project', async () => { + execCmd('force:source:deploy -p force-app --json', { + ensureExitCode: 0, + }); + }); + + describe('individual type deploys', () => { + it('can deploy COT', async () => { + execCmd(`force:source:deploy -p ${translationPath} --json`, { + ensureExitCode: 0, + }); + }); + + it('can "deploy" CFTs', async () => { + // should not actually deploy anything + execCmd( + `force:source:deploy -p ${path.join(translationPath, 'customField__c.fieldTranslation-meta.xml')} --json`, + { + ensureExitCode: 0, + } + ); + }); + + it('can deploy COT', async () => { + execCmd( + `force:source:deploy -p ${path.join(translationPath, 'customField__c.fieldTranslation-meta.xml')} --json`, + { + ensureExitCode: 0, + } + ); + }); + }); + }); + + describe('retrieve', () => { + it('can retrieve the whole project', async () => { + execCmd('force:source:retrieve -p force-app --json', { + ensureExitCode: 0, + }); + }); + + describe('individual type retrieves', () => { + it('can retrieve COT', async () => { + execCmd(`force:source:retrieve -p ${translationPath} --json`, { + ensureExitCode: 0, + }); + }); + + it('can retrieve COT from directory', async () => { + execCmd( + `force:source:retrieve -p ${path.join( + translationPath, + 'customObject__c-es.objectTranslation-meta.xml' + )} --json`, + { + ensureExitCode: 0, + } + ); + }); + }); + }); + }); + + describe('mdapi format', () => { + it('can convert COT/CFTs correctly', () => { + execCmd('force:source:convert --outputdir mdapi', { ensureExitCode: 0 }); + // the CFTs shouldn't be written to mdapi format + expect(fs.existsSync(path.join(session.project.dir, 'mdapi', 'fields'))).to.be.false; + expect(fs.existsSync(path.join(session.project.dir, 'mdapi', 'objectTranslations'))).to.be.true; + }); + }); +});