From 25dccc74ac5e4ece50b2292203507558a9cfecac Mon Sep 17 00:00:00 2001 From: Steve Hetzel Date: Tue, 10 Feb 2026 13:25:13 -0700 Subject: [PATCH 1/2] chore: update license for 2026 --- LICENSE.txt | 2 +- src/commands/apex/get/log.ts | 2 +- src/commands/apex/get/test.ts | 2 +- src/commands/apex/list/log.ts | 2 +- src/commands/apex/run.ts | 2 +- src/commands/apex/run/test.ts | 2 +- src/commands/apex/tail/log.ts | 2 +- src/commands/logic/get/test.ts | 2 +- src/commands/logic/run/test.ts | 2 +- src/flags.ts | 2 +- src/index.ts | 2 +- src/logColorize.ts | 2 +- src/reporters/index.ts | 2 +- src/reporters/jsonReporter.ts | 2 +- src/reporters/runReporter.ts | 2 +- src/reporters/testReporter.ts | 2 +- src/shared/TestGetBase.ts | 6 +-- src/shared/TestRunService.ts | 2 +- test/commands/apex/get/log.test.ts | 2 +- test/commands/apex/get/test.nut.ts | 2 +- test/commands/apex/get/test.test.ts | 10 ++-- test/commands/apex/list/log.test.ts | 2 +- test/commands/apex/loggingCommands.nut.ts | 2 +- test/commands/apex/run.test.ts | 2 +- test/commands/apex/run/test.nut.ts | 10 ++-- test/commands/apex/run/test.test.ts | 52 +++--------------- test/commands/apex/tail/log.test.ts | 2 +- test/commands/logic/get/test.nut.ts | 32 ++++++------ test/commands/logic/get/test.test.ts | 44 +++++++++------- test/commands/logic/run/test.nut.ts | 64 ++++++++++++++--------- test/commands/logic/run/test.test.ts | 2 +- test/commands/logic/testHelper.ts | 43 ++++++++++----- test/reporters/jsonReporter.test.ts | 2 +- test/reporters/testReporter.test.ts | 48 ++++++++--------- test/testData.ts | 4 +- test/utils.test.ts | 2 +- 36 files changed, 182 insertions(+), 183 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index ca35d0df..1aeebc57 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ Apache License Version 2.0 -Copyright (c) 2025 Salesforce, Inc. +Copyright (c) 2026 Salesforce, Inc. All rights reserved. Apache License diff --git a/src/commands/apex/get/log.ts b/src/commands/apex/get/log.ts index 698a5cc5..9efc955b 100644 --- a/src/commands/apex/get/log.ts +++ b/src/commands/apex/get/log.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/commands/apex/get/test.ts b/src/commands/apex/get/test.ts index 87c593ea..7469c969 100644 --- a/src/commands/apex/get/test.ts +++ b/src/commands/apex/get/test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/commands/apex/list/log.ts b/src/commands/apex/list/log.ts index 97d56144..4620c157 100644 --- a/src/commands/apex/list/log.ts +++ b/src/commands/apex/list/log.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/commands/apex/run.ts b/src/commands/apex/run.ts index ccdee184..5b42d7cb 100644 --- a/src/commands/apex/run.ts +++ b/src/commands/apex/run.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/commands/apex/run/test.ts b/src/commands/apex/run/test.ts index 9f066142..d6a3fe7b 100644 --- a/src/commands/apex/run/test.ts +++ b/src/commands/apex/run/test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/commands/apex/tail/log.ts b/src/commands/apex/tail/log.ts index 19bd62fc..6512446d 100644 --- a/src/commands/apex/tail/log.ts +++ b/src/commands/apex/tail/log.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/commands/logic/get/test.ts b/src/commands/logic/get/test.ts index 3087a81d..470cde58 100644 --- a/src/commands/logic/get/test.ts +++ b/src/commands/logic/get/test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/commands/logic/run/test.ts b/src/commands/logic/run/test.ts index 7584f294..8bca9876 100644 --- a/src/commands/logic/run/test.ts +++ b/src/commands/logic/run/test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/flags.ts b/src/flags.ts index 20f52d08..8559bff3 100644 --- a/src/flags.ts +++ b/src/flags.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/index.ts b/src/index.ts index 3cbf49e6..124dde53 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/logColorize.ts b/src/logColorize.ts index bd8711e8..6fb86eb1 100644 --- a/src/logColorize.ts +++ b/src/logColorize.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/reporters/index.ts b/src/reporters/index.ts index 6aa62abe..eac44b5a 100644 --- a/src/reporters/index.ts +++ b/src/reporters/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/reporters/jsonReporter.ts b/src/reporters/jsonReporter.ts index cd961557..639960ac 100644 --- a/src/reporters/jsonReporter.ts +++ b/src/reporters/jsonReporter.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/reporters/runReporter.ts b/src/reporters/runReporter.ts index 0d6a9273..24ce3185 100644 --- a/src/reporters/runReporter.ts +++ b/src/reporters/runReporter.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/reporters/testReporter.ts b/src/reporters/testReporter.ts index 9ef391c4..710c5c9b 100644 --- a/src/reporters/testReporter.ts +++ b/src/reporters/testReporter.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/shared/TestGetBase.ts b/src/shared/TestGetBase.ts index 99009e44..987c3eb7 100644 --- a/src/shared/TestGetBase.ts +++ b/src/shared/TestGetBase.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,7 +49,7 @@ export class TestGetBase { detailedCoverage, concise, jsonEnabled, - isUnifiedLogic + isUnifiedLogic, } = options; const testService = new TestService(connection); @@ -64,7 +64,7 @@ export class TestGetBase { 'code-coverage': codeCoverage, 'detailed-coverage': detailedCoverage, concise: concise ?? false, - isUnifiedLogic + isUnifiedLogic, }; return testReporter.report(result, reportOptions); diff --git a/src/shared/TestRunService.ts b/src/shared/TestRunService.ts index 3e035af7..0fa2de10 100644 --- a/src/shared/TestRunService.ts +++ b/src/shared/TestRunService.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/commands/apex/get/log.test.ts b/test/commands/apex/get/log.test.ts index a8ec4ec1..29960f0e 100644 --- a/test/commands/apex/get/log.test.ts +++ b/test/commands/apex/get/log.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/commands/apex/get/test.nut.ts b/test/commands/apex/get/test.nut.ts index b10ae89d..2cd660b0 100644 --- a/test/commands/apex/get/test.nut.ts +++ b/test/commands/apex/get/test.nut.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/commands/apex/get/test.test.ts b/test/commands/apex/get/test.test.ts index d71582be..ea71ae87 100644 --- a/test/commands/apex/get/test.test.ts +++ b/test/commands/apex/get/test.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -208,12 +208,12 @@ describe('apex:test:report', () => { describe('isUnifiedLogic parameter', () => { it('should NOT pass isUnifiedLogic parameter', async () => { - testReporterReportStub = sandbox.stub(TestReporter.prototype, 'report'); - sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple); - testReporterReportStub.resolves({ success: true }); + testReporterReportStub = sandbox.stub(TestReporter.prototype, 'report'); + sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple); + testReporterReportStub.resolves({ success: true }); await Test.run(['--test-run-id', '7071w00003woTsc', '--target-org', 'test@example.com']); - expect(testReporterReportStub.calledOnce).to.be.true; + expect(testReporterReportStub.calledOnce).to.be.true; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access expect(testReporterReportStub.getCall(0).args[1].isUnifiedLogic).to.be.undefined; }); diff --git a/test/commands/apex/list/log.test.ts b/test/commands/apex/list/log.test.ts index 266e2b26..313fdfd4 100644 --- a/test/commands/apex/list/log.test.ts +++ b/test/commands/apex/list/log.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/commands/apex/loggingCommands.nut.ts b/test/commands/apex/loggingCommands.nut.ts index 3a316197..4b154c05 100644 --- a/test/commands/apex/loggingCommands.nut.ts +++ b/test/commands/apex/loggingCommands.nut.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/commands/apex/run.test.ts b/test/commands/apex/run.test.ts index 2c545a33..914697cc 100644 --- a/test/commands/apex/run.test.ts +++ b/test/commands/apex/run.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/commands/apex/run/test.nut.ts b/test/commands/apex/run/test.nut.ts index 011185c1..8bff065f 100644 --- a/test/commands/apex/run/test.nut.ts +++ b/test/commands/apex/run/test.nut.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -211,8 +211,8 @@ describe('apex run test', () => { }); it('will run specified test suites --class-names', async () => { - const result = execCmd('apex:run:test -w 10 --suite-names DreamhouseTestSuite', { ensureExitCode: 0 }) - .shellOutput.stdout; + const result = execCmd('apex:run:test -w 10 --suite-names DreamhouseTestSuite', { ensureExitCode: 0 }).shellOutput + .stdout; expect(result).to.match(/Tests Ran\s+10/); expect(result).to.include('FileUtilitiesTest.'); expect(result).to.include('TestPropertyController.'); @@ -279,13 +279,13 @@ function addTestSuiteFile(projectDir: string): void { if (!fs.existsSync(testSuitesDir)) { fs.mkdirSync(testSuitesDir, { recursive: true }); } - + const xmlContent = ` FileUtilitiesTest GeocodingServiceTest TestPropertyController `; - const filePath = path.join(testSuitesDir, 'DreamhouseTestSuite.testSuite-meta.xml'); + const filePath = path.join(testSuitesDir, 'DreamhouseTestSuite.testSuite-meta.xml'); fs.writeFileSync(filePath, xmlContent, 'utf8'); } diff --git a/test/commands/apex/run/test.test.ts b/test/commands/apex/run/test.test.ts index a3391e38..3352beb4 100644 --- a/test/commands/apex/run/test.test.ts +++ b/test/commands/apex/run/test.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -165,22 +165,10 @@ describe('apex:test:run', () => { const runTestSynchronousSpy = sandbox .stub(TestService.prototype, 'runTestAsynchronous') .resolves(runWithCoverage); - await Test.run([ - '--code-coverage', - '--result-format', - 'human', - '--test-level', - 'RunLocalTests', - ]); + await Test.run(['--code-coverage', '--result-format', 'human', '--test-level', 'RunLocalTests']); expect(buildPayloadSpy.calledOnce).to.be.true; expect(runTestSynchronousSpy.calledOnce).to.be.true; - expect(buildPayloadSpy.firstCall.args).to.deep.equal([ - 'RunLocalTests', - undefined, - undefined, - undefined, - 'Apex', - ]); + expect(buildPayloadSpy.firstCall.args).to.deep.equal(['RunLocalTests', undefined, undefined, undefined, 'Apex']); expect(runTestSynchronousSpy.firstCall.args[0]).to.deep.equal({ category: ['Apex'], skipCodeCoverage: false, @@ -198,13 +186,7 @@ describe('apex:test:run', () => { await Test.run(['--class-names', 'myApex', '--test-level', 'RunSpecifiedTests']); expect(buildPayloadSpy.calledOnce).to.be.true; expect(runTestSynchronousSpy.calledOnce).to.be.true; - expect(buildPayloadSpy.firstCall.args).to.deep.equal([ - 'RunSpecifiedTests', - undefined, - 'myApex', - undefined, - '', - ]); + expect(buildPayloadSpy.firstCall.args).to.deep.equal(['RunSpecifiedTests', undefined, 'myApex', undefined, '']); expect(runTestSynchronousSpy.firstCall.args[0]).to.deep.equal({ skipCodeCoverage: true, testLevel: 'RunSpecifiedTests', @@ -426,27 +408,15 @@ describe('apex:test:run', () => { const runTestSynchronousSpy = sandbox .stub(TestService.prototype, 'runTestAsynchronous') .resolves(runWithCoverage); - await Test.run([ - '--code-coverage', - '--result-format', - 'human', - '--test-level', - 'RunLocalTests', - ]); + await Test.run(['--code-coverage', '--result-format', 'human', '--test-level', 'RunLocalTests']); expect(buildPayloadSpy.calledOnce).to.be.true; expect(runTestSynchronousSpy.calledOnce).to.be.true; - expect(buildPayloadSpy.firstCall.args).to.deep.equal([ - 'RunLocalTests', - undefined, - undefined, - undefined, - 'Apex', - ]); + expect(buildPayloadSpy.firstCall.args).to.deep.equal(['RunLocalTests', undefined, undefined, undefined, 'Apex']); expect(runTestSynchronousSpy.firstCall.args[0]).to.deep.equal({ category: ['Apex'], skipCodeCoverage: false, suiteNames: undefined, - testLevel: 'RunLocalTests' + testLevel: 'RunLocalTests', }); }); @@ -457,13 +427,7 @@ describe('apex:test:run', () => { await Test.run(['--class-names', 'myApex', '--test-level', 'RunSpecifiedTests']); expect(buildPayloadSpy.calledOnce).to.be.true; expect(runTestSynchronousSpy.calledOnce).to.be.true; - expect(buildPayloadSpy.firstCall.args).to.deep.equal([ - 'RunSpecifiedTests', - undefined, - 'myApex', - undefined, - '', - ]); + expect(buildPayloadSpy.firstCall.args).to.deep.equal(['RunSpecifiedTests', undefined, 'myApex', undefined, '']); expect(runTestSynchronousSpy.firstCall.args[0]).to.deep.equal({ skipCodeCoverage: true, testLevel: 'RunSpecifiedTests', diff --git a/test/commands/apex/tail/log.test.ts b/test/commands/apex/tail/log.test.ts index 6db35113..d51a299b 100644 --- a/test/commands/apex/tail/log.test.ts +++ b/test/commands/apex/tail/log.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/commands/logic/get/test.nut.ts b/test/commands/logic/get/test.nut.ts index f333649b..2ef1c493 100644 --- a/test/commands/logic/get/test.nut.ts +++ b/test/commands/logic/get/test.nut.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,12 +28,11 @@ describe('logic get test', () => { before(async () => { session = await setupUnifiedFrameworkProject(); - // Run tests to get a test run ID for subsequent get operations testRunId = execCmd('logic:run:test --test-level RunLocalTests --json', { ensureExitCode: 0, }).jsonOutput?.result.testRunId.trim(); - + expect(testRunId).to.be.a('string'); expect(testRunId).to.match(/^707/); // Test run IDs start with 707 }); @@ -46,7 +45,7 @@ describe('logic get test', () => { it('should get test results with default format', async () => { const result = execCmd(`logic:get:test --test-run-id ${testRunId}`, { ensureExitCode: 0 }); const output = result.shellOutput.stdout; - + // Verify basic output structure expect(output).to.include('Test Results'); expect(output).to.include('Outcome'); @@ -56,10 +55,10 @@ describe('logic get test', () => { }); it('should get test results in JSON format', async () => { - const result = execCmd(`logic:get:test --test-run-id ${testRunId} --json`, { - ensureExitCode: 0 + const result = execCmd(`logic:get:test --test-run-id ${testRunId} --json`, { + ensureExitCode: 0, }); - + const jsonResult = result.jsonOutput?.result; expect(jsonResult).to.be.an('object'); expect(jsonResult).to.have.property('summary'); @@ -72,10 +71,10 @@ describe('logic get test', () => { }); it('should get test results with code coverage', async () => { - const result = execCmd(`logic:get:test --test-run-id ${testRunId} --code-coverage`, { - ensureExitCode: 0 + const result = execCmd(`logic:get:test --test-run-id ${testRunId} --code-coverage`, { + ensureExitCode: 0, }); - const output = result.shellOutput.stdout; + const output = result.shellOutput.stdout; // Verify code coverage information is included expect(output).to.include('Code Coverage'); }); @@ -83,11 +82,11 @@ describe('logic get test', () => { describe('result formats', () => { it('should output in JSON format', async () => { - const result = execCmd(`logic:get:test --test-run-id ${testRunId} --result-format json`, { - ensureExitCode: 0 + const result = execCmd(`logic:get:test --test-run-id ${testRunId} --result-format json`, { + ensureExitCode: 0, }); const output = result.shellOutput.stdout; - + // Should be valid JSON // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-assignment expect(() => JSON.parse(output)).to.not.throw(); @@ -99,12 +98,11 @@ describe('logic get test', () => { }); describe('code coverage options', () => { - it('should include code coverage in JSON format', async () => { - const result = execCmd(`logic:get:test --test-run-id ${testRunId} --code-coverage --json`, { - ensureExitCode: 0 + const result = execCmd(`logic:get:test --test-run-id ${testRunId} --code-coverage --json`, { + ensureExitCode: 0, }); - + const jsonResult = result.jsonOutput?.result; expect(jsonResult).to.have.property('coverage'); }); diff --git a/test/commands/logic/get/test.test.ts b/test/commands/logic/get/test.test.ts index a64a76c9..a1bed007 100644 --- a/test/commands/logic/get/test.test.ts +++ b/test/commands/logic/get/test.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,23 +65,23 @@ describe('logic:test:report', () => { describe('test failures', () => { it('should return a success human format message with async and include the test category', async () => { sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(logicRunWithFailures); - + const result = await LogicTest.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human']); - + expect(result).to.deep.equal(logicTestRunWithFailuresResult); expect(logStub.firstCall.args[0]).to.include('TEST NAME CATEGORY'); expect(logStub.firstCall.args[0]).to.include('ApexTests.testConfig Apex'); expect(logStub.firstCall.args[0]).to.include('Fail'); expect(uxStub.log.callCount).to.equal(0); }); - + it('should return a success json format message with async and include the test category', async () => { sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(logicRunWithFailures); const result = await LogicTest.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'json']); expect(result).to.deep.equal(logicTestRunWithFailuresResult); expect(styledJsonStub.firstCall.args[0]).to.deep.equal({ result: logicTestRunWithFailuresResult, status: 100 }); }); - + it('should return a success --json format message with sync and include the test category', async () => { sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(logicRunWithFailures); sandbox.stub(Org.prototype, 'getUsername').returns('test@user.com'); @@ -90,7 +90,7 @@ describe('logic:test:report', () => { expect(logStub.firstCall.args[0]).to.include('TEST NAME CATEGORY'); expect(styledJsonStub.notCalled).to.be.true; }); - + it('should return a success human format with synchronous and include the test categorys', async () => { sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(logicRunWithFailures); await LogicTest.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human']); @@ -99,7 +99,7 @@ describe('logic:test:report', () => { expect(logStub.firstCall.args[0]).to.not.contain('Apex Code Coverage by Class'); expect(logStub.firstCall.args[0]).to.include('TEST NAME CATEGORY'); }); - + it('should only display failed test with human format with concise flag and include the test categorys', async () => { sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(logicRunWithFailures); await LogicTest.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human', '--concise']); @@ -111,13 +111,13 @@ describe('logic:test:report', () => { expect(logStub.firstCall.args[0]).to.include('TEST NAME CATEGORY'); }); }); - + describe('test success', () => { it('should return a success human format message with async and include the test categorys', async () => { sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(logicTestRunSimple); - + const result = await LogicTest.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human']); - + expect(result).to.deep.equal(logicTestRunSimpleResult); expect(logStub.firstCall.args[0]).to.include('=== Test Summary'); expect(logStub.firstCall.args[0]).to.include('=== Test Results'); @@ -125,7 +125,7 @@ describe('logic:test:report', () => { expect(logStub.firstCall.args[0]).to.include('TEST NAME CATEGORY'); expect(logStub.firstCall.args[0]).to.include('MyApexTests.testConfig Apex Pass 53'); }); - + it('should return a success json format message with async and include the test categorys', async () => { process.exitCode = 0; sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(logicTestRunSimple); @@ -133,7 +133,7 @@ describe('logic:test:report', () => { expect(result).to.deep.equal(logicTestRunSimpleResult); expect(styledJsonStub.firstCall.args[0]).to.deep.equal({ result: logicTestRunSimpleResult, status: 0 }); }); - + it('should return a success --json format message with sync and include the test categorys', async () => { sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(logicTestRunSimple); sandbox.stub(Org.prototype, 'getUsername').returns('test@user.com'); @@ -141,7 +141,7 @@ describe('logic:test:report', () => { expect(result).to.deep.equal(logicTestRunSimpleResult); expect(styledJsonStub.notCalled).to.be.true; }); - + it('should return a success human format with synchronous and include the test categorys', async () => { sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(logicTestRunSimple); await LogicTest.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human']); @@ -151,10 +151,17 @@ describe('logic:test:report', () => { expect(logStub.firstCall.args[0]).to.include('TEST NAME CATEGORY'); expect(logStub.firstCall.args[0]).to.include('MyApexTests.testConfig Apex Pass 53'); }); - + it('should only display summary with human format and code coverage and concise parameters', async () => { sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(logicRunWithCoverage); - await LogicTest.run(['--test-run-id', '707xxxxxxxxxxxx', '--result-format', 'human', '--code-coverage', '--concise']); + await LogicTest.run([ + '--test-run-id', + '707xxxxxxxxxxxx', + '--result-format', + 'human', + '--code-coverage', + '--concise', + ]); expect(logStub.firstCall.args[0]).to.contain('Test Summary'); expect(logStub.firstCall.args[0]).to.not.contain('Test Results'); expect(logStub.firstCall.args[0]).to.not.contain('Apex Code Coverage by Class'); @@ -163,12 +170,11 @@ describe('logic:test:report', () => { }); }); - describe('isUnifiedLogic parameter', () => { it('should pass isUnifiedLogic parameter', async () => { - testReporterReportStub = sandbox.stub(TestReporter.prototype, 'report'); - sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple); - testReporterReportStub.resolves({ success: true }); + testReporterReportStub = sandbox.stub(TestReporter.prototype, 'report'); + sandbox.stub(TestService.prototype, 'reportAsyncResults').resolves(testRunSimple); + testReporterReportStub.resolves({ success: true }); await LogicTest.run(['--test-run-id', '7071w00003woTsc', '--target-org', 'test@example.com']); expect(testReporterReportStub.calledOnce).to.be.true; diff --git a/test/commands/logic/run/test.nut.ts b/test/commands/logic/run/test.nut.ts index e1d19638..f72a38b9 100644 --- a/test/commands/logic/run/test.nut.ts +++ b/test/commands/logic/run/test.nut.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,8 +33,8 @@ describe('logic run test', () => { describe('--test-category', () => { it('will run tests with Apex category', async () => { - const result = execCmd('logic:run:test --test-category Apex --test-level RunLocalTests --wait 10', { - ensureExitCode: 0 + const result = execCmd('logic:run:test --test-category Apex --test-level RunLocalTests --wait 10', { + ensureExitCode: 0, }).shellOutput.stdout; expect(result).to.include('CATEGORY'); expect(result).to.include('Apex'); @@ -42,8 +42,8 @@ describe('logic run test', () => { }); it('will run tests with Flow category', async () => { - const result = execCmd('logic:run:test --test-category Flow --test-level RunLocalTests --wait 10', { - ensureExitCode: 0 + const result = execCmd('logic:run:test --test-category Flow --test-level RunLocalTests --wait 10', { + ensureExitCode: 0, }).shellOutput.stdout; expect(result).to.include('CATEGORY'); expect(result).to.include('Flow'); @@ -51,9 +51,12 @@ describe('logic run test', () => { }); it('will run tests with multiple categories', async () => { - const result = execCmd('logic:run:test --test-category Apex --test-category Flow --test-level RunLocalTests --wait 10', { - ensureExitCode: 0 - }).shellOutput.stdout; + const result = execCmd( + 'logic:run:test --test-category Apex --test-category Flow --test-level RunLocalTests --wait 10', + { + ensureExitCode: 0, + } + ).shellOutput.stdout; expect(result).to.include('CATEGORY'); expect(result).to.include('Apex'); expect(result).to.include('Flow'); @@ -62,8 +65,8 @@ describe('logic run test', () => { describe('--class-names', () => { it('will run specified class', async () => { - const result = execCmd('logic:run:test --class-names GeocodingServiceTest --wait 10', { - ensureExitCode: 0 + const result = execCmd('logic:run:test --class-names GeocodingServiceTest --wait 10', { + ensureExitCode: 0, }).shellOutput.stdout; expect(result).to.match(/Tests Ran\s+3/); expect(result).to.include('GeocodingServiceTest'); @@ -73,21 +76,27 @@ describe('logic run test', () => { }); it('will run multiple specified classes from different categories', async () => { - const result = execCmd('logic:run:test --class-names GeocodingServiceTest --class-names FlowTesting.Populate_opp_description --wait 10', { - ensureExitCode: 0 - }).shellOutput.stdout; + const result = execCmd( + 'logic:run:test --class-names GeocodingServiceTest --class-names FlowTesting.Populate_opp_description --wait 10', + { + ensureExitCode: 0, + } + ).shellOutput.stdout; expect(result).to.match(/Tests Ran\s+4/); expect(result).to.include('CATEGORY'); expect(result).to.include('Apex'); expect(result).to.include('Flow'); }); - }); + }); describe('--tests', () => { it('will run specified test methods', async () => { - const result = execCmd('logic:run:test --tests FlowTesting.Populate_opp_description.test_opportunity_updates --wait 10', { - ensureExitCode: 0 - }).shellOutput.stdout; + const result = execCmd( + 'logic:run:test --tests FlowTesting.Populate_opp_description.test_opportunity_updates --wait 10', + { + ensureExitCode: 0, + } + ).shellOutput.stdout; expect(result).to.match(/Tests Ran\s+1/); expect(result).to.include('CATEGORY'); expect(result).to.include('Flow'); @@ -96,9 +105,12 @@ describe('logic run test', () => { }); it('will run multiple test methods from different categories', async () => { - const result = execCmd('logic:run:test --tests TestPropertyController.testGetPicturesWithResults --tests FlowTesting.Populate_opp_description.test_opportunity_updates --wait 10', { - ensureExitCode: 0 - }).shellOutput.stdout; + const result = execCmd( + 'logic:run:test --tests TestPropertyController.testGetPicturesWithResults --tests FlowTesting.Populate_opp_description.test_opportunity_updates --wait 10', + { + ensureExitCode: 0, + } + ).shellOutput.stdout; expect(result).to.match(/Tests Ran\s+2/); expect(result).to.include('CATEGORY'); expect(result).to.include('Apex'); @@ -110,8 +122,8 @@ describe('logic run test', () => { describe('JSON output', () => { it('will run tests and return JSON with Category property', async () => { - const result = execCmd('logic:run:test --test-level RunLocalTests --wait 10 --json', { - ensureExitCode: 0 + const result = execCmd('logic:run:test --test-level RunLocalTests --wait 10 --json', { + ensureExitCode: 0, }).jsonOutput?.result; expect(result?.tests.length).to.be.greaterThan(0); expect(result?.summary.outcome).to.equal('Passed'); @@ -151,8 +163,8 @@ describe('logic run test', () => { describe('async execution', () => { it('will run tests async and return test run id', async () => { - const result = execCmd('logic:run:test --test-category Flow --test-level RunLocalTests --json', { - ensureExitCode: 0 + const result = execCmd('logic:run:test --test-category Flow --test-level RunLocalTests --json', { + ensureExitCode: 0, }).jsonOutput?.result; expect(result?.testRunId).to.be.a('string'); expect(result?.testRunId.startsWith('707')).to.be.true; @@ -161,8 +173,8 @@ describe('logic run test', () => { describe('--synchronous', () => { it('will run tests synchronously', async () => { - const result = execCmd('logic:run:test --test-category Apex --test-level RunLocalTests --synchronous', { - ensureExitCode: 0 + const result = execCmd('logic:run:test --test-category Apex --test-level RunLocalTests --synchronous', { + ensureExitCode: 0, }).shellOutput.stdout; expect(result).to.include('Outcome'); expect(result).to.include('CATEGORY'); diff --git a/test/commands/logic/run/test.test.ts b/test/commands/logic/run/test.test.ts index 04483ec6..559dd89b 100644 --- a/test/commands/logic/run/test.test.ts +++ b/test/commands/logic/run/test.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/commands/logic/testHelper.ts b/test/commands/logic/testHelper.ts index b44f032c..b32387a1 100644 --- a/test/commands/logic/testHelper.ts +++ b/test/commands/logic/testHelper.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,35 +36,54 @@ export async function setupUnifiedFrameworkProject(): Promise { }, ], }); - const flowXml = path.join('test', 'nuts', 'unifiedFrameworkProject', 'force-app', 'main', 'default', 'flows', 'Populate_opp_description.flow-meta.xml'); + const flowXml = path.join( + 'test', + 'nuts', + 'unifiedFrameworkProject', + 'force-app', + 'main', + 'default', + 'flows', + 'Populate_opp_description.flow-meta.xml' + ); const flowsDir = path.join(session.project.dir, 'force-app', 'main', 'default', 'flows'); const targetFile = path.join(flowsDir, 'Populate_opp_description.flow-meta.xml'); - + if (!fs.existsSync(flowsDir)) { fs.mkdirSync(flowsDir, { recursive: true }); } - + fs.copyFileSync(flowXml, targetFile); - - const flowTestXml = path.join('test', 'nuts', 'unifiedFrameworkProject', 'force-app', 'main', 'default', 'flowtests', 'test_opportunity_updates.flowtest-meta.xml'); + + const flowTestXml = path.join( + 'test', + 'nuts', + 'unifiedFrameworkProject', + 'force-app', + 'main', + 'default', + 'flowtests', + 'test_opportunity_updates.flowtest-meta.xml' + ); const flowTestsDir = path.join(session.project.dir, 'force-app', 'main', 'default', 'flowtests'); const targetTestFile = path.join(flowTestsDir, 'test_opportunity_updates.flowtest-meta.xml'); - + if (!fs.existsSync(flowTestsDir)) { fs.mkdirSync(flowTestsDir, { recursive: true }); } - + fs.copyFileSync(flowTestXml, targetTestFile); - + const sfdxProjectPath = path.join(session.project.dir, 'sfdx-project.json'); - + // We need to update the sourceApiVersion to 65.0 because the changes in the api are not supported in 64.0 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const sfdxProject = JSON.parse(fs.readFileSync(sfdxProjectPath, 'utf8')); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument - sfdxProject.sourceApiVersion = parseInt(sfdxProject.sourceApiVersion, 10) < 65 ? '65.0' : sfdxProject.sourceApiVersion; + sfdxProject.sourceApiVersion = + parseInt(sfdxProject.sourceApiVersion, 10) < 65 ? '65.0' : sfdxProject.sourceApiVersion; fs.writeFileSync(sfdxProjectPath, JSON.stringify(sfdxProject, null, 2)); execCmd('project:deploy:start --source-dir force-app', { ensureExitCode: 0, cli: 'sf' }); return session; -} \ No newline at end of file +} diff --git a/test/reporters/jsonReporter.test.ts b/test/reporters/jsonReporter.test.ts index 28f4578a..279ec52b 100644 --- a/test/reporters/jsonReporter.test.ts +++ b/test/reporters/jsonReporter.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/reporters/testReporter.test.ts b/test/reporters/testReporter.test.ts index b997b6b6..6cecc4a3 100644 --- a/test/reporters/testReporter.test.ts +++ b/test/reporters/testReporter.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,23 +33,23 @@ describe('TestReporter - isUnifiedLogic parameter', () => { let humanReporterFormatStub: sinon.SinonStub; beforeEach(() => { sandbox = sinon.createSandbox(); - + // Create mocks connection = { getUsername: () => 'test@example.com' } as Connection; ux = new Ux({ jsonEnabled: false }); - + // Stub methods humanReporterFormatStub = sandbox.stub(HumanReporter.prototype, 'format'); humanReporterFormatStub.returns('Mocked human report output'); - + sandbox.stub(ux, 'log'); - + testReporter = new TestReporter(ux, connection); }); afterEach(() => { sandbox.restore(); - + // Clean up any test directories try { fs.rmSync('test-output-dir', { recursive: true }); @@ -65,19 +65,19 @@ describe('TestReporter - isUnifiedLogic parameter', () => { 'code-coverage': false, 'detailed-coverage': false, concise: false, - isUnifiedLogic: true + isUnifiedLogic: true, }; await testReporter.report(testRunSimple, options); expect(humanReporterFormatStub.calledOnce).to.be.true; const formatArgs = humanReporterFormatStub.getCall(0).args; - + // Verify the parameters: format(result, detailedCoverage, concise, isUnifiedLogic) expect(formatArgs[0]).to.equal(testRunSimple); expect(formatArgs[1]).to.be.false; // detailedCoverage expect(formatArgs[2]).to.be.false; // concise - expect(formatArgs[3]).to.be.true; // isUnifiedLogic + expect(formatArgs[3]).to.be.true; // isUnifiedLogic }); it('should pass isUnifiedLogic=undefined to HumanReporter when not specified', async () => { @@ -85,7 +85,7 @@ describe('TestReporter - isUnifiedLogic parameter', () => { 'result-format': 'human', 'code-coverage': false, 'detailed-coverage': false, - concise: false + concise: false, // isUnifiedLogic not specified }; @@ -93,7 +93,7 @@ describe('TestReporter - isUnifiedLogic parameter', () => { expect(humanReporterFormatStub.calledOnce).to.be.true; const formatArgs = humanReporterFormatStub.getCall(0).args; - + expect(formatArgs[3]).to.be.undefined; // isUnifiedLogic should be undefined }); @@ -103,14 +103,14 @@ describe('TestReporter - isUnifiedLogic parameter', () => { 'code-coverage': false, 'detailed-coverage': false, concise: false, - isUnifiedLogic: false + isUnifiedLogic: false, }; await testReporter.report(testRunSimple, options); expect(humanReporterFormatStub.calledOnce).to.be.true; const formatArgs = humanReporterFormatStub.getCall(0).args; - + expect(formatArgs[3]).to.be.false; // isUnifiedLogic should be false }); }); @@ -123,26 +123,26 @@ describe('TestReporter - isUnifiedLogic parameter', () => { 'code-coverage': false, 'detailed-coverage': true, concise: false, - isUnifiedLogic: true + isUnifiedLogic: true, }; await testReporter.report(testRunSimple, options); // HumanReporter should be called twice: once for file output, once for console output expect(humanReporterFormatStub.calledTwice).to.be.true; - + // Check the first call (for file output via buildOutputDirConfig) const firstCallArgs = humanReporterFormatStub.getCall(0).args; - + // Check the second call (for console output via logHuman) const secondCallArgs = humanReporterFormatStub.getCall(1).args; - + // Both calls should have isUnifiedLogic=true - expect(firstCallArgs[3]).to.be.true; // isUnifiedLogic in first call + expect(firstCallArgs[3]).to.be.true; // isUnifiedLogic in first call expect(secondCallArgs[3]).to.be.true; // isUnifiedLogic in second call - + // Verify other parameters in first call - expect(firstCallArgs[1]).to.be.true; // detailedCoverage + expect(firstCallArgs[1]).to.be.true; // detailedCoverage expect(firstCallArgs[2]).to.be.false; // concise }); @@ -156,7 +156,7 @@ describe('TestReporter - isUnifiedLogic parameter', () => { 'code-coverage': false, 'detailed-coverage': false, concise: false, - isUnifiedLogic: true + isUnifiedLogic: true, }; await testReporter.report(testRunSimple, options); @@ -164,7 +164,7 @@ describe('TestReporter - isUnifiedLogic parameter', () => { // Verify directory and file were created expect(fs.existsSync('test-output-dir')).to.be.true; expect(fs.existsSync('test-output-dir/test-result.txt')).to.be.true; - + // Verify file content const fileContent = fs.readFileSync('test-output-dir/test-result.txt', 'utf8'); expect(fileContent).to.equal(expectedOutput); @@ -177,7 +177,7 @@ describe('TestReporter - isUnifiedLogic parameter', () => { 'result-format': 'human', 'code-coverage': true, 'detailed-coverage': false, - concise: true + concise: true, // No isUnifiedLogic specified - should work as before }; @@ -185,7 +185,7 @@ describe('TestReporter - isUnifiedLogic parameter', () => { expect(humanReporterFormatStub.calledOnce).to.be.true; const formatArgs = humanReporterFormatStub.getCall(0).args; - + expect(formatArgs[3]).to.be.undefined; // isUnifiedLogic should be undefined }); }); diff --git a/test/testData.ts b/test/testData.ts index 04492e00..d3d97523 100644 --- a/test/testData.ts +++ b/test/testData.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -260,7 +260,7 @@ export const logicTestRunSimple: TestResult = { runTime: 53, testTimestamp: '2020-08-25T00:48:02.000+0000', fullName: 'MyApexTests.testConfig', - category: TestCategory.Apex + category: TestCategory.Apex, }, ], }; diff --git a/test/utils.test.ts b/test/utils.test.ts index b3ca8f29..42ad1f69 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2025, Salesforce, Inc. + * Copyright 2026, Salesforce, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 440c4852a3d4de4c61fc097ed34657bec157e870 Mon Sep 17 00:00:00 2001 From: Steve Hetzel Date: Tue, 10 Feb 2026 13:27:59 -0700 Subject: [PATCH 2/2] fix: enable PDP events via o11y for PFT --- package.json | 2 ++ test/commands/logic/testHelper.ts | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4dc099bb..c94f26be 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,8 @@ "version": "3.9.5", "author": "Salesforce", "bugs": "https://github.com/forcedotcom/cli/issues", + "enableO11y": true, + "o11yUploadEndpoint": "https://794testsite.my.site.com/byolwr/webruntime/log/metrics", "dependencies": { "@salesforce/apex-node": "^8.4.2", "@salesforce/core": "^8.24.0", diff --git a/test/commands/logic/testHelper.ts b/test/commands/logic/testHelper.ts index b32387a1..79c441a5 100644 --- a/test/commands/logic/testHelper.ts +++ b/test/commands/logic/testHelper.ts @@ -80,8 +80,7 @@ export async function setupUnifiedFrameworkProject(): Promise { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const sfdxProject = JSON.parse(fs.readFileSync(sfdxProjectPath, 'utf8')); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument - sfdxProject.sourceApiVersion = - parseInt(sfdxProject.sourceApiVersion, 10) < 65 ? '65.0' : sfdxProject.sourceApiVersion; + sfdxProject.sourceApiVersion = parseInt(sfdxProject.sourceApiVersion, 10) < 65 ? '65.0' : sfdxProject.sourceApiVersion; fs.writeFileSync(sfdxProjectPath, JSON.stringify(sfdxProject, null, 2)); execCmd('project:deploy:start --source-dir force-app', { ensureExitCode: 0, cli: 'sf' });