From f1d0abf9318f8e3bf005506fa07558dbe9cbb101 Mon Sep 17 00:00:00 2001 From: Willhoit Date: Tue, 29 Oct 2024 13:57:18 -0500 Subject: [PATCH] Replace force source status (#1197) * fix: replace force:org:status * chore: cosnt * chore: replace depreacted org short-flag (u with o) * chore: forceignore nuts * test: remove sfdx NUTs * test: add cli back * test: fix NUT (maybe) --------- Co-authored-by: Willie Ruemmele --- package.json | 1 + test/nuts/delete/source.nut.ts | 6 +- test/nuts/tracking/basics.nut.ts | 129 ++++++------------ test/nuts/tracking/conflicts.nut.ts | 36 ++--- test/nuts/tracking/deleteResetTracking.nut.ts | 9 +- test/nuts/tracking/forceIgnore.nut.ts | 27 +--- test/nuts/tracking/lwc.nut.ts | 129 +++++++++--------- test/nuts/tracking/mpd-non-sequential.nut.ts | 2 +- test/nuts/tracking/remoteChanges.nut.ts | 83 +++-------- test/nuts/tracking/types.ts | 22 --- 10 files changed, 146 insertions(+), 298 deletions(-) delete mode 100644 test/nuts/tracking/types.ts diff --git a/package.json b/package.json index be56abe6..2400ff37 100644 --- a/package.json +++ b/package.json @@ -128,6 +128,7 @@ "test:nuts:specialTypes:translations": "mocha \"test/nuts/specialTypes/translation.nut.ts\" --slow 4500 --timeout 1200000 --retries 0 --jobs 20", "test:nuts:static": "nyc mocha \"test/commands/**/*.nut.ts\" \"test/nuts/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", "test:nuts:tracking": "nyc mocha \"test/nuts/tracking/*.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", + "test:nuts:tracking:forceignore": "nyc mocha \"test/nuts/tracking/forceignore.nut.ts\" --slow 4500 --timeout 1200000 --parallel --retries 0 --jobs 20", "test:only": "wireit", "version": "oclif readme" }, diff --git a/test/nuts/delete/source.nut.ts b/test/nuts/delete/source.nut.ts index e2f3b809..4eaac2d8 100644 --- a/test/nuts/delete/source.nut.ts +++ b/test/nuts/delete/source.nut.ts @@ -134,7 +134,7 @@ describe('project delete source NUTs', () => { const query = () => execCmd<{ records: Array<{ IsNameObsolete: boolean }> }>( `data:query -q "SELECT IsNameObsolete FROM SourceMember WHERE MemberType='ApexClass' AND MemberName='${apexName}' LIMIT 1" -t --json`, - { silent: true, cli: 'sf', ensureExitCode: 0 } + { silent: true, ensureExitCode: 0, cli: 'sf' } ); let soql = query().jsonOutput?.result; @@ -187,7 +187,7 @@ describe('project delete source NUTs', () => { // use the brokerCard LWC const lwcPath = path.join(testkit.projectDir, 'force-app', 'main', 'default', 'lwc', 'brokerCard', 'helper.js'); fs.writeFileSync(lwcPath, '//', { encoding: 'utf8' }); - execCmd(`project:deploy:start --source-dir ${lwcPath}`, { cli: 'sf', ensureExitCode: 0 }); + execCmd(`project:deploy:start --source-dir ${lwcPath}`, { ensureExitCode: 0 }); const deleteResult = execCmd(`project:delete:source -p ${lwcPath} --no-prompt --json`).jsonOutput ?.result; assert(deleteResult?.deletedSource); @@ -232,7 +232,7 @@ describe('project delete source NUTs', () => { it('should delete an entire LWC', async () => { const lwcPath = path.join(testkit.projectDir, 'force-app', 'main', 'default', 'lwc'); const mylwcPath = path.join(lwcPath, 'mylwc'); - execCmd(`force:lightning:component:create -n mylwc --type lwc -d ${lwcPath}`, { cli: 'sf', ensureExitCode: 0 }); + execCmd(`force:lightning:component:create -n mylwc --type lwc -d ${lwcPath}`, { ensureExitCode: 0, cli: 'sf' }); execCmd(`project:deploy:start --source-dir ${mylwcPath}`); expect(await isNameObsolete(testkit.username, 'LightningComponentBundle', 'mylwc')).to.be.false; const deleteResult = execCmd(`project:delete:source -p ${mylwcPath} --no-prompt --json`) diff --git a/test/nuts/tracking/basics.nut.ts b/test/nuts/tracking/basics.nut.ts index c5496531..f1f0e1f4 100644 --- a/test/nuts/tracking/basics.nut.ts +++ b/test/nuts/tracking/basics.nut.ts @@ -10,11 +10,10 @@ import * as fs from 'node:fs'; import { expect, assert } from 'chai'; import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; import { DeployResultJson, RetrieveResultJson, isSdrFailure, isSdrSuccess } from '../../../src/utils/types.js'; -import { PreviewResult } from '../../../src/utils/previewOutput.js'; -import type { StatusResult } from './types.js'; +import { PreviewFile, PreviewResult } from '../../../src/utils/previewOutput.js'; import { eBikesDeployResultCount } from './constants.js'; -const filterIgnored = (r: StatusResult): boolean => r.ignored !== true; +const filterIgnored = (r: PreviewFile): boolean => r.ignored !== true; describe('end-to-end-test for tracking with an org (single packageDir)', () => { let session: TestSession; @@ -48,16 +47,7 @@ describe('end-to-end-test for tracking with an org (single packageDir)', () => { describe('basic status and pull', () => { it('detects the initial metadata status', () => { - const result = execCmd('force:source:status --json', { - ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result; - assert(Array.isArray(result)); - // the fields should be populated - expect(result.every((row) => row.type && row.fullName)).to.equal(true); - }); - it('detects the initial metadata status using sf', () => { - const response = execCmd('deploy metadata preview --json', { + const response = execCmd('project deploy preview --json', { ensureExitCode: 0, }).jsonOutput?.result; assert(response); @@ -67,7 +57,7 @@ describe('end-to-end-test for tracking with an org (single packageDir)', () => { expect(response.conflicts).to.be.an.instanceof(Array).with.length(0); }); it('includes no wildcard entries', () => { - const response = execCmd('deploy metadata preview --metadata ApexClass --json', { + const response = execCmd('project deploy preview --metadata ApexClass --json', { ensureExitCode: 0, }).jsonOutput?.result; assert(response); @@ -85,31 +75,28 @@ describe('end-to-end-test for tracking with an org (single packageDir)', () => { expect(files.every(isSdrSuccess), JSON.stringify(files.filter(isSdrFailure))).to.equal(true); }); it('sees no local changes (all were committed from push), but profile updated in remote', () => { - const localResult = execCmd('force:source:status --json --local', { + const localResult = execCmd('project deploy preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; - expect(localResult?.filter(filterIgnored)).to.deep.equal([]); + expect(localResult?.toDeploy.filter(filterIgnored)).to.deep.equal([]); - const remoteResult = execCmd('force:source:status --json --remote', { + const remoteResult = execCmd('project retrieve preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; - expect(remoteResult?.some((item) => item.type === 'Profile')).to.equal(true); + expect(remoteResult?.toRetrieve.some((item) => item.type === 'Profile')).to.equal(true); }); - it('sf sees no local changes (all were committed from push)', () => { - const response = execCmd('deploy metadata preview --json', { + it('sees no local changes (all were committed from push)', () => { + const response = execCmd('project deploy preview --json', { ensureExitCode: 0, }).jsonOutput?.result; expect(response?.toDeploy).to.be.an.instanceof(Array).with.lengthOf(0); }); - it('sf sees no remote changes (all were committed from push) except Profile', () => { - const remoteResult = execCmd('force:source:status --json --remote', { + it('sees no remote changes (all were committed from push) except Profile', () => { + const remoteResult = execCmd('project retrieve preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; - expect(remoteResult?.some((item) => item.type === 'Profile')).to.equal(true); + expect(remoteResult?.toRetrieve.some((item) => item.type === 'Profile')).to.equal(true); }); it('can pull the remote profile', () => { @@ -123,23 +110,31 @@ describe('end-to-end-test for tracking with an org (single packageDir)', () => { }); it('sees no local or remote changes', () => { - const result = execCmd('force:source:status --json', { + const deployResult = execCmd('project deploy preview --json', { + ensureExitCode: 0, + }).jsonOutput?.result; + expect( + deployResult?.toDeploy.filter((r) => r.type === 'Profile').filter(filterIgnored), + JSON.stringify(deployResult) + ).to.have.length(0); + + const retrieveResult = execCmd('project retrieve preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; - expect(result?.filter((r) => r.type === 'Profile').filter(filterIgnored), JSON.stringify(result)).to.have.length( - 0 - ); + expect( + retrieveResult?.toRetrieve.filter((r) => r.type === 'Profile').filter(filterIgnored), + JSON.stringify(retrieveResult) + ).to.have.length(0); }); - it('sf no local changes', () => { - const response = execCmd('deploy metadata preview --json', { + it('no local changes', () => { + const response = execCmd('project deploy preview --json', { ensureExitCode: 0, }).jsonOutput?.result; expect(response?.toDeploy).to.be.an.instanceof(Array).with.lengthOf(0); }); - it('sf deploy no local changes is not an error', () => { + it('deploy no local changes is not an error', () => { const response = execCmd('project deploy start --json', { ensureExitCode: 0, }).jsonOutput?.result; @@ -152,38 +147,11 @@ describe('end-to-end-test for tracking with an org (single packageDir)', () => { fs.promises.unlink(path.join(classDir, 'TestOrderController.cls')), fs.promises.unlink(path.join(classDir, 'TestOrderController.cls-meta.xml')), ]); - const result = execCmd('force:source:status --json --local', { - ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result; - expect(result?.filter(filterIgnored)).to.deep.equal([ - { - type: 'ApexClass', - state: 'Local Deleted', - fullName: 'TestOrderController', - filePath: path.normalize('force-app/main/default/classes/TestOrderController.cls'), - ignored: false, - actualState: 'Deleted', - origin: 'Local', - }, - { - type: 'ApexClass', - state: 'Local Deleted', - fullName: 'TestOrderController', - filePath: path.normalize('force-app/main/default/classes/TestOrderController.cls-meta.xml'), - ignored: false, - actualState: 'Deleted', - origin: 'Local', - }, - ]); - }); - it('sf sees a local delete in local status', () => { - const response = execCmd('deploy metadata preview --json', { + const response = execCmd('project deploy preview --json', { ensureExitCode: 0, }).jsonOutput?.result; assert(response); expect(response.toDeploy).to.be.an.instanceof(Array).with.lengthOf(0); - expect(response.toDelete).to.be.an.instanceof(Array).with.lengthOf(1); expect(response.toDelete).deep.equals([ { type: 'ApexClass', @@ -197,16 +165,6 @@ describe('end-to-end-test for tracking with an org (single packageDir)', () => { ]); }); it('does not see any change in remote status', () => { - const result = execCmd('force:source:status --json --remote', { - ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result; - expect( - result?.filter((r) => r.fullName === 'TestOrderController'), - JSON.stringify(result) - ).to.have.length(0); - }); - it('sf does not see any change in remote status', () => { const result = execCmd('retrieve metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result; @@ -217,21 +175,14 @@ describe('end-to-end-test for tracking with an org (single packageDir)', () => { }); it('pushes the local delete to the org', () => { - const result = execCmd('deploy metadata --json', { + const result = execCmd('project:deploy:start --json', { ensureExitCode: 0, }).jsonOutput?.result.files; expect(result, JSON.stringify(result)).to.be.an.instanceof(Array).with.length(2); }); - it('sees no local changes', () => { - const result = execCmd('force:source:status --json --local', { - ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result; - expect(result?.filter(filterIgnored), JSON.stringify(result)).to.be.an.instanceof(Array).with.length(0); - }); - it('sf no local changes', () => { - const response = execCmd('deploy metadata preview --json', { + it('no local changes', () => { + const response = execCmd('project deploy preview --json', { ensureExitCode: 0, }).jsonOutput?.result; @@ -243,9 +194,8 @@ describe('end-to-end-test for tracking with an org (single packageDir)', () => { it('should throw an err when attempting to pull from a non scratch-org', () => { const hubUsername = session.hubOrg.username; assert(hubUsername, 'hubUsername should be defined'); - const failure = execCmd(`force:source:status -u ${hubUsername} --remote --json`, { + const failure = execCmd(`project retrieve preview -o ${hubUsername} --json`, { ensureExitCode: 1, - cli: 'sf', }).jsonOutput as unknown as { name: string }; // command5 is removing `Error` from the end of the error names. expect(failure.name).to.include('NonSourceTrackedOrg'); @@ -282,14 +232,15 @@ describe('end-to-end-test for tracking with an org (single packageDir)', () => { }); describe('classes that failed to deploy are still in local status', () => { it('sees no local changes', () => { - const result = execCmd('force:source:status --json --local', { + const result = execCmd('project deploy preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; - expect(result?.filter(filterIgnored), JSON.stringify(result)).to.be.an.instanceof(Array).with.length(2); + expect(result?.toDeploy.filter(filterIgnored), JSON.stringify(result)) + .to.be.an.instanceof(Array) + .with.length(1); }); - it('sf sees no local changes', () => { - const response = execCmd('deploy metadata preview --json', { + it('sees no local changes', () => { + const response = execCmd('project deploy preview --json', { ensureExitCode: 0, }).jsonOutput?.result; assert(response); diff --git a/test/nuts/tracking/conflicts.nut.ts b/test/nuts/tracking/conflicts.nut.ts index 852fbe82..dcdb6302 100644 --- a/test/nuts/tracking/conflicts.nut.ts +++ b/test/nuts/tracking/conflicts.nut.ts @@ -13,7 +13,6 @@ import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; import { AuthInfo, Connection } from '@salesforce/core'; import { DeployResultJson, isSdrFailure, isSdrSuccess, RetrieveResultJson } from '../../../src/utils/types.js'; import { PreviewResult } from '../../../src/utils/previewOutput.js'; -import type { StatusResult } from './types.js'; import { eBikesDeployResultCount } from './constants.js'; let session: TestSession; @@ -70,12 +69,11 @@ describe('conflict detection and resolution', () => { description: 'modified', }, }); - const result = execCmd('force:source:status --json --remote', { + const result = execCmd('project retrieve preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; expect( - result?.filter((r) => r.type === 'CustomApplication'), + result?.toRetrieve.filter((r) => r.type === 'CustomApplication'), JSON.stringify(result) ).to.have.lengthOf(1); }); @@ -94,36 +92,24 @@ describe('conflict detection and resolution', () => { ); }); it('can see the conflict in status', () => { - const result = execCmd('force:source:status --json', { + const result = execCmd('project deploy preview --json', { ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result.filter((app) => app.type === 'CustomApplication'); + }).jsonOutput?.result.conflicts.filter((app) => app.type === 'CustomApplication'); // json is not sorted. This relies on the implementation of getConflicts() expect(result).to.deep.equal([ { type: 'CustomApplication', - state: 'Local Changed (Conflict)', fullName: 'EBikes', - filePath: path.normalize('force-app/main/default/applications/EBikes.app-meta.xml'), - ignored: false, conflict: true, - origin: 'Local', - actualState: 'Changed', - }, - { - type: 'CustomApplication', - state: 'Remote Changed (Conflict)', - fullName: 'EBikes', - filePath: path.normalize('force-app/main/default/applications/EBikes.app-meta.xml'), ignored: false, - conflict: true, - origin: 'Remote', - actualState: 'Changed', + operation: 'deploy', + path: path.normalize(path.join(session.project.dir, 'force-app/main/default/applications/EBikes.app-meta.xml')), + projectRelativePath: path.normalize('force-app/main/default/applications/EBikes.app-meta.xml'), }, ]); }); - it('sf can see the conflict in status (deploy)', () => { + it('can see the conflict in status (deploy)', () => { const result = execCmd('deploy metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result.conflicts.filter((app) => app.type === 'CustomApplication'); @@ -141,7 +127,7 @@ describe('conflict detection and resolution', () => { ]); }); - it('sf can see the conflict in status (retrieve)', () => { + it('can see the conflict in status (retrieve)', () => { const result = execCmd('retrieve metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result.conflicts.filter((app) => app.type === 'CustomApplication'); @@ -159,7 +145,7 @@ describe('conflict detection and resolution', () => { ]); }); - it('sf can see the conflict in status (deploy) ignoring conflicts', () => { + it('can see the conflict in status (deploy) ignoring conflicts', () => { const result = execCmd('deploy metadata preview --json -c', { ensureExitCode: 0, }).jsonOutput?.result.toDeploy.filter((app) => app.type === 'CustomApplication'); @@ -177,7 +163,7 @@ describe('conflict detection and resolution', () => { ]); }); - it('sf can see the conflict in status (retrieve) ignoring conflicts', () => { + it('can see the conflict in status (retrieve) ignoring conflicts', () => { const result = execCmd('retrieve metadata preview --json -c', { ensureExitCode: 0, }).jsonOutput?.result.toRetrieve.filter((app) => app.type === 'CustomApplication'); diff --git a/test/nuts/tracking/deleteResetTracking.nut.ts b/test/nuts/tracking/deleteResetTracking.nut.ts index b65e2ca9..98538b54 100644 --- a/test/nuts/tracking/deleteResetTracking.nut.ts +++ b/test/nuts/tracking/deleteResetTracking.nut.ts @@ -11,6 +11,7 @@ import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; import { expect } from 'chai'; import { AuthInfo, Connection } from '@salesforce/core'; import { DeleteTrackingResult } from '../../../src/commands/project/delete/tracking.js'; +import { PreviewResult } from '../../../src/utils/previewOutput.js'; let session: TestSession; let orgId: string; @@ -64,11 +65,11 @@ describe('reset and clear tracking', () => { describe('clearing tracking', () => { it('runs status to start tracking', () => { - const result = execCmd('force:source:status --json', { + const result = execCmd('project deploy preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; - expect(result).to.have.length.greaterThan(100); // ebikes is big + // dreamhouse-lwc is big + expect(result?.toDeploy).to.have.length.greaterThan(75); }); it('local tracking file exists', () => { @@ -110,7 +111,7 @@ describe('reset and clear tracking', () => { } }); // gets tracking files from server - execCmd('force:source:status --json --remote', { ensureExitCode: 0, cli: 'sf' }); + execCmd('project retrieve preview --json', { ensureExitCode: 0, cli: 'sf' }); const revisions = await getRevisionsAsArray(); const revisionFile = JSON.parse( await fs.promises.readFile(path.join(trackingFileFolder, 'maxRevision.json'), 'utf8') diff --git a/test/nuts/tracking/forceIgnore.nut.ts b/test/nuts/tracking/forceIgnore.nut.ts index a9620a54..75f052e6 100644 --- a/test/nuts/tracking/forceIgnore.nut.ts +++ b/test/nuts/tracking/forceIgnore.nut.ts @@ -14,7 +14,6 @@ import { AuthInfo, Connection } from '@salesforce/core'; import { ComponentStatus } from '@salesforce/source-deploy-retrieve'; import { DeployResultJson, RetrieveResultJson } from '../../../src/utils/types.js'; import { PreviewResult } from '../../../src/utils/previewOutput.js'; -import type { StatusResult } from './types.js'; let session: TestSession; // leave this in posix path mode since it's used in forceignore @@ -70,23 +69,6 @@ describe('forceignore changes', () => { }); it('shows the file in status as ignored', () => { - const output = execCmd('force:source:status --json', { - ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result; - expect(output, JSON.stringify(output)).to.deep.include({ - state: 'Local Add', - fullName: 'IgnoreTest', - type: 'ApexClass', - origin: 'Local', - filePath: path.join(classdir, 'IgnoreTest.cls'), - ignored: true, - conflict: false, - actualState: 'Add', - }); - }); - - it('sf shows the file in status as ignored', () => { const output = execCmd('deploy metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result; @@ -154,13 +136,12 @@ describe('forceignore changes', () => { ); }); - it('source:status recognizes change', () => { + it('source:status recognizes ignored class', () => { // gets file into source tracking - const statusOutput = execCmd('force:source:status --json --remote', { + const statusOutput = execCmd('project retrieve preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; - expect(statusOutput?.some((result) => result.fullName === 'CreatedClass')).to.equal(true); + expect(statusOutput?.ignored.some((result) => result.fullName === 'CreatedClass')).to.equal(true); }); it('metadata preview recognizes change and marks it ignored', () => { @@ -174,7 +155,7 @@ describe('forceignore changes', () => { ).to.equal(true); }); - it('sf will not retrieve a remote file added to the ignore AFTER it is being tracked', () => { + it('will not retrieve a remote file added to the ignore AFTER it is being tracked', () => { // pull doesn't retrieve that change const pullOutput = execCmd('project:retrieve:start --json', { ensureExitCode: 0, diff --git a/test/nuts/tracking/lwc.nut.ts b/test/nuts/tracking/lwc.nut.ts index 47b5f35d..29ceac1a 100644 --- a/test/nuts/tracking/lwc.nut.ts +++ b/test/nuts/tracking/lwc.nut.ts @@ -10,15 +10,14 @@ import * as fs from 'node:fs'; import { assert, expect } from 'chai'; import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; import { ComponentStatus } from '@salesforce/source-deploy-retrieve'; -import { PreviewResult } from '../../../src/utils/previewOutput.js'; +import { PreviewFile, PreviewResult } from '../../../src/utils/previewOutput.js'; import { DeployResultJson } from '../../../src/utils/types.js'; -import type { StatusResult } from './types.js'; let session: TestSession; let cssPathAbsolute: string; let cssPathRelative: string; -const filterIgnored = (r: StatusResult): boolean => r.ignored !== true; +const filterIgnored = (r: PreviewFile): boolean => r.ignored !== true; describe('lwc', () => { before(async () => { @@ -47,24 +46,16 @@ describe('lwc', () => { }); it('pushes the repo to get source tracking started', () => { - const resp = execCmd('deploy metadata --json'); - expect(resp.jsonOutput?.status, JSON.stringify(resp)).equals(0); + execCmd('project deploy start --json', { ensureExitCode: 0 }); }); - it('sfdx sees lwc css changes in local status', async () => { + it('sees lwc css changes in local status', async () => { await fs.promises.writeFile( cssPathAbsolute, (await fs.promises.readFile(cssPathAbsolute, 'utf-8')).replace('absolute', 'relative') ); - const result = execCmd('force:source:status --json', { - ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result; - expect(result?.find((r) => r.filePath === cssPathRelative)).to.have.property('actualState', 'Changed'); - }); - it('sf sees lwc css changes in local status', () => { - const result = execCmd('deploy metadata preview --json', { + const result = execCmd('project deploy preview --json', { ensureExitCode: 0, }).jsonOutput?.result; assert(result); @@ -78,25 +69,15 @@ describe('lwc', () => { }); it('pushes lwc css change', () => { - const result = execCmd('deploy metadata --json', { + const result = execCmd('project deploy start --json', { ensureExitCode: 0, }).jsonOutput?.result.files; // we get a result for each bundle member, even though only one changed expect(result?.filter((r) => r.fullName === 'heroDetails')).to.have.length(4); }); - it('sfdx sees no local changes', () => { - const result = execCmd('force:source:status --json', { - ensureExitCode: 0, - cli: 'sf', - }) - .jsonOutput?.result.filter((r) => r.origin === 'Local') - .filter(filterIgnored); - expect(result).to.have.length(0); - }); - - it('sf sees no local changes', () => { - const result = execCmd('deploy metadata preview --json', { + it('sees no local changes', () => { + const result = execCmd('project deploy preview --json', { ensureExitCode: 0, }).jsonOutput?.result; assert(result); @@ -106,26 +87,34 @@ describe('lwc', () => { it("deleting an lwc sub-component should show the sub-component as 'Deleted'", async () => { await fs.promises.rm(cssPathAbsolute); - const result = execCmd('force:source:status --json', { + const result = execCmd('project deploy preview --json', { ensureExitCode: 0, - cli: 'sf', }) - .jsonOutput?.result.filter(filterIgnored) - .find((r) => r.filePath === cssPathRelative); + .jsonOutput?.result.toDeploy.filter(filterIgnored) + .find((r) => r.path?.endsWith('.js-meta.xml')); + assert(result); + // remove + delete result.projectRelativePath; expect(result).to.deep.equal({ fullName: 'heroDetails', type: 'LightningComponentBundle', - state: 'Local Deleted', - ignored: false, - filePath: cssPathRelative, - origin: 'Local', - actualState: 'Deleted', + operation: 'deploy', conflict: false, + ignored: false, + path: path.join( + session.project.dir, + 'force-app', + 'main', + 'default', + 'lwc', + 'heroDetails', + 'heroDetails.js-meta.xml' + ), }); }); it('pushes lwc subcomponent delete', () => { - const result = execCmd('deploy metadata --json', { + const result = execCmd('project deploy start --json', { ensureExitCode: 0, }).jsonOutput?.result.files; const bundleMembers = result?.filter((r) => r.fullName === 'heroDetails'); @@ -138,17 +127,7 @@ describe('lwc', () => { }); it('sees no local changes', () => { - const result = execCmd('force:source:status --json', { - ensureExitCode: 0, - cli: 'sf', - }) - .jsonOutput?.result.filter((r) => r.origin === 'Local') - .filter(filterIgnored); - expect(result).to.have.length(0); - }); - - it('sf sees no local changes', () => { - const result = execCmd('deploy metadata preview --json', { + const result = execCmd('project deploy preview --json', { ensureExitCode: 0, }).jsonOutput?.result; assert(result); @@ -169,18 +148,45 @@ describe('lwc', () => { dependentLWCPath, (await fs.promises.readFile(dependentLWCPath, 'utf-8')).replace(//s, '') ); - const result = execCmd('force:source:status --json', { + const result = execCmd('project deploy preview --json', { ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result.filter((r) => r.origin === 'Local'); + }).jsonOutput?.result; + assert(result); - expect(result.filter(filterIgnored)).to.have.length(4); - expect(result.filter(filterIgnored).filter((r) => r.actualState === 'Deleted')).to.have.length(3); - expect(result.filter(filterIgnored).filter((r) => r.actualState === 'Changed')).to.have.length(1); + expect(result.toDeploy).to.deep.equal([ + { + type: 'LightningComponentBundle', + fullName: 'hero', + conflict: false, + ignored: false, + path: path.join(session.project.dir, 'force-app', 'main', 'default', 'lwc', 'hero', 'hero.js-meta.xml'), + projectRelativePath: path.join('force-app', 'main', 'default', 'lwc', 'hero', 'hero.js-meta.xml'), + operation: 'deploy', + }, + ]); + expect(result.toDelete).to.deep.equal([ + { + type: 'LightningComponentBundle', + fullName: 'heroDetails', + conflict: false, + ignored: false, + path: path.join( + session.project.dir, + 'force-app', + 'main', + 'default', + 'lwc', + 'heroDetails', + 'heroDetails.js-meta.xml' + ), + projectRelativePath: path.join('force-app', 'main', 'default', 'lwc', 'heroDetails', 'heroDetails.js-meta.xml'), + operation: 'deletePost', + }, + ]); }); it('push deletes the LWC remotely', () => { - const result = execCmd('deploy metadata --json', { + const result = execCmd('project deploy start --json', { ensureExitCode: 0, }).jsonOutput?.result.files; // there'll also be changes for the changed Hero component html, but we've already tested changing a bundle member @@ -193,22 +199,11 @@ describe('lwc', () => { }); it('sees no local changes', () => { - const result = execCmd('force:source:status --json', { - ensureExitCode: 0, - cli: 'sf', - }) - .jsonOutput?.result.filter((r) => r.origin === 'Local') - .filter(filterIgnored); - expect(result).to.have.length(0); - }); - it('sf sees no local changes', () => { - const result = execCmd('deploy metadata preview --json', { + const result = execCmd('project deploy preview --json', { ensureExitCode: 0, }).jsonOutput?.result; assert(result); expect(result.toDeploy).to.have.length(0); expect(result.toRetrieve).to.have.length(0); }); - - it('detects remote subcomponent conflicts'); }); diff --git a/test/nuts/tracking/mpd-non-sequential.nut.ts b/test/nuts/tracking/mpd-non-sequential.nut.ts index 9b693e83..73f8c555 100644 --- a/test/nuts/tracking/mpd-non-sequential.nut.ts +++ b/test/nuts/tracking/mpd-non-sequential.nut.ts @@ -46,7 +46,7 @@ describe('multiple pkgDirectories pushed as one deploy', () => { describe('mpd non-sequential', () => { it('pushes using MPD', () => { - const result = execCmd('deploy:metadata --json', { + const result = execCmd('project:deploy:start --json', { ensureExitCode: 0, }).jsonOutput?.result.files; assert(Array.isArray(result)); diff --git a/test/nuts/tracking/remoteChanges.nut.ts b/test/nuts/tracking/remoteChanges.nut.ts index ae643745..27e23d14 100644 --- a/test/nuts/tracking/remoteChanges.nut.ts +++ b/test/nuts/tracking/remoteChanges.nut.ts @@ -14,7 +14,6 @@ import { AuthInfo, Connection } from '@salesforce/core'; import type { FileResponse } from '@salesforce/source-deploy-retrieve'; import type { PreviewResult, PreviewFile } from '../../../src/utils/previewOutput.js'; import { DeployResultJson, isSdrFailure, isSdrSuccess, RetrieveResultJson } from '../../../src/utils/types.js'; -import type { StatusResult } from './types.js'; import { eBikesDeployResultCount } from './constants.js'; let session: TestSession; @@ -22,7 +21,7 @@ let conn: Connection; config.truncateThreshold = 0; -const filterIgnored = (r: StatusResult): boolean => r.ignored !== true; +const filterIgnored = (r: PreviewFile): boolean => r.ignored !== true; const noAudience = (pf: PreviewFile | FileResponse) => pf.type !== 'Audience'; const noReportType = (pf: PreviewFile | FileResponse) => pf.type !== 'ReportType'; @@ -66,14 +65,13 @@ describe('remote changes', () => { }); it('sees no local changes (all were committed from deploy)', () => { - const localResult = execCmd('force:source:status --json --local', { + const localResult = execCmd('project deploy preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; - expect(localResult?.filter(filterIgnored)).to.deep.equal([]); + expect(localResult?.toDeploy.filter(filterIgnored)).to.deep.equal([]); }); - it('sf sees no local changes (all were committed from deploy)', () => { + it('sees no local changes (all were committed from deploy)', () => { const localResult = execCmd('deploy metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result; @@ -106,32 +104,16 @@ describe('remote changes', () => { ) ).to.equal(true); }); - it('sfdx can see the delete in status', () => { - const result = execCmd('force:source:status --json --remote', { - ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result; - // it shows up as one class on the server, but 2 files when pulled - expect( - result?.filter((r) => r.state.includes('Delete')), - JSON.stringify(result) - ).to.have.length(1); - }); - it('sf can see the delete in status', () => { + + it('can see the delete in status', () => { const result = execCmd('retrieve metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result; // it shows up as one class on the server, but 2 files when pulled expect(result?.toDelete, JSON.stringify(result)).to.have.length(1); }); - it('sfdx does not see any change in local status', () => { - const result = execCmd('force:source:status --json --local', { - ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result; - expect(result?.filter(filterIgnored)).to.deep.equal([]); - }); - it('sf does not see any change in local status', () => { + + it('does not see any change in local status', () => { const result = execCmd('deploy metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result; @@ -162,25 +144,23 @@ describe('remote changes', () => { ).to.equal(false); }); it('sees correct local and remote status', () => { - const remoteResult = execCmd('force:source:status --json --remote', { + const remoteResult = execCmd('project retrieve preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; - expect(remoteResult?.filter((r) => r.state.includes('Remote Deleted'))).to.deep.equal([]); + expect(remoteResult?.toRetrieve.filter((r) => r.operation?.includes('Remote Deleted'))).to.deep.equal([]); - const localStatus = execCmd('force:source:status --json --local', { + const localStatus = execCmd('project deploy preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; - expect(localStatus?.filter(filterIgnored)).to.deep.equal([]); + expect(localStatus?.toDeploy.filter(filterIgnored)).to.deep.equal([]); }); - it('sf sees correct local status', () => { + it('sees correct local status', () => { const result = execCmd('deploy metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result; expect(result?.toDeploy).to.deep.equal([]); }); - it('sf sees correct remote status', () => { + it('sees correct remote status', () => { const result = execCmd('retrieve metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result; @@ -202,16 +182,15 @@ describe('remote changes', () => { } }); it('can see the add in status', () => { - const result = execCmd('force:source:status --json --remote', { + const result = execCmd('project retrieve preview --json', { ensureExitCode: 0, - cli: 'sf', }).jsonOutput?.result; expect( - result?.some((r) => r.fullName === className), + result?.toRetrieve.some((r) => r.fullName === className), JSON.stringify(result) ).to.equal(true); }); - it('sf can see the add in status', () => { + it('can see the add in status', () => { const result = execCmd('retrieve metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result; @@ -229,24 +208,7 @@ describe('remote changes', () => { .map((r) => expect(r.state, JSON.stringify(r)).to.equal('Created')); }); describe('check status', () => { - it('sfdx sees correct remote status', () => { - const remoteResult = execCmd('force:source:status --json --remote', { - ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result; - expect( - remoteResult?.filter((r) => r.fullName === className), - JSON.stringify(remoteResult) - ).deep.equal([]); - }); - it('sfdx sees correct local status', () => { - const localStatus = execCmd('force:source:status --json --local', { - ensureExitCode: 0, - cli: 'sf', - }).jsonOutput?.result; - expect(localStatus?.filter(filterIgnored)).to.deep.equal([]); - }); - it('sf sees correct remote status', () => { + it('sees correct remote status', () => { const result = execCmd('retrieve metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result; @@ -255,7 +217,7 @@ describe('remote changes', () => { JSON.stringify(result) ).deep.equal([]); }); - it('sf sees correct local status', () => { + it('sees correct local status', () => { const result = execCmd('deploy metadata preview --json', { ensureExitCode: 0, }).jsonOutput?.result; @@ -319,11 +281,4 @@ describe('remote changes', () => { expect(result).to.include(`v${newApiVersion} metadata`); }); }); - - describe('remote changes: mixed', () => { - it('all three types of changes on the server'); - it('can see the changes in status'); - it('can pull the changes'); - it('sees correct local and remote status'); - }); }); diff --git a/test/nuts/tracking/types.ts b/test/nuts/tracking/types.ts deleted file mode 100644 index e657376c..00000000 --- a/test/nuts/tracking/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023, 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 - */ - -// Types are copied from plugin-source. Used by the tracking NUTs to validate that behavior is identical between the two plugins. -type StatusActualState = 'Deleted' | 'Add' | 'Changed' | 'Unchanged'; -type StatusOrigin = 'Local' | 'Remote'; -type StatusStateString = `${StatusOrigin} ${StatusActualState}` | `${StatusOrigin} ${StatusActualState} (Conflict)`; - -export type StatusResult = { - state: StatusStateString; - fullName: string; - type: string; - filePath?: string; - ignored?: boolean; - conflict?: boolean; - actualState?: StatusActualState; - origin: StatusOrigin; -};