Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading