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
11 changes: 5 additions & 6 deletions messages/runtest.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ NOTE: The testRunCoverage value (JSON and JUnit result formats) is a percentage
<%= config.bin %> <%= command.id %> --test-level RunLocalTests --output-dir <path to outputdir> --target-org me@my.org

- Run all tests in the org asynchronously:

<%= config.bin %> <%= command.id %> --target-org myscratch

- Run all tests synchronously; the command waits to display the test results until all tests finish:

<%= config.bin %> <%= command.id %> --synchronous

- Run specific tests using the --test-level flag:
Expand All @@ -51,13 +51,12 @@ NOTE: The testRunCoverage value (JSON and JUnit result formats) is a percentage
<%= config.bin %> <%= command.id %> --class-names TestA --class-names TestB --result-format tap --code-coverage

- Run Apex tests on methods specified using the standard Class.method notation; if you specify a test class without a method, the command runs all methods in the class:

<%= config.bin %> <%= command.id %> --tests TestA.excitingMethod --tests TestA.boringMethod --tests TestB

- Run Apex tests on methods specified using the standard Class.method notation with a namespace:

<%= config.bin %> <%= command.id %> --tests ns.TestA.excitingMethod --tests ns.TestA.boringMethod --tests ns.TestB


# flags.class-names.summary

Expand Down Expand Up @@ -144,7 +143,7 @@ Encountered an error when processing test results

# apexTestReportFormatHint

Run "%s apex get test %s --result-format <format>" to retrieve test results in a different format.
Run "sf apex get test %s --result-format <format>" to retrieve test results in a different format.

# outputDirHint

Expand Down
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@
"author": "Salesforce",
"bugs": "https://github.com/forcedotcom/cli/issues",
"dependencies": {
"@oclif/core": "^4",
"@salesforce/apex-node": "^6.1.2",
"@salesforce/core": "^7.4.1",
"@salesforce/apex-node": "^7.0.3",
"@salesforce/core": "^8.1.0",
"@salesforce/kit": "^3.1.6",
"@salesforce/sf-plugins-core": "^11.1.0",
"@salesforce/sf-plugins-core": "^11.1.2",
"ansis": "^3.2.0"
},
"devDependencies": {
"@oclif/core": "^4.0.8",
"@oclif/plugin-command-snapshot": "^5.2.3",
"@salesforce/cli-plugins-testkit": "^5.3.17",
"@salesforce/dev-scripts": "^10.2.0",
"@salesforce/plugin-command-reference": "^3.1.2",
"eslint-plugin-sf-plugin": "^1.18.9",
"oclif": "^4.13.10",
"@salesforce/dev-scripts": "^10.2.2",
"@salesforce/plugin-command-reference": "^3.1.8",
"eslint-plugin-sf-plugin": "^1.18.10",
"oclif": "^4.13.12",
"ts-node": "^10.9.2",
"typescript": "^5.5.2"
},
Expand Down
2 changes: 1 addition & 1 deletion src/commands/apex/get/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default class Test extends SfCommand<RunResult> {
const testService = new TestService(conn);
const result = await testService.reportAsyncResults(flags['test-run-id'], flags['code-coverage']);

const testReporter = new TestReporter(new Ux({ jsonEnabled: this.jsonEnabled() }), conn, this.config.bin);
const testReporter = new TestReporter(new Ux({ jsonEnabled: this.jsonEnabled() }), conn);

return testReporter.report(result, {
'output-dir': flags['output-dir'],
Expand Down
2 changes: 1 addition & 1 deletion src/commands/apex/run/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export default class Test extends SfCommand<RunCommandResult> {
}

if ('summary' in result) {
const testReporter = new TestReporter(new Ux({ jsonEnabled: this.jsonEnabled() }), conn, this.config.bin);
const testReporter = new TestReporter(new Ux({ jsonEnabled: this.jsonEnabled() }), conn);
return testReporter.report(result, flags);
} else {
// Tests were ran asynchronously or the --wait timed out.
Expand Down
5 changes: 2 additions & 3 deletions src/reporters/testReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ export class TestReporter {
*
* @param ux a new Ux instance based on if the command is in json mode
* @param connection a connection to the org the tests are being run against - used for getting username for hints
* @param bin the bin of the cli, used for providing suggestions in the users cli
*/
public constructor(private readonly ux: Ux, private readonly connection: Connection, private readonly bin: string) {}
public constructor(private readonly ux: Ux, private readonly connection: Connection) {}

public async report(
result: TestResult,
Expand Down Expand Up @@ -208,6 +207,6 @@ export class TestReporter {
if (username) {
reportArgs += ` -o ${username}`;
}
return messages.getMessage('apexTestReportFormatHint', [this.bin, reportArgs]);
return messages.getMessage('apexTestReportFormatHint', [reportArgs]);
}
}
33 changes: 15 additions & 18 deletions test/commands/apex/get/log.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import fs from 'node:fs';
import { Config } from '@oclif/core';
import sinon from 'sinon';
import { LogService } from '@salesforce/apex-node';
import { expect } from 'chai';
import { SfCommand } from '@salesforce/sf-plugins-core';
import { stubSfCommandUx } from '@salesforce/sf-plugins-core';
import { Org } from '@salesforce/core';
import ansis from 'ansis';
import Log, { LogGetResult } from '../../../../src/commands/apex/get/log.js';
Expand All @@ -18,14 +17,12 @@ const strip = new ansis.Ansis().strip;
const logStripper = (log: LogGetResult[number]) => (typeof log === 'string' ? strip(log) : { log: strip(log.log) });

describe('apex:log:get', () => {
let config: Config;
let sandbox: sinon.SinonSandbox;
let logStub: sinon.SinonStub;
let uxStub: ReturnType<typeof stubSfCommandUx>;

beforeEach(async () => {
config = await Config.load(import.meta.url);
sandbox = sinon.createSandbox();
logStub = sandbox.stub(SfCommand.prototype, 'log');
uxStub = stubSfCommandUx(sandbox);
sandbox.stub(Org, 'create').resolves({ getConnection: () => ({}) } as Org);
});

Expand All @@ -42,38 +39,38 @@ describe('apex:log:get', () => {

it('0 logs to get', async () => {
sandbox.stub(LogService.prototype, 'getLogs').resolves([]);
const result = await Log.run([], config);
const result = await Log.run([]);
expect(result).to.deep.equal([]);
expect(logStub.firstCall.args[0]).to.equal('No results found');
expect(uxStub.log.firstCall.args[0]).to.equal('No results found');
});

it('outputdir will write to fs', async () => {
sandbox.stub(LogService.prototype, 'getLogs').resolves([{ log: 'myLog' }]);
const result = await new Log(['--output-dir', 'myDirectory'], config).run();
const result = await Log.run(['--output-dir', 'myDirectory']);
expect(result).to.deep.equal(['myLog']);
expect(logStub.firstCall.args[0]).to.equal('Log files written to myDirectory');
expect(uxStub.log.firstCall.args[0]).to.equal('Log files written to myDirectory');
});

it('outputdir will write to fs --json', async () => {
sandbox.stub(LogService.prototype, 'getLogs').resolves([{ log: 'myLog' }]);
const result = await new Log(['--outputdir', 'myDirectory', '--json'], config).run();
const result = await Log.run(['--outputdir', 'myDirectory', '--json']);
expect(result).to.deep.equal(['myLog']);
expect(logStub.firstCall.args[0]).to.equal('Log files written to myDirectory');
expect(uxStub.log.firstCall.args[0]).to.equal('Log files written to myDirectory');
});

it('multiple results', async () => {
sandbox.stub(LogService.prototype, 'getLogs').resolves([{ log: 'myLog' }, { log: 'myLog2' }]);
const result = (await new Log([], config).run()).map(logStripper);
const result = (await Log.run([])).map(logStripper);
expect(result).to.deep.equal([{ log: 'myLog' }, { log: 'myLog2' }]);
expect(logStripper(logStub.firstCall.args[0] as string)).to.equal('myLog');
expect(logStripper(logStub.secondCall.args[0] as string)).to.equal('myLog2');
expect(logStripper(uxStub.log.firstCall.args[0] as string)).to.equal('myLog');
expect(logStripper(uxStub.log.secondCall.args[0] as string)).to.equal('myLog2');
});

it('multiple results --json', async () => {
sandbox.stub(LogService.prototype, 'getLogs').resolves([{ log: 'myLog' }, { log: 'myLog2' }]);
const result = (await new Log(['--json'], config).run()).map(logStripper);
const result = (await Log.run(['--json'])).map(logStripper);
expect(result).to.deep.equal([{ log: 'myLog' }, { log: 'myLog2' }]);
expect(logStripper(logStub.firstCall.args[0] as string)).to.equal('myLog');
expect(logStripper(logStub.secondCall.args[0] as string)).to.equal('myLog2');
expect(logStripper(uxStub.log.firstCall.args[0] as string)).to.equal('myLog');
expect(logStripper(uxStub.log.secondCall.args[0] as string)).to.equal('myLog2');
});
});
46 changes: 21 additions & 25 deletions test/commands/apex/get/test.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,24 @@
import fs from 'node:fs';
import { Connection, Org } from '@salesforce/core';
import sinon from 'sinon';
import { Ux } from '@salesforce/sf-plugins-core';
import { Config } from '@oclif/core';
import { expect } from 'chai';
import { Ux, stubSfCommandUx } from '@salesforce/sf-plugins-core';
import { expect, config } from 'chai';
import { TestService } from '@salesforce/apex-node';
import Test from '../../../../src/commands/apex/get/test.js';
import { runWithFailures, testRunSimple, testRunSimpleResult, testRunWithFailuresResult } from '../../../testData.js';

config.truncateThreshold = 0;

let logStub: sinon.SinonStub;
let styledJsonStub: sinon.SinonStub;

describe('apex:test:report', () => {
let sandbox: sinon.SinonSandbox;
let config: Config;
let uxStub: ReturnType<typeof stubSfCommandUx>;

beforeEach(async () => {
config = await Config.load(import.meta.url);
sandbox = sinon.createSandbox();
uxStub = stubSfCommandUx(sandbox);
logStub = sandbox.stub(Ux.prototype, 'log');
styledJsonStub = sandbox.stub(Ux.prototype, 'styledJSON');
sandbox.stub(Connection.prototype, 'getUsername').returns('test@example.com');
Expand All @@ -46,19 +47,20 @@ describe('apex:test:report', () => {
it('should return a success human format message with async', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(runWithFailures);

const result = await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human'], config).run();
const result = await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human']);

expect(result).to.deep.equal(testRunWithFailuresResult);
expect(logStub.firstCall.args[0]).to.include('=== Test Summary');
expect(logStub.firstCall.args[0]).to.include('=== Test Results');
expect(logStub.firstCall.args[0]).to.include('Test Run Id 707xx0000AUS2gH');
expect(logStub.firstCall.args[0]).to.include('MyApexTests.testConfig Fail');
expect(uxStub.log.callCount).to.equal(0);
});

it('should return a success tap format message with async', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(runWithFailures);

const result = await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'tap'], config).run();
const result = await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'tap']);

expect(result).to.deep.equal(testRunWithFailuresResult);
expect(logStub.firstCall.args[0]).to.include('1..1');
Expand All @@ -68,7 +70,7 @@ describe('apex:test:report', () => {

it('should return a success junit format message with async', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(runWithFailures);
const result = await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'junit'], config).run();
const result = await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'junit']);
expect(result).to.deep.equal(testRunWithFailuresResult);
expect(logStub.firstCall.args[0]).to.include('<property name="failRate" value="50%"/>');
expect(logStub.firstCall.args[0]).to.include('<property name="outcome" value="Failed"/>');
Expand All @@ -77,33 +79,30 @@ describe('apex:test:report', () => {

it('should return a success json format message with async', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(runWithFailures);
const result = await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'json'], config).run();
const result = await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'json']);
expect(result).to.deep.equal(testRunWithFailuresResult);
expect(styledJsonStub.firstCall.args[0]).to.deep.equal({ result: testRunWithFailuresResult, status: 100 });
});

it('should return a success --json format message with sync', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(runWithFailures);
sandbox.stub(Org.prototype, 'getUsername').returns('test@user.com');
const result = await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--json'], config).run();
const result = await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--json']);
expect(result).to.deep.equal(testRunWithFailuresResult);
expect(styledJsonStub.notCalled).to.be.true;
});

it('should return a success human format with synchronous', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(runWithFailures);
await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human'], config).run();
await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human']);
expect(logStub.firstCall.args[0]).to.contain('Test Summary');
expect(logStub.firstCall.args[0]).to.contain('Test Results');
expect(logStub.firstCall.args[0]).to.not.contain('Apex Code Coverage by Class');
});

it('should warn when using --outputdir', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(runWithFailures);
await new Test(
['--output-dir', 'myDirectory', '--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human'],
config
).run();
await Test.run(['--output-dir', 'myDirectory', '--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human']);
expect(logStub.firstCall.args[0]).to.contain('Test result files written to myDirectory');
});
});
Expand All @@ -112,7 +111,7 @@ describe('apex:test:report', () => {
it('should return a success human format message with async', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple);

const result = await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human'], config).run();
const result = await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human']);

expect(result).to.deep.equal(testRunSimpleResult);
expect(logStub.firstCall.args[0]).to.include('=== Test Summary');
Expand All @@ -124,7 +123,7 @@ describe('apex:test:report', () => {
it('should return a success tap format message with async', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple);

const result = await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'tap'], config).run();
const result = await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'tap']);

expect(result).to.deep.equal(testRunSimpleResult);
expect(logStub.firstCall.args[0]).to.include('1..1');
Expand All @@ -134,7 +133,7 @@ describe('apex:test:report', () => {

it('should return a success junit format message with async', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple);
const result = await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'junit'], config).run();
const result = await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'junit']);
expect(result).to.deep.equal(testRunSimpleResult);
expect(logStub.firstCall.args[0]).to.contain('<testcase name="testConfig" classname="MyApexTests" time="0.05">');
expect(logStub.firstCall.args[0]).to.contain('<property name="testsRan" value="1"/>');
Expand All @@ -143,33 +142,30 @@ describe('apex:test:report', () => {
it('should return a success json format message with async', async () => {
process.exitCode = 0;
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple);
const result = await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'json'], config).run();
const result = await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'json']);
expect(result).to.deep.equal(testRunSimpleResult);
expect(styledJsonStub.firstCall.args[0]).to.deep.equal({ result: testRunSimpleResult, status: 0 });
});

it('should return a success --json format message with sync', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple);
sandbox.stub(Org.prototype, 'getUsername').returns('test@user.com');
const result = await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--json'], config).run();
const result = await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--json']);
expect(result).to.deep.equal(testRunSimpleResult);
expect(styledJsonStub.notCalled).to.be.true;
});

it('should return a success human format with synchronous', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple);
await new Test(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human'], config).run();
await Test.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human']);
expect(logStub.firstCall.args[0]).to.contain('Test Summary');
expect(logStub.firstCall.args[0]).to.contain('Test Results');
expect(logStub.firstCall.args[0]).to.not.contain('Apex Code Coverage by Class');
});

it('should warn when using --outputdir', async () => {
sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple);
await new Test(
['--output-dir', 'myDirectory', '--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human'],
config
).run();
await Test.run(['--output-dir', 'myDirectory', '--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human']);
expect(logStub.firstCall.args[0]).to.contain('Test result files written to myDirectory');
});
});
Expand Down
Loading