@salesforce/apex-node
Advanced tools
Comparing version 7.0.4 to 8.1.0
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import { ApexDiagnostic, CommonOptions } from '../utils'; | ||
@@ -3,0 +2,0 @@ export type ApexExecuteOptions = CommonOptions & { |
@@ -26,3 +26,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.encodeBody = void 0; | ||
exports.encodeBody = encodeBody; | ||
/* | ||
@@ -48,3 +48,2 @@ * Copyright (c) 2020, salesforce.com, inc. | ||
} | ||
exports.encodeBody = encodeBody; | ||
//# sourceMappingURL=utils.js.map |
@@ -39,3 +39,5 @@ /** | ||
testStartTime: string; | ||
testSetupTime: string; | ||
testExecutionTime: string; | ||
testTotalTime: string; | ||
testRunId: string; | ||
@@ -49,6 +51,9 @@ userId: string; | ||
testNameColHeader: string; | ||
testSetupMethodNameColHeader: string; | ||
outcomeColHeader: string; | ||
msgColHeader: string; | ||
runtimeColHeader: string; | ||
setupTimeColHeader: string; | ||
testResultsHeader: string; | ||
testSetupResultsHeader: string; | ||
classesColHeader: string; | ||
@@ -55,0 +60,0 @@ percentColHeader: string; |
@@ -48,3 +48,5 @@ "use strict"; | ||
testStartTime: 'Test Start Time', | ||
testSetupTime: 'Test Setup Time', | ||
testExecutionTime: 'Test Execution Time', | ||
testTotalTime: 'Test Total Time', | ||
testRunId: 'Test Run Id', | ||
@@ -58,6 +60,9 @@ userId: 'User Id', | ||
testNameColHeader: 'TEST NAME', | ||
testSetupMethodNameColHeader: 'TEST SETUP METHOD NAME', | ||
outcomeColHeader: 'OUTCOME', | ||
msgColHeader: 'MESSAGE', | ||
runtimeColHeader: 'RUNTIME (MS)', | ||
setupTimeColHeader: 'SETUP TIME', | ||
testResultsHeader: 'Test Results', | ||
testSetupResultsHeader: 'Test Setup Time by Test Class for Run runId', | ||
classesColHeader: 'CLASSES', | ||
@@ -64,0 +69,0 @@ percentColHeader: 'PERCENT', |
@@ -5,3 +5,3 @@ export { CancellationToken, CancellationTokenSource, Progress } from './common'; | ||
export { JUnitReporter, JUnitFormatTransformer, TapReporter, TapFormatTransformer, HumanReporter, CoverageReporterOptions, CoverageReporter, CoverageReportFormats, DefaultReportOptions, DefaultWatermarks } from './reporters'; | ||
export { ApexCodeCoverageAggregate, ApexCodeCoverageAggregateRecord, ApexTestProgressValue, ApexTestResultData, ApexTestResultOutcome, ApexTestRunResultStatus, AsyncTestArrayConfiguration, AsyncTestConfiguration, CodeCoverageResult, OutputDirConfig, ResultFormat, SyncTestConfiguration, TestItem, TestLevel, TestResult, TestService, TestRunIdResult } from './tests'; | ||
export { ApexCodeCoverageAggregate, ApexCodeCoverageAggregateRecord, ApexTestProgressValue, ApexTestResultData, ApexTestResultOutcome, ApexTestRunResultStatus, ApexTestSetupData, AsyncTestArrayConfiguration, AsyncTestConfiguration, CodeCoverageResult, OutputDirConfig, ResultFormat, SyncTestConfiguration, TestItem, TestLevel, TestResult, TestService, TestRunIdResult } from './tests'; | ||
export { ApexDiagnostic, Row, Table } from './utils'; |
@@ -131,3 +131,3 @@ "use strict"; | ||
async logCallback(message) { | ||
if (message.sobject && message.sobject.Id) { | ||
if (message.sobject?.Id) { | ||
const log = await this.getLogById(message.sobject.Id); | ||
@@ -134,0 +134,0 @@ if (log && this.logTailer) { |
@@ -26,3 +26,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isValidApexClassID = exports.isValidTestRunID = exports.isNotQuotable = exports.isEmpty = exports.isTableConfig = exports.isTitle = exports.isColumn = exports.isRow = exports.isPrimitive = exports.isNull = exports.isArray = exports.isObject = exports.isNumber = exports.isBoolean = exports.isString = exports.isTestResult = void 0; | ||
exports.isNotQuotable = exports.isEmpty = exports.isTableConfig = exports.isTitle = exports.isColumn = exports.isRow = exports.isPrimitive = exports.isNull = exports.isArray = exports.isObject = exports.isNumber = exports.isBoolean = exports.isString = exports.isTestResult = void 0; | ||
exports.isValidTestRunID = isValidTestRunID; | ||
exports.isValidApexClassID = isValidApexClassID; | ||
const constants_1 = require("../tests/constants"); | ||
@@ -100,3 +102,2 @@ const tsTypes = __importStar(require("@salesforce/ts-types")); | ||
} | ||
exports.isValidTestRunID = isValidTestRunID; | ||
function isValidApexClassID(apexClassId) { | ||
@@ -106,3 +107,2 @@ return ((apexClassId.length === 15 || apexClassId.length === 18) && | ||
} | ||
exports.isValidApexClassID = isValidApexClassID; | ||
//# sourceMappingURL=narrowing.js.map |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import { TestResult } from '../tests'; | ||
@@ -14,2 +13,3 @@ import { Readable, ReadableOptions } from 'node:stream'; | ||
private formatTestResults; | ||
private formatSetup; | ||
private formatDetailedCov; | ||
@@ -16,0 +16,0 @@ private formatCodeCov; |
@@ -60,2 +60,5 @@ "use strict"; | ||
} | ||
if (this.testResult.setup && !this.concise) { | ||
this.formatSetup(); | ||
} | ||
this.formatSummary(); | ||
@@ -92,2 +95,6 @@ } | ||
{ | ||
name: i18n_1.nls.localize('testSetupTime'), | ||
value: `${this.testResult.summary.testSetupTimeInMs || 0} ms` | ||
}, | ||
{ | ||
name: i18n_1.nls.localize('testExecutionTime'), | ||
@@ -97,2 +104,6 @@ value: `${this.testResult.summary.testExecutionTimeInMs} ms` | ||
{ | ||
name: i18n_1.nls.localize('testTotalTime'), | ||
value: `${this.testResult.summary.testTotalTimeInMs} ms` | ||
}, | ||
{ | ||
name: i18n_1.nls.localize('orgId'), | ||
@@ -156,2 +167,25 @@ value: this.testResult.summary.orgId | ||
} | ||
formatSetup() { | ||
const tb = new tableWritableStream_1.TableWriteableStream(this); | ||
const testRowArray = []; | ||
this.testResult.setup.forEach((elem) => { | ||
testRowArray.push({ | ||
name: elem.fullName, | ||
time: `${elem.testSetupTime}`, | ||
runId: this.testResult.summary.testRunId | ||
}); | ||
}); | ||
if (testRowArray.length > 0) { | ||
this.push('\n\n'); | ||
tb.createTable(testRowArray, [ | ||
{ | ||
key: 'name', | ||
label: i18n_1.nls.localize('testSetupMethodNameColHeader') | ||
}, | ||
{ key: 'time', label: i18n_1.nls.localize('setupTimeColHeader') } | ||
], i18n_1.nls | ||
.localize('testSetupResultsHeader') | ||
.replace('runId', testRowArray[0].runId)); | ||
} | ||
} | ||
formatDetailedCov() { | ||
@@ -268,2 +302,5 @@ const tb = new tableWritableStream_1.TableWriteableStream(this); | ||
(0, utils_1.elapsedTime)() | ||
], HumanFormatTransform.prototype, "formatSetup", null); | ||
__decorate([ | ||
(0, utils_1.elapsedTime)() | ||
], HumanFormatTransform.prototype, "formatDetailedCov", null); | ||
@@ -270,0 +307,0 @@ __decorate([ |
@@ -6,2 +6,3 @@ import { TestResult } from '../tests'; | ||
private formatTestResults; | ||
private formatSetup; | ||
private formatDetailedCov; | ||
@@ -8,0 +9,0 @@ private formatCodeCov; |
@@ -59,2 +59,5 @@ "use strict"; | ||
} | ||
if (testResult.setup && !concise) { | ||
tbResult += this.formatSetup(testResult); | ||
} | ||
tbResult += this.formatSummary(testResult); | ||
@@ -96,2 +99,6 @@ return tbResult; | ||
{ | ||
name: i18n_1.nls.localize('testSetupTime'), | ||
value: `${testResult.summary.testSetupTimeInMs || 0} ms` | ||
}, | ||
{ | ||
name: i18n_1.nls.localize('testExecutionTime'), | ||
@@ -101,2 +108,6 @@ value: `${testResult.summary.testExecutionTimeInMs} ms` | ||
{ | ||
name: i18n_1.nls.localize('testTotalTime'), | ||
value: `${testResult.summary.testTotalTimeInMs} ms` | ||
}, | ||
{ | ||
name: i18n_1.nls.localize('orgId'), | ||
@@ -162,2 +173,27 @@ value: testResult.summary.orgId | ||
} | ||
formatSetup(testResult) { | ||
const tb = new utils_1.Table(); | ||
const testRowArray = []; | ||
testResult.setup.forEach((elem) => { | ||
testRowArray.push({ | ||
name: elem.fullName, | ||
time: `${elem.testSetupTime}`, | ||
runId: testResult.summary.testRunId | ||
}); | ||
}); | ||
let testResultTable = ''; | ||
if (testRowArray.length > 0) { | ||
testResultTable = os.EOL.repeat(2); | ||
testResultTable += tb.createTable(testRowArray, [ | ||
{ | ||
key: 'name', | ||
label: i18n_1.nls.localize('testSetupMethodNameColHeader') | ||
}, | ||
{ key: 'time', label: i18n_1.nls.localize('setupTimeColHeader') } | ||
], i18n_1.nls | ||
.localize('testSetupResultsHeader') | ||
.replace('runId', testRowArray[0].runId)); | ||
} | ||
return testResultTable; | ||
} | ||
formatDetailedCov(testResult, concise) { | ||
@@ -275,2 +311,5 @@ const tb = new utils_1.Table(); | ||
(0, utils_1.elapsedTime)() | ||
], HumanReporter.prototype, "formatSetup", null); | ||
__decorate([ | ||
(0, utils_1.elapsedTime)() | ||
], HumanReporter.prototype, "formatDetailedCov", null); | ||
@@ -277,0 +316,0 @@ __decorate([ |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import { TestResult } from '../tests'; | ||
@@ -3,0 +2,0 @@ import { Readable, ReadableOptions } from 'node:stream'; |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import { Readable, ReadableOptions } from 'node:stream'; | ||
@@ -3,0 +2,0 @@ import { TestResult } from '../tests'; |
@@ -100,3 +100,3 @@ "use strict"; | ||
testResult.message.split(/\r\n|\r|\n/g).forEach((msg) => { | ||
if (msg && msg.length > 0) { | ||
if (msg?.length > 0) { | ||
message.push(msg.trim()); | ||
@@ -103,0 +103,0 @@ } |
@@ -79,3 +79,3 @@ "use strict"; | ||
testResult.message.split(/\r\n|\r|\n/g).forEach((msg) => { | ||
if (msg && msg.length > 0) { | ||
if (msg?.length > 0) { | ||
message.push(msg.trim()); | ||
@@ -82,0 +82,0 @@ } |
@@ -77,3 +77,3 @@ "use strict"; | ||
incoming: async (message, callback) => { | ||
if (message && message.error) { | ||
if (message?.error) { | ||
// throw errors on handshake errors | ||
@@ -80,0 +80,0 @@ if (message.channel === '/meta/handshake') { |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import { Readable, ReadableOptions } from 'node:stream'; | ||
@@ -3,0 +2,0 @@ import { TestResult } from '../tests'; |
@@ -53,9 +53,13 @@ import { Connection } from '@salesforce/core'; | ||
/** | ||
* Checks if the specified sObject contains the given field. | ||
* @param sObjectName - The name of the sObject. | ||
* @param fieldName - The name of the field to check. | ||
* @returns A boolean indicating if the field exists in the sObject. | ||
* @returns A boolean indicating if the org's api version supports the test setup feature. | ||
*/ | ||
describeSObjects(sObjectName: string, fieldName: string): Promise<boolean>; | ||
private transformTestResult; | ||
supportsTestSetupFeature(): Promise<boolean>; | ||
/** | ||
* @returns A connection based on the current api version and the max api version. | ||
*/ | ||
defineApiVersion(): Promise<Connection>; | ||
/** | ||
* @returns A new connection similar to the current one but with a new api version. | ||
*/ | ||
cloneConnectionWithNewVersion(newVersion: string): Promise<Connection>; | ||
} |
@@ -66,2 +66,3 @@ "use strict"; | ||
]; | ||
const MIN_VERSION_TO_SUPPORT_TEST_SETUP_METHODS = 61.0; | ||
class AsyncTests { | ||
@@ -91,8 +92,7 @@ connection; | ||
await sClient.handshake(); | ||
token && | ||
token.onCancellationRequested(async () => { | ||
const testRunId = await sClient.subscribedTestRunIdPromise; | ||
await this.abortTestRun(testRunId, progress); | ||
sClient.disconnect(); | ||
}); | ||
token?.onCancellationRequested(async () => { | ||
const testRunId = await sClient.subscribedTestRunIdPromise; | ||
await this.abortTestRun(testRunId, progress); | ||
sClient.disconnect(); | ||
}); | ||
const testRunId = await this.getTestRunRequestAction(options)(); | ||
@@ -102,3 +102,3 @@ if (exitOnTestRunId) { | ||
} | ||
if (token && token.isCancellationRequested) { | ||
if (token?.isCancellationRequested) { | ||
return null; | ||
@@ -130,3 +130,3 @@ } | ||
const writeStream = (0, node_fs_1.createWriteStream)(path_1.default.join(os.tmpdir(), runId, 'rawResults.json')); | ||
this.logger.debug(`Raw raw results written to: ${writeStream.path}`); | ||
this.logger.debug(`Raw results written to: ${writeStream.path}`); | ||
const stringifyStream = bfj.stringify(formattedResults, { | ||
@@ -165,7 +165,6 @@ bufferLength: (0, utils_2.getBufferSize)(), | ||
} | ||
token && | ||
token.onCancellationRequested(async () => { | ||
sClient.disconnect(); | ||
}); | ||
if (token && token.isCancellationRequested) { | ||
token?.onCancellationRequested(async () => { | ||
sClient.disconnect(); | ||
}); | ||
if (token?.isCancellationRequested) { | ||
return null; | ||
@@ -188,3 +187,3 @@ } | ||
} | ||
const hasTestSetupTimeField = await this.describeSObjects('ApexTestRunResult', 'TestSetupTime'); | ||
const hasTestSetupTimeField = await this.supportsTestSetupFeature(); | ||
const testRunSummaryQuery = hasTestSetupTimeField | ||
@@ -199,3 +198,3 @@ ? `SELECT AsyncApexJobId, Status, ClassesCompleted, ClassesEnqueued, MethodsEnqueued, StartTime, EndTime, TestTime, TestSetupTime, UserId FROM ApexTestRunResult WHERE AsyncApexJobId = '${testRunId}'` | ||
try { | ||
const testRunSummaryResults = await this.connection.singleRecordQuery(testRunSummaryQuery, { | ||
const testRunSummaryResults = await (await this.defineApiVersion()).singleRecordQuery(testRunSummaryQuery, { | ||
tooling: true | ||
@@ -224,3 +223,2 @@ }); | ||
try { | ||
const coveredApexClassIdSet = new Set(); | ||
const apexTestResults = await this.getAsyncTestResults(asyncRunResult.queueItem); | ||
@@ -238,4 +236,3 @@ const { apexTestClassIdSet, testResults, globalTests } = await this.buildAsyncTestResults(apexTestResults); | ||
} | ||
// TODO: deprecate testTotalTime | ||
const result = { | ||
const rawResult = { | ||
summary: { | ||
@@ -251,2 +248,3 @@ outcome, | ||
testStartTime: (0, utils_1.formatStartTime)(testRunSummary.StartTime, 'ISO'), | ||
testSetupTimeInMs: testRunSummary.TestSetupTime, | ||
testExecutionTimeInMs: testRunSummary.TestTime ?? 0, | ||
@@ -263,27 +261,4 @@ testTotalTimeInMs: testRunSummary.TestTime ?? 0, | ||
}; | ||
if (codeCoverage) { | ||
const perClassCovMap = await this.codecoverage.getPerClassCodeCoverage(apexTestClassIdSet); | ||
result.tests.forEach((item) => { | ||
const keyCodeCov = `${item.apexClass.id}-${item.methodName}`; | ||
const perClassCov = perClassCovMap.get(keyCodeCov); | ||
// Skipped test is not in coverage map, check to see if perClassCov exists first | ||
if (perClassCov) { | ||
perClassCov.forEach((classCov) => coveredApexClassIdSet.add(classCov.apexClassOrTriggerId)); | ||
item.perClassCoverage = perClassCov; | ||
} | ||
}); | ||
progress?.report({ | ||
type: 'FormatTestResultProgress', | ||
value: 'queryingForAggregateCodeCoverage', | ||
message: i18n_1.nls.localize('queryingForAggregateCodeCoverage') | ||
}); | ||
const { codeCoverageResults, totalLines, coveredLines } = await this.codecoverage.getAggregateCodeCoverage(coveredApexClassIdSet); | ||
result.codecoverage = codeCoverageResults; | ||
result.summary.totalLines = totalLines; | ||
result.summary.coveredLines = coveredLines; | ||
result.summary.testRunCoverage = (0, utils_2.calculatePercentage)(coveredLines, totalLines); | ||
result.summary.orgWideCoverage = | ||
await this.codecoverage.getOrgWideCoverage(); | ||
} | ||
return this.transformTestResult(result); | ||
await (0, utils_2.calculateCodeCoverage)(this.codecoverage, codeCoverage, apexTestClassIdSet, rawResult, true, progress); | ||
return (0, utils_2.transformTestResult)(rawResult); | ||
} | ||
@@ -296,3 +271,3 @@ finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.getAsyncTestResults'); | ||
const hasIsTestSetupField = await this.describeSObjects('ApexTestResult', 'IsTestSetup'); | ||
const hasIsTestSetupField = await this.supportsTestSetupFeature(); | ||
try { | ||
@@ -312,4 +287,5 @@ const apexTestResultQuery = hasIsTestSetupField | ||
} | ||
const queryPromises = queries.map((query) => { | ||
return (0, utils_2.queryAll)(this.connection, query, true); | ||
const connection = await this.defineApiVersion(); | ||
const queryPromises = queries.map(async (query) => { | ||
return (0, utils_2.queryAll)(connection, query, true); | ||
}); | ||
@@ -361,2 +337,3 @@ const apexTestResults = await Promise.all(queryPromises); | ||
apexLogId: item.ApexLogId, | ||
isTestSetup: item.IsTestSetup, | ||
apexClass: { | ||
@@ -427,32 +404,46 @@ id: item.ApexClass.Id, | ||
/** | ||
* Checks if the specified sObject contains the given field. | ||
* @param sObjectName - The name of the sObject. | ||
* @param fieldName - The name of the field to check. | ||
* @returns A boolean indicating if the field exists in the sObject. | ||
* @returns A boolean indicating if the org's api version supports the test setup feature. | ||
*/ | ||
async describeSObjects(sObjectName, fieldName) { | ||
async supportsTestSetupFeature() { | ||
try { | ||
const describeResult = await this.connection.tooling.describe(sObjectName); | ||
return describeResult.fields.some((field) => field.name === fieldName); | ||
return (parseFloat(await this.connection.retrieveMaxApiVersion()) >= | ||
MIN_VERSION_TO_SUPPORT_TEST_SETUP_METHODS); | ||
} | ||
catch (e) { | ||
throw new Error(`Error describing ${sObjectName}: ${e.message}`); | ||
throw new Error(`Error retrieving max api version`); | ||
} | ||
} | ||
transformTestResult(rawResult) { | ||
// Destructure summary to omit testSetupTimeInMs | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const { testSetupTimeInMs, ...summary } = rawResult.summary; | ||
// Filter and transform tests array | ||
const tests = rawResult.tests | ||
.filter((test) => !test.isTestSetup) | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
.map(({ isTestSetup, ...rest }) => rest); | ||
// Return the transformed result | ||
return { | ||
summary, | ||
tests, | ||
codecoverage: rawResult.codecoverage | ||
}; | ||
/** | ||
* @returns A connection based on the current api version and the max api version. | ||
*/ | ||
async defineApiVersion() { | ||
const maxApiVersion = await this.connection.retrieveMaxApiVersion(); | ||
if (parseFloat(this.connection.getApiVersion()) < | ||
MIN_VERSION_TO_SUPPORT_TEST_SETUP_METHODS && | ||
this.supportsTestSetupFeature()) { | ||
return await this.cloneConnectionWithNewVersion(maxApiVersion); | ||
} | ||
return this.connection; | ||
} | ||
/** | ||
* @returns A new connection similar to the current one but with a new api version. | ||
*/ | ||
async cloneConnectionWithNewVersion(newVersion) { | ||
try { | ||
const authInfo = await core_1.AuthInfo.create({ | ||
username: this.connection.getUsername() | ||
}); | ||
const newConn = await core_1.Connection.create({ | ||
authInfo: authInfo, | ||
connectionOptions: { | ||
...this.connection.getConnectionOptions(), | ||
version: newVersion | ||
} | ||
}); | ||
return newConn; | ||
} | ||
catch (e) { | ||
throw new Error(`Error creating new connection with API version ${newVersion}: ${e.message}`); | ||
} | ||
} | ||
} | ||
@@ -459,0 +450,0 @@ exports.AsyncTests = AsyncTests; |
@@ -9,7 +9,9 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getAsyncDiagnostic = exports.getSyncDiagnostic = exports.formatTestErrors = void 0; | ||
exports.formatTestErrors = formatTestErrors; | ||
exports.getSyncDiagnostic = getSyncDiagnostic; | ||
exports.getAsyncDiagnostic = getAsyncDiagnostic; | ||
const i18n_1 = require("../i18n"); | ||
function formatTestErrors(error) { | ||
const matches = error.message?.match(/\bsObject type ["'](.*?)["'] is not supported\b/); | ||
if (matches && matches[0] && matches[1]) { | ||
if (matches?.[0] && matches?.[1]) { | ||
error.message = i18n_1.nls.localize('invalidsObjectErr', [ | ||
@@ -23,3 +25,2 @@ matches[1], | ||
} | ||
exports.formatTestErrors = formatTestErrors; | ||
function getSyncDiagnostic(syncRecord) { | ||
@@ -34,4 +35,3 @@ const diagnostic = { | ||
}; | ||
const matches = syncRecord.stackTrace && | ||
syncRecord.stackTrace.match(/(line (\d+), column (\d+))/); | ||
const matches = syncRecord.stackTrace?.match(/(line (\d+), column (\d+))/); | ||
if (matches) { | ||
@@ -47,3 +47,2 @@ if (matches[2]) { | ||
} | ||
exports.getSyncDiagnostic = getSyncDiagnostic; | ||
function getAsyncDiagnostic(asyncRecord) { | ||
@@ -58,4 +57,3 @@ const diagnostic = { | ||
}; | ||
const matches = asyncRecord.StackTrace && | ||
asyncRecord.StackTrace.match(/(line (\d+), column (\d+))/); | ||
const matches = asyncRecord.StackTrace?.match(/(line (\d+), column (\d+))/); | ||
if (matches) { | ||
@@ -71,3 +69,2 @@ if (matches[2]) { | ||
} | ||
exports.getAsyncDiagnostic = getAsyncDiagnostic; | ||
//# sourceMappingURL=diagnosticUtil.js.map |
export { TestService } from './testService'; | ||
export { ApexCodeCoverageAggregate, ApexCodeCoverageAggregateRecord, ApexTestProgressValue, ApexTestResultData, ApexTestResultDataRaw, ApexTestResultOutcome, ApexTestRunResultStatus, AsyncTestArrayConfiguration, AsyncTestConfiguration, CodeCoverageResult, OutputDirConfig, PerClassCoverage, ResultFormat, SyncTestConfiguration, TestItem, TestLevel, TestResult, TestResultRaw, TestRunIdResult } from './types'; | ||
export { ApexCodeCoverageAggregate, ApexCodeCoverageAggregateRecord, ApexTestProgressValue, ApexTestResultData, ApexTestResultDataRaw, ApexTestResultOutcome, ApexTestRunResultStatus, ApexTestSetupData, AsyncTestArrayConfiguration, AsyncTestConfiguration, CodeCoverageResult, OutputDirConfig, PerClassCoverage, ResultFormat, SyncTestConfiguration, TestItem, TestLevel, TestResult, TestResultRaw, TestRunIdResult } from './types'; |
@@ -17,2 +17,3 @@ import { Connection } from '@salesforce/core'; | ||
private buildSyncTestResults; | ||
private processTestResult; | ||
} |
@@ -44,3 +44,3 @@ "use strict"; | ||
const testRun = (await this.connection.tooling.request(request)); | ||
if (token && token.isCancellationRequested) { | ||
if (token?.isCancellationRequested) { | ||
return null; | ||
@@ -59,3 +59,2 @@ } | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('synctests.formatSyncResults'); | ||
const coveredApexClassIdSet = new Set(); | ||
const { apexTestClassIdSet, testResults } = this.buildSyncTestResults(apiTestResult); | ||
@@ -65,3 +64,3 @@ try { | ||
const globalTestPassed = apiTestResult.successes.length; | ||
const result = { | ||
const rawResult = { | ||
summary: { | ||
@@ -90,23 +89,4 @@ outcome: globalTestFailed === 0 | ||
}; | ||
if (codeCoverage) { | ||
const perClassCovMap = await this.codecoverage.getPerClassCodeCoverage(apexTestClassIdSet); | ||
if (perClassCovMap.size > 0) { | ||
result.tests.forEach((item) => { | ||
const keyCodeCov = `${item.apexClass.id}-${item.methodName}`; | ||
const perClassCov = perClassCovMap.get(keyCodeCov); | ||
if (perClassCov) { | ||
perClassCov.forEach((classCov) => coveredApexClassIdSet.add(classCov.apexClassOrTriggerId)); | ||
item.perClassCoverage = perClassCov; | ||
} | ||
}); | ||
} | ||
const { codeCoverageResults, totalLines, coveredLines } = await this.codecoverage.getAggregateCodeCoverage(coveredApexClassIdSet); | ||
result.codecoverage = codeCoverageResults; | ||
result.summary.totalLines = totalLines; | ||
result.summary.coveredLines = coveredLines; | ||
result.summary.testRunCoverage = (0, utils_2.calculatePercentage)(coveredLines, totalLines); | ||
result.summary.orgWideCoverage = | ||
await this.codecoverage.getOrgWideCoverage(); | ||
} | ||
return result; | ||
await (0, utils_2.calculateCodeCoverage)(this.codecoverage, codeCoverage, apexTestClassIdSet, rawResult, false); | ||
return (0, utils_2.transformTestResult)(rawResult); | ||
} | ||
@@ -120,51 +100,9 @@ finally { | ||
try { | ||
const apexTestClassIdSet = new Set(); | ||
const testResults = []; | ||
const apexTestClassIdSet = new Set(); | ||
apiTestResult.successes.forEach((item) => { | ||
const nms = item.namespace ? `${item.namespace}.` : ''; | ||
apexTestClassIdSet.add(item.id); | ||
testResults.push({ | ||
id: '', | ||
queueItemId: '', | ||
stackTrace: '', | ||
message: '', | ||
asyncApexJobId: '', | ||
methodName: item.methodName, | ||
outcome: "Pass" /* ApexTestResultOutcome.Pass */, | ||
apexLogId: apiTestResult.apexLogId, | ||
apexClass: { | ||
id: item.id, | ||
name: item.name, | ||
namespacePrefix: item.namespace, | ||
fullName: `${nms}${item.name}` | ||
}, | ||
runTime: item.time ?? 0, | ||
testTimestamp: '', | ||
fullName: `${nms}${item.name}.${item.methodName}` | ||
}); | ||
testResults.push(this.processTestResult(item, apiTestResult, apexTestClassIdSet, "Pass" /* ApexTestResultOutcome.Pass */)); | ||
}); | ||
apiTestResult.failures.forEach((item) => { | ||
const nms = item.namespace ? `${item.namespace}__` : ''; | ||
apexTestClassIdSet.add(item.id); | ||
const diagnostic = item.message || item.stackTrace ? (0, diagnosticUtil_1.getSyncDiagnostic)(item) : null; | ||
testResults.push({ | ||
id: '', | ||
queueItemId: '', | ||
stackTrace: item.stackTrace, | ||
message: item.message, | ||
asyncApexJobId: '', | ||
methodName: item.methodName, | ||
outcome: "Fail" /* ApexTestResultOutcome.Fail */, | ||
apexLogId: apiTestResult.apexLogId, | ||
apexClass: { | ||
id: item.id, | ||
name: item.name, | ||
namespacePrefix: item.namespace, | ||
fullName: `${nms}${item.name}` | ||
}, | ||
runTime: item.time ?? 0, | ||
testTimestamp: '', | ||
fullName: `${nms}${item.name}.${item.methodName}`, | ||
...(diagnostic ? { diagnostic } : {}) | ||
}); | ||
testResults.push(this.processTestResult(item, apiTestResult, apexTestClassIdSet, "Fail" /* ApexTestResultOutcome.Fail */)); | ||
}); | ||
@@ -177,2 +115,38 @@ return { apexTestClassIdSet, testResults }; | ||
} | ||
processTestResult(item, apiTestResult, apexTestClassIdSet, outcome) { | ||
const nms = item.namespace | ||
? outcome === 'Fail' | ||
? `${item.namespace}__` | ||
: `${item.namespace}.` | ||
: ''; | ||
apexTestClassIdSet.add(item.id); | ||
const testResult = { | ||
id: '', | ||
queueItemId: '', | ||
stackTrace: item.stackTrace || '', | ||
message: item.message || '', | ||
asyncApexJobId: '', | ||
methodName: item.methodName, | ||
outcome: outcome, | ||
apexLogId: apiTestResult.apexLogId, | ||
apexClass: { | ||
id: item.id, | ||
name: item.name, | ||
namespacePrefix: item.namespace, | ||
fullName: `${nms}${item.name}` | ||
}, | ||
runTime: item.time ?? 0, | ||
testTimestamp: '', | ||
fullName: `${nms}${item.name}.${item.methodName}` | ||
}; | ||
if (outcome === "Fail" /* ApexTestResultOutcome.Fail */) { | ||
const diagnostic = item.message || item.stackTrace | ||
? (0, diagnosticUtil_1.getSyncDiagnostic)(item) | ||
: null; | ||
if (diagnostic) { | ||
testResult.diagnostic = diagnostic; | ||
} | ||
} | ||
return testResult; | ||
} | ||
} | ||
@@ -179,0 +153,0 @@ exports.SyncTests = SyncTests; |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import { Connection } from '@salesforce/core'; | ||
@@ -3,0 +2,0 @@ import { ApexTestProgressValue, AsyncTestArrayConfiguration, AsyncTestConfiguration, OutputDirConfig, SyncTestConfiguration, TestLevel, TestResult, TestRunIdResult, TestSuiteMembershipRecord } from './types'; |
@@ -198,2 +198,6 @@ import { ApexDiagnostic } from '../utils'; | ||
ApexLogId: string | null; | ||
/** | ||
* Indicates if the results are for a test setup method. The default is false. | ||
*/ | ||
IsTestSetup?: boolean; | ||
ApexClass: { | ||
@@ -243,6 +247,18 @@ Id: string; | ||
/** | ||
* The status of the test run | ||
* The number of classes that have completed execution in the test run | ||
*/ | ||
Status: ApexTestRunResultStatus; | ||
ClassesCompleted: number; | ||
/** | ||
* The number of classes that have been enqueued for execution in the test run | ||
*/ | ||
ClassesEnqueued: number; | ||
/** | ||
* The time at which the test run ended. | ||
*/ | ||
EndTime: string | undefined; | ||
/** | ||
* The number of methods that have been enqueued for execution in the test run | ||
*/ | ||
MethodsEnqueued: number; | ||
/** | ||
* The time at which the test run started. | ||
@@ -252,2 +268,10 @@ */ | ||
/** | ||
* The status of the test run | ||
*/ | ||
Status: ApexTestRunResultStatus; | ||
/** | ||
* The time it took to set up the test, in seconds. | ||
*/ | ||
TestSetupTime: number | undefined; | ||
/** | ||
* The time it took the test to run, in seconds. | ||
@@ -356,2 +380,20 @@ */ | ||
}; | ||
export type ApexTestSetupData = { | ||
id: string; | ||
stackTrace: string | null; | ||
message: string | null; | ||
asyncApexJobId: string; | ||
methodName: string; | ||
apexLogId: string | null; | ||
apexClass: { | ||
id: string; | ||
name: string; | ||
namespacePrefix: string; | ||
fullName: string; | ||
}; | ||
testSetupTime: number; | ||
testTimestamp: string; | ||
fullName: string; | ||
diagnostic?: ApexDiagnostic; | ||
}; | ||
export type CodeCoverageResult = { | ||
@@ -371,4 +413,5 @@ apexId: string; | ||
export type TestResult = { | ||
summary: Omit<TestResultRaw['summary'], 'testSetupTimeInMs'>; | ||
tests: Omit<ApexTestResultDataRaw, 'isTestSetup'>[]; | ||
summary: TestResultRaw['summary']; | ||
tests: ApexTestResultData[]; | ||
setup?: ApexTestSetupData[]; | ||
codecoverage?: CodeCoverageResult[]; | ||
@@ -375,0 +418,0 @@ }; |
import { Connection } from '@salesforce/core'; | ||
import { NamespaceInfo } from './types'; | ||
import { ApexTestProgressValue, NamespaceInfo, TestResult, TestResultRaw } from './types'; | ||
import type { QueryResult } from '@jsforce/jsforce-node'; | ||
import { Progress } from '../common'; | ||
import { CodeCoverage } from './codeCoverage'; | ||
export declare function calculatePercentage(dividend: number, divisor: number): string; | ||
@@ -11,1 +13,3 @@ export declare function stringify(jsonObj: object): string; | ||
export declare const resetLimitsForTesting: () => void; | ||
export declare const transformTestResult: (rawResult: TestResultRaw) => TestResult; | ||
export declare const calculateCodeCoverage: (codeCoverageInstance: CodeCoverage, codeCoverage: boolean, apexTestClassIdSet: Set<string>, result: TestResultRaw, isAsync: boolean, progress?: Progress<ApexTestProgressValue>) => Promise<void>; |
@@ -9,4 +9,8 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.resetLimitsForTesting = exports.getBufferSize = exports.getJsonIndent = exports.queryAll = exports.queryNamespaces = exports.stringify = exports.calculatePercentage = void 0; | ||
exports.calculateCodeCoverage = exports.transformTestResult = exports.resetLimitsForTesting = exports.getBufferSize = exports.getJsonIndent = exports.queryAll = void 0; | ||
exports.calculatePercentage = calculatePercentage; | ||
exports.stringify = stringify; | ||
exports.queryNamespaces = queryNamespaces; | ||
const core_1 = require("@salesforce/core"); | ||
const i18n_1 = require("../i18n"); | ||
const DEFAULT_BUFFER_SIZE = 256; | ||
@@ -28,7 +32,5 @@ const MIN_BUFFER_SIZE = 256; | ||
} | ||
exports.calculatePercentage = calculatePercentage; | ||
function stringify(jsonObj) { | ||
return JSON.stringify(jsonObj, null, 2); | ||
} | ||
exports.stringify = stringify; | ||
async function queryNamespaces(connection) { | ||
@@ -48,3 +50,2 @@ const installedNsQuery = 'SELECT NamespacePrefix FROM PackageLicense'; | ||
} | ||
exports.queryNamespaces = queryNamespaces; | ||
const queryAll = async (connection, query, tooling = false) => { | ||
@@ -109,2 +110,77 @@ const conn = tooling ? connection.tooling : connection; | ||
exports.resetLimitsForTesting = resetLimitsForTesting; | ||
const transformTestResult = (rawResult) => { | ||
// Initialize arrays for setup methods and regular tests | ||
const regularTests = []; | ||
const setupMethods = []; | ||
// Iterate through each item in rawResult.tests | ||
rawResult.tests.forEach((test) => { | ||
const { isTestSetup, ...rest } = test; | ||
if (isTestSetup) { | ||
setupMethods.push(transformToApexTestSetupData(rest)); | ||
} | ||
else { | ||
regularTests.push(rest); | ||
} | ||
}); | ||
return { | ||
summary: { | ||
...rawResult.summary, | ||
testSetupTimeInMs: rawResult.summary.testSetupTimeInMs, | ||
testTotalTimeInMs: (rawResult.summary.testSetupTimeInMs || 0) + | ||
rawResult.summary.testExecutionTimeInMs | ||
}, | ||
tests: regularTests, | ||
setup: setupMethods, | ||
codecoverage: rawResult.codecoverage | ||
}; | ||
}; | ||
exports.transformTestResult = transformTestResult; | ||
const calculateCodeCoverage = async (codeCoverageInstance, codeCoverage, apexTestClassIdSet, result, isAsync, progress) => { | ||
const coveredApexClassIdSet = new Set(); | ||
if (codeCoverage) { | ||
const perClassCovMap = await codeCoverageInstance.getPerClassCodeCoverage(apexTestClassIdSet); | ||
if (perClassCovMap.size > 0) { | ||
result.tests.forEach((item) => { | ||
const keyCodeCov = `${item.apexClass.id}-${item.methodName}`; | ||
const perClassCov = perClassCovMap.get(keyCodeCov); | ||
// Skipped test is not in coverage map, check to see if perClassCov exists first | ||
if (perClassCov) { | ||
perClassCov.forEach((classCov) => coveredApexClassIdSet.add(classCov.apexClassOrTriggerId)); | ||
item.perClassCoverage = perClassCov; | ||
} | ||
}); | ||
} | ||
if (isAsync) { | ||
progress?.report({ | ||
type: 'FormatTestResultProgress', | ||
value: 'queryingForAggregateCodeCoverage', | ||
message: i18n_1.nls.localize('queryingForAggregateCodeCoverage') | ||
}); | ||
} | ||
const { codeCoverageResults, totalLines, coveredLines } = await codeCoverageInstance.getAggregateCodeCoverage(coveredApexClassIdSet); | ||
result.codecoverage = codeCoverageResults; | ||
result.summary.totalLines = totalLines; | ||
result.summary.coveredLines = coveredLines; | ||
result.summary.testRunCoverage = calculatePercentage(coveredLines, totalLines); | ||
result.summary.orgWideCoverage = | ||
await codeCoverageInstance.getOrgWideCoverage(); | ||
} | ||
}; | ||
exports.calculateCodeCoverage = calculateCodeCoverage; | ||
const transformToApexTestSetupData = (testData) => { | ||
// Assuming all necessary properties are present and optional properties are handled | ||
return { | ||
id: testData.id, | ||
stackTrace: testData.stackTrace ?? null, | ||
message: testData.message ?? null, | ||
asyncApexJobId: testData.asyncApexJobId, | ||
methodName: testData.methodName, | ||
apexLogId: testData.apexLogId ?? null, | ||
apexClass: testData.apexClass, | ||
testSetupTime: testData.runTime, | ||
testTimestamp: testData.testTimestamp, | ||
fullName: testData.fullName, | ||
diagnostic: testData.diagnostic | ||
}; | ||
}; | ||
//# sourceMappingURL=utils.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.escapeXml = exports.refreshAuth = void 0; | ||
exports.refreshAuth = refreshAuth; | ||
exports.escapeXml = escapeXml; | ||
const types_1 = require("./types"); | ||
@@ -9,3 +10,2 @@ async function refreshAuth(connection) { | ||
} | ||
exports.refreshAuth = refreshAuth; | ||
function escapeXml(data) { | ||
@@ -16,3 +16,2 @@ return data.replace(/[<>&'"]/g, (char) => { | ||
} | ||
exports.escapeXml = escapeXml; | ||
//# sourceMappingURL=authUtil.js.map |
@@ -9,3 +9,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.msToSecond = exports.formatStartTime = exports.getCurrentTime = exports.MILLISECONDS_PER_MINUTE = void 0; | ||
exports.MILLISECONDS_PER_MINUTE = void 0; | ||
exports.getCurrentTime = getCurrentTime; | ||
exports.formatStartTime = formatStartTime; | ||
exports.msToSecond = msToSecond; | ||
exports.MILLISECONDS_PER_MINUTE = 60000; | ||
@@ -15,3 +18,2 @@ function getCurrentTime() { | ||
} | ||
exports.getCurrentTime = getCurrentTime; | ||
/** | ||
@@ -33,7 +35,5 @@ * Returns the formatted date and time given the milliseconds in numbers or UTC formatted string | ||
} | ||
exports.formatStartTime = formatStartTime; | ||
function msToSecond(timestamp) { | ||
return (timestamp / 1000).toFixed(2); | ||
} | ||
exports.msToSecond = msToSecond; | ||
//# sourceMappingURL=dateUtil.js.map |
@@ -9,3 +9,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.elapsedTime = void 0; | ||
exports.elapsedTime = elapsedTime; | ||
/* eslint-disable @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-return */ | ||
@@ -92,3 +92,2 @@ const core_1 = require("@salesforce/core"); | ||
} | ||
exports.elapsedTime = elapsedTime; | ||
//# sourceMappingURL=elapsedTime.js.map |
@@ -32,3 +32,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createFiles = exports.createFile = exports.ensureFileExists = exports.ensureDirectoryExists = void 0; | ||
exports.ensureDirectoryExists = ensureDirectoryExists; | ||
exports.ensureFileExists = ensureFileExists; | ||
exports.createFile = createFile; | ||
exports.createFiles = createFiles; | ||
const fs = __importStar(require("fs")); | ||
@@ -43,3 +46,2 @@ const path = __importStar(require("path")); | ||
} | ||
exports.ensureDirectoryExists = ensureDirectoryExists; | ||
function ensureFileExists(filePath) { | ||
@@ -49,3 +51,2 @@ ensureDirectoryExists(path.dirname(filePath)); | ||
} | ||
exports.ensureFileExists = ensureFileExists; | ||
/** | ||
@@ -62,3 +63,2 @@ * Method to save a file on disk. | ||
} | ||
exports.createFile = createFile; | ||
function streamPromise(stream) { | ||
@@ -87,3 +87,2 @@ return new Promise((resolve, reject) => { | ||
} | ||
exports.createFiles = createFiles; | ||
//# sourceMappingURL=fileSystemHandler.js.map |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
export declare class NullHeapMonitor implements Disposable { | ||
@@ -3,0 +2,0 @@ checkHeapSize(): void; |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import { Readable } from 'node:stream'; | ||
@@ -3,0 +2,0 @@ export interface Row { |
{ | ||
"name": "@salesforce/apex-node", | ||
"description": "Salesforce JS library for Apex", | ||
"version": "7.0.4", | ||
"version": "8.1.0", | ||
"author": "Salesforce", | ||
@@ -9,4 +9,4 @@ "bugs": "https://github.com/forcedotcom/salesforcedx-apex/issues", | ||
"dependencies": { | ||
"@jsforce/jsforce-node": "^3.2.2", | ||
"@salesforce/core": "^8.1.1", | ||
"@jsforce/jsforce-node": "^3.2.3", | ||
"@salesforce/core": "^8.2.0", | ||
"@salesforce/kit": "^3.1.6", | ||
@@ -33,4 +33,4 @@ "@types/istanbul-reports": "^3.0.4", | ||
"@typescript-eslint/eslint-plugin": "^6.21.0", | ||
"@typescript-eslint/parser": "^6.10.0", | ||
"chai": "^4.3.10", | ||
"@typescript-eslint/parser": "^6.21.0", | ||
"chai": "^4.4.1", | ||
"commitlint": "^18.6.1", | ||
@@ -48,3 +48,3 @@ "cz-conventional-changelog": "^3.3.0", | ||
"nyc": "^15.1.0", | ||
"prettier": "^3.2.5", | ||
"prettier": "^3.3.2", | ||
"shx": "^0.3.4", | ||
@@ -54,3 +54,3 @@ "sinon": "^17.0.1", | ||
"ts-node": "^10.9.2", | ||
"typescript": "^5.4.5" | ||
"typescript": "^5.5.3" | ||
}, | ||
@@ -57,0 +57,0 @@ "homepage": "https://github.com/forcedotcom/salesforcedx-apex", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
423160
6677
Updated@jsforce/jsforce-node@^3.2.3
Updated@salesforce/core@^8.2.0