Skip to content

Commit

Permalink
Replace force source status (#1197)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
iowillhoit and WillieRuemmele authored Oct 29, 2024
1 parent faea743 commit f1d0abf
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 298 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
6 changes: 3 additions & 3 deletions test/nuts/delete/source.nut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<DeleteSourceJson>(`project:delete:source -p ${lwcPath} --no-prompt --json`).jsonOutput
?.result;
assert(deleteResult?.deletedSource);
Expand Down Expand Up @@ -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<DeleteSourceJson>(`project:delete:source -p ${mylwcPath} --no-prompt --json`)
Expand Down
129 changes: 40 additions & 89 deletions test/nuts/tracking/basics.nut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<StatusResult[]>('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<PreviewResult>('deploy metadata preview --json', {
const response = execCmd<PreviewResult>('project deploy preview --json', {
ensureExitCode: 0,
}).jsonOutput?.result;
assert(response);
Expand All @@ -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<PreviewResult>('deploy metadata preview --metadata ApexClass --json', {
const response = execCmd<PreviewResult>('project deploy preview --metadata ApexClass --json', {
ensureExitCode: 0,
}).jsonOutput?.result;
assert(response);
Expand All @@ -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<StatusResult[]>('force:source:status --json --local', {
const localResult = execCmd<PreviewResult>('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<StatusResult[]>('force:source:status --json --remote', {
const remoteResult = execCmd<PreviewResult>('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<PreviewResult>('deploy metadata preview --json', {
it('sees no local changes (all were committed from push)', () => {
const response = execCmd<PreviewResult>('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<StatusResult[]>('force:source:status --json --remote', {
it('sees no remote changes (all were committed from push) except Profile', () => {
const remoteResult = execCmd<PreviewResult>('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', () => {
Expand All @@ -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<StatusResult[]>('force:source:status --json', {
const deployResult = execCmd<PreviewResult>('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<PreviewResult>('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<PreviewResult>('deploy metadata preview --json', {
it('no local changes', () => {
const response = execCmd<PreviewResult>('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<DeployResultJson>('project deploy start --json', {
ensureExitCode: 0,
}).jsonOutput?.result;
Expand All @@ -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<StatusResult[]>('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<PreviewResult>('deploy metadata preview --json', {
const response = execCmd<PreviewResult>('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',
Expand All @@ -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<StatusResult[]>('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<PreviewResult>('retrieve metadata preview --json', {
ensureExitCode: 0,
}).jsonOutput?.result;
Expand All @@ -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<DeployResultJson>('deploy metadata --json', {
const result = execCmd<DeployResultJson>('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<StatusResult[]>('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<PreviewResult>('deploy metadata preview --json', {
it('no local changes', () => {
const response = execCmd<PreviewResult>('project deploy preview --json', {
ensureExitCode: 0,
}).jsonOutput?.result;

Expand All @@ -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');
Expand Down Expand Up @@ -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<StatusResult[]>('force:source:status --json --local', {
const result = execCmd<PreviewResult>('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<PreviewResult>('deploy metadata preview --json', {
it('sees no local changes', () => {
const response = execCmd<PreviewResult>('project deploy preview --json', {
ensureExitCode: 0,
}).jsonOutput?.result;
assert(response);
Expand Down
36 changes: 11 additions & 25 deletions test/nuts/tracking/conflicts.nut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -70,12 +69,11 @@ describe('conflict detection and resolution', () => {
description: 'modified',
},
});
const result = execCmd<StatusResult[]>('force:source:status --json --remote', {
const result = execCmd<PreviewResult>('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);
});
Expand All @@ -94,36 +92,24 @@ describe('conflict detection and resolution', () => {
);
});
it('can see the conflict in status', () => {
const result = execCmd<StatusResult[]>('force:source:status --json', {
const result = execCmd<PreviewResult>('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<PreviewResult>('deploy metadata preview --json', {
ensureExitCode: 0,
}).jsonOutput?.result.conflicts.filter((app) => app.type === 'CustomApplication');
Expand All @@ -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<PreviewResult>('retrieve metadata preview --json', {
ensureExitCode: 0,
}).jsonOutput?.result.conflicts.filter((app) => app.type === 'CustomApplication');
Expand All @@ -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<PreviewResult>('deploy metadata preview --json -c', {
ensureExitCode: 0,
}).jsonOutput?.result.toDeploy.filter((app) => app.type === 'CustomApplication');
Expand All @@ -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<PreviewResult>('retrieve metadata preview --json -c', {
ensureExitCode: 0,
}).jsonOutput?.result.toRetrieve.filter((app) => app.type === 'CustomApplication');
Expand Down
9 changes: 5 additions & 4 deletions test/nuts/tracking/deleteResetTracking.nut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<PreviewResult>('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', () => {
Expand Down Expand Up @@ -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')
Expand Down
Loading

0 comments on commit f1d0abf

Please sign in to comment.