@salesforce/apex-node
Advanced tools
Comparing version 6.0.1 to 6.1.0
@@ -40,2 +40,3 @@ "use strict"; | ||
const elapsedTime_1 = require("../utils/elapsedTime"); | ||
const os = __importStar(require("node:os")); | ||
class ExecuteService { | ||
@@ -100,3 +101,3 @@ connection; | ||
timeout.refresh(); | ||
apexCode = apexCode + input + '\n'; | ||
apexCode = apexCode + input + os.EOL; | ||
}); | ||
@@ -103,0 +104,0 @@ readInterface.on('close', () => { |
@@ -40,3 +40,4 @@ "use strict"; | ||
const i18n_1 = require("../i18n"); | ||
const elapsedTime_1 = require("../utils/elapsedTime"); | ||
const utils_1 = require("../utils"); | ||
const os = __importStar(require("node:os")); | ||
const startOfSource = (source) => { | ||
@@ -150,3 +151,3 @@ if (source) { | ||
.readFileSync(fileCoverageData.path, 'utf8') | ||
.split('\n'); | ||
.split(os.EOL); | ||
} | ||
@@ -188,10 +189,10 @@ catch { | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], CoverageReporter.prototype, "generateReports", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], CoverageReporter.prototype, "buildCoverageMap", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], CoverageReporter.prototype, "findFullPathToClass", null); | ||
//# sourceMappingURL=coverageReporter.js.map |
@@ -7,2 +7,3 @@ /// <reference types="node" /> | ||
private readonly detailedCoverage; | ||
private logger; | ||
constructor(testResult: TestResult, detailedCoverage: boolean, options?: ReadableOptions); | ||
@@ -9,0 +10,0 @@ _read(): void; |
@@ -8,2 +8,18 @@ "use strict"; | ||
*/ | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
@@ -15,2 +31,9 @@ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -24,5 +47,7 @@ exports.HumanFormatTransform = void 0; | ||
const os_1 = require("os"); | ||
const os = __importStar(require("node:os")); | ||
class HumanFormatTransform extends node_stream_1.Readable { | ||
testResult; | ||
detailedCoverage; | ||
logger; | ||
constructor(testResult, detailedCoverage, options) { | ||
@@ -34,6 +59,15 @@ super(options); | ||
this.detailedCoverage ??= false; | ||
this.logger = core_1.Logger.childFromRoot('HumanFormatTransform'); | ||
} | ||
_read() { | ||
this.format(); | ||
this.push(null); // Indicates end of data | ||
this.logger.trace('starting _read'); | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('HumanFormatTransform._read'); | ||
try { | ||
this.format(); | ||
this.push(null); // Indicates end of data | ||
this.logger.trace('finishing _read'); | ||
} | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('HumanFormatTransform._read'); | ||
} | ||
} | ||
@@ -164,3 +198,3 @@ format() { | ||
}); | ||
this.push('\n\n'); | ||
this.push(os.EOL.repeat(2)); | ||
tb.createTable(testRowArray, [ | ||
@@ -197,3 +231,3 @@ { | ||
}); | ||
this.push('\n\n'); | ||
this.push(os.EOL.repeat(2)); | ||
tb.createTable(codeCovRowArray, [ | ||
@@ -200,0 +234,0 @@ { |
@@ -8,2 +8,18 @@ "use strict"; | ||
*/ | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
@@ -15,2 +31,9 @@ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -21,15 +44,22 @@ exports.HumanReporter = void 0; | ||
const core_1 = require("@salesforce/core"); | ||
const os = __importStar(require("node:os")); | ||
class HumanReporter { | ||
format(testResult, detailedCoverage) { | ||
let tbResult = this.formatSummary(testResult); | ||
if (!testResult.codecoverage || !detailedCoverage) { | ||
tbResult += this.formatTestResults(testResult.tests); | ||
} | ||
if (testResult.codecoverage) { | ||
if (detailedCoverage) { | ||
tbResult += this.formatDetailedCov(testResult); | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('HumanReporter.format'); | ||
try { | ||
let tbResult = this.formatSummary(testResult); | ||
if (!testResult.codecoverage || !detailedCoverage) { | ||
tbResult += this.formatTestResults(testResult.tests); | ||
} | ||
tbResult += this.formatCodeCov(testResult.codecoverage); | ||
if (testResult.codecoverage) { | ||
if (detailedCoverage) { | ||
tbResult += this.formatDetailedCov(testResult); | ||
} | ||
tbResult += this.formatCodeCov(testResult.codecoverage); | ||
} | ||
return tbResult; | ||
} | ||
return tbResult; | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('HumanReporter.format'); | ||
} | ||
} | ||
@@ -107,3 +137,3 @@ formatSummary(testResult) { | ||
}); | ||
let testResultTable = '\n\n'; | ||
let testResultTable = os.EOL.repeat(2); | ||
testResultTable += tb.createTable(testRowArray, [ | ||
@@ -150,3 +180,3 @@ { | ||
}); | ||
let detailedCovTable = '\n\n'; | ||
let detailedCovTable = os.EOL.repeat(2); | ||
detailedCovTable += tb.createTable(testRowArray, [ | ||
@@ -184,3 +214,3 @@ { | ||
}); | ||
let codeCovTable = '\n\n'; | ||
let codeCovTable = os.EOL.repeat(2); | ||
codeCovTable += tb.createTable(codeCovRowArray, [ | ||
@@ -187,0 +217,0 @@ { |
export { TapReporter } from './tapReporter'; | ||
export { JUnitReporter } from './junitReporter'; | ||
export { JUnitFormatTransformer } from './junitFormatTransformer'; | ||
export { HumanReporter } from './humanReporter'; | ||
export { HumanFormatTransform } from './humanFormatTransform'; | ||
export { CoverageReporter, CoverageReporterOptions, CoverageReportFormats, DefaultReportOptions, DefaultWatermarks } from './coverageReporter'; | ||
export { TapFormatTransformer } from './tapFormatTransform'; | ||
export { JUnitFormatTransformer } from './junitFormatTransformer'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.JUnitFormatTransformer = exports.TapFormatTransformer = exports.DefaultWatermarks = exports.DefaultReportOptions = exports.CoverageReporter = exports.HumanReporter = exports.JUnitReporter = exports.TapReporter = void 0; | ||
exports.TapFormatTransformer = exports.DefaultWatermarks = exports.DefaultReportOptions = exports.CoverageReporter = exports.HumanFormatTransform = exports.HumanReporter = exports.JUnitFormatTransformer = exports.JUnitReporter = exports.TapReporter = void 0; | ||
/* | ||
@@ -14,4 +14,8 @@ * Copyright (c) 2020, salesforce.com, inc. | ||
Object.defineProperty(exports, "JUnitReporter", { enumerable: true, get: function () { return junitReporter_1.JUnitReporter; } }); | ||
var junitFormatTransformer_1 = require("./junitFormatTransformer"); | ||
Object.defineProperty(exports, "JUnitFormatTransformer", { enumerable: true, get: function () { return junitFormatTransformer_1.JUnitFormatTransformer; } }); | ||
var humanReporter_1 = require("./humanReporter"); | ||
Object.defineProperty(exports, "HumanReporter", { enumerable: true, get: function () { return humanReporter_1.HumanReporter; } }); | ||
var humanFormatTransform_1 = require("./humanFormatTransform"); | ||
Object.defineProperty(exports, "HumanFormatTransform", { enumerable: true, get: function () { return humanFormatTransform_1.HumanFormatTransform; } }); | ||
var coverageReporter_1 = require("./coverageReporter"); | ||
@@ -23,4 +27,2 @@ Object.defineProperty(exports, "CoverageReporter", { enumerable: true, get: function () { return coverageReporter_1.CoverageReporter; } }); | ||
Object.defineProperty(exports, "TapFormatTransformer", { enumerable: true, get: function () { return tapFormatTransform_1.TapFormatTransformer; } }); | ||
var junitFormatTransformer_1 = require("./junitFormatTransformer"); | ||
Object.defineProperty(exports, "JUnitFormatTransformer", { enumerable: true, get: function () { return junitFormatTransformer_1.JUnitFormatTransformer; } }); | ||
//# sourceMappingURL=index.js.map |
/// <reference types="node" /> | ||
import { TestResult } from '../tests'; | ||
import { Readable, ReadableOptions } from 'node:stream'; | ||
export type JUnitFormatTransformerOptions = ReadableOptions & { | ||
bufferSize?: number; | ||
}; | ||
export declare class JUnitFormatTransformer extends Readable { | ||
private readonly testResult; | ||
constructor(testResult: TestResult, options?: ReadableOptions); | ||
private logger; | ||
private buffer; | ||
private bufferSize; | ||
constructor(testResult: TestResult, options?: JUnitFormatTransformerOptions); | ||
private pushToBuffer; | ||
_read(): void; | ||
@@ -8,0 +15,0 @@ format(): void; |
@@ -13,2 +13,3 @@ "use strict"; | ||
const narrowing_1 = require("../narrowing"); | ||
const core_1 = require("@salesforce/core"); | ||
// cli currently has spaces in multiples of four for junit format | ||
@@ -25,2 +26,5 @@ const tab = ' '; | ||
testResult; | ||
logger; | ||
buffer; | ||
bufferSize; | ||
constructor(testResult, options) { | ||
@@ -30,25 +34,42 @@ super(options); | ||
this.testResult = testResult; | ||
this.logger = core_1.Logger.childFromRoot('JUnitFormatTransformer'); | ||
this.buffer = ''; | ||
this.bufferSize = options?.bufferSize || 256; // Default buffer size is 256 | ||
} | ||
pushToBuffer(chunk) { | ||
this.buffer += chunk; | ||
if (this.buffer.length >= this.bufferSize) { | ||
this.push(this.buffer); | ||
this.buffer = ''; | ||
} | ||
} | ||
_read() { | ||
this.logger.trace('starting _read'); | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('JUnitFormatTransformer._read'); | ||
this.format(); | ||
if (this.buffer.length > 0) { | ||
this.push(this.buffer); | ||
} | ||
this.push(null); // Signal the end of the stream | ||
this.logger.trace('finishing _read'); | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('JUnitFormatTransformer._read'); | ||
} | ||
format() { | ||
const { summary } = this.testResult; | ||
this.push(`<?xml version="1.0" encoding="UTF-8"?>\n`); | ||
this.push(`<testsuites>\n`); | ||
this.push(`${tab}<testsuite name="force.apex" `); | ||
this.push(`timestamp="${summary.testStartTime}" `); | ||
this.push(`hostname="${summary.hostname}" `); | ||
this.push(`tests="${summary.testsRan}" `); | ||
this.push(`failures="${summary.failing}" `); | ||
this.push(`errors="0" `); | ||
this.push(`time="${(0, utils_1.msToSecond)(summary.testExecutionTimeInMs)}">\n`); | ||
this.pushToBuffer(`<?xml version="1.0" encoding="UTF-8"?>\n`); | ||
this.pushToBuffer(`<testsuites>\n`); | ||
this.pushToBuffer(`${tab}<testsuite name="force.apex" `); | ||
this.pushToBuffer(`timestamp="${summary.testStartTime}" `); | ||
this.pushToBuffer(`hostname="${summary.hostname}" `); | ||
this.pushToBuffer(`tests="${summary.testsRan}" `); | ||
this.pushToBuffer(`failures="${summary.failing}" `); | ||
this.pushToBuffer(`errors="0" `); | ||
this.pushToBuffer(`time="${(0, utils_1.msToSecond)(summary.testExecutionTimeInMs)}">\n`); | ||
this.buildProperties(); | ||
this.buildTestCases(); | ||
this.push(`${tab}</testsuite>\n`); | ||
this.push(`</testsuites>\n`); | ||
this.pushToBuffer(`${tab}</testsuite>\n`); | ||
this.pushToBuffer(`</testsuites>\n`); | ||
} | ||
buildProperties() { | ||
this.push(`${tab}${tab}<properties>\n`); | ||
this.pushToBuffer(`${tab}${tab}<properties>\n`); | ||
Object.entries(this.testResult.summary).forEach(([key, value]) => { | ||
@@ -68,5 +89,9 @@ if ((0, narrowing_1.isEmpty)(value) || skippedProperties.includes(key)) { | ||
} | ||
this.push(`${tab}${tab}${tab}<property name="${key}" value="${value}"/>\n`); | ||
this.pushToBuffer(`${tab}${tab}${tab}<property name="${key}" value="${value}"/>\n`); | ||
// this call to setImmediate will schedule the closure on the event loop | ||
// this action causing the current code to yield to the event loop | ||
// allowing other processes to get time on the event loop | ||
setImmediate(() => { }); | ||
}); | ||
this.push(`${tab}${tab}</properties>\n`); | ||
this.pushToBuffer(`${tab}${tab}</properties>\n`); | ||
} | ||
@@ -77,3 +102,3 @@ buildTestCases() { | ||
const methodName = JUnitFormatTransformer.xmlEscape(testCase.methodName); | ||
this.push(`${tab}${tab}<testcase name="${methodName}" classname="${testCase.apexClass.fullName}" time="${(0, utils_1.msToSecond)(testCase.runTime)}">\n`); | ||
this.pushToBuffer(`${tab}${tab}<testcase name="${methodName}" classname="${testCase.apexClass.fullName}" time="${(0, utils_1.msToSecond)(testCase.runTime)}">\n`); | ||
if (testCase.outcome === "Fail" /* ApexTestResultOutcome.Fail */ || | ||
@@ -83,9 +108,13 @@ testCase.outcome === "CompileFail" /* ApexTestResultOutcome.CompileFail */) { | ||
message = JUnitFormatTransformer.xmlEscape(message); | ||
this.push(`${tab}${tab}${tab}<failure message="${message}">`); | ||
this.pushToBuffer(`${tab}${tab}${tab}<failure message="${message}">`); | ||
if (testCase.stackTrace) { | ||
this.push(`<![CDATA[${testCase.stackTrace}]]>`); | ||
this.pushToBuffer(`<![CDATA[${testCase.stackTrace}]]>`); | ||
} | ||
this.push(`</failure>\n`); | ||
this.pushToBuffer(`</failure>\n`); | ||
} | ||
this.push(`${tab}${tab}</testcase>\n`); | ||
this.pushToBuffer(`${tab}${tab}</testcase>\n`); | ||
// this call to setImmediate will schedule the closure on the event loop | ||
// this action causing the current code to yield to the event loop | ||
// allowing other processes to get time on the event loop | ||
setImmediate(() => { }); | ||
} | ||
@@ -92,0 +121,0 @@ } |
@@ -24,17 +24,23 @@ "use strict"; | ||
format(testResult) { | ||
const { summary, tests } = testResult; | ||
let output = `<?xml version="1.0" encoding="UTF-8"?>\n`; | ||
output += `<testsuites>\n`; | ||
output += `${tab}<testsuite name="force.apex" `; | ||
output += `timestamp="${summary.testStartTime}" `; | ||
output += `hostname="${summary.hostname}" `; | ||
output += `tests="${summary.testsRan}" `; | ||
output += `failures="${summary.failing}" `; | ||
output += `errors="0" `; | ||
output += `time="${(0, utils_1.msToSecond)(summary.testExecutionTimeInMs)}">\n`; | ||
output += this.buildProperties(testResult); | ||
output += this.buildTestCases(tests); | ||
output += `${tab}</testsuite>\n`; | ||
output += `</testsuites>\n`; | ||
return output; | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('JUnitReporter.format'); | ||
try { | ||
const { summary, tests } = testResult; | ||
let output = `<?xml version="1.0" encoding="UTF-8"?>\n`; | ||
output += `<testsuites>\n`; | ||
output += `${tab}<testsuite name="force.apex" `; | ||
output += `timestamp="${summary.testStartTime}" `; | ||
output += `hostname="${summary.hostname}" `; | ||
output += `tests="${summary.testsRan}" `; | ||
output += `failures="${summary.failing}" `; | ||
output += `errors="0" `; | ||
output += `time="${(0, utils_1.msToSecond)(summary.testExecutionTimeInMs)}">\n`; | ||
output += this.buildProperties(testResult); | ||
output += this.buildTestCases(tests); | ||
output += `${tab}</testsuite>\n`; | ||
output += `</testsuites>\n`; | ||
return output; | ||
} | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('JUnitReporter.format'); | ||
} | ||
} | ||
@@ -41,0 +47,0 @@ buildProperties(testResult) { |
@@ -10,6 +10,13 @@ /// <reference types="node" /> | ||
} | ||
export type TapFormatTransformerOptions = ReadableOptions & { | ||
bufferSize?: number; | ||
}; | ||
export declare class TapFormatTransformer extends Readable { | ||
private readonly logger; | ||
private testResult; | ||
private epilogue?; | ||
constructor(testResult: TestResult, epilogue?: string[], options?: ReadableOptions); | ||
private buffer; | ||
private bufferSize; | ||
constructor(testResult: TestResult, epilogue?: string[], options?: TapFormatTransformerOptions); | ||
private pushToBuffer; | ||
_read(): void; | ||
@@ -16,0 +23,0 @@ format(): void; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
@@ -8,2 +24,9 @@ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -17,7 +40,12 @@ exports.TapFormatTransformer = void 0; | ||
*/ | ||
const core_1 = require("@salesforce/core"); | ||
const node_stream_1 = require("node:stream"); | ||
const utils_1 = require("../utils"); | ||
const os = __importStar(require("node:os")); | ||
class TapFormatTransformer extends node_stream_1.Readable { | ||
logger; | ||
testResult; | ||
epilogue; | ||
buffer; | ||
bufferSize; | ||
constructor(testResult, epilogue, options) { | ||
@@ -27,13 +55,30 @@ super(options); | ||
this.epilogue = epilogue; | ||
this.logger = core_1.Logger.childFromRoot('TapFormatTransformer'); | ||
this.buffer = ''; | ||
this.bufferSize = options?.bufferSize || 256; // Default buffer size is 256 | ||
} | ||
pushToBuffer(chunk) { | ||
this.buffer += chunk; | ||
if (this.buffer.length >= this.bufferSize) { | ||
this.push(this.buffer); | ||
this.buffer = ''; | ||
} | ||
} | ||
_read() { | ||
this.logger.trace('starting format'); | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('TapFormatTransformer._read'); | ||
this.format(); | ||
if (this.buffer.length > 0) { | ||
this.push(this.buffer); | ||
} | ||
this.push(null); // Signal the end of the stream | ||
this.logger.trace('finishing format'); | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('TapFormatTransformer._read'); | ||
} | ||
format() { | ||
const testPointCount = this.testResult.tests.length; | ||
this.push(`1..${testPointCount}\n`); | ||
this.pushToBuffer(`1..${testPointCount}\n`); | ||
this.buildTapResults(); | ||
this.epilogue?.forEach((c) => { | ||
this.push(`# ${c}\n`); | ||
this.pushToBuffer(`# ${c}\n`); | ||
}); | ||
@@ -45,5 +90,5 @@ } | ||
const outcome = test.outcome === "Pass" /* ApexTestResultOutcome.Pass */ ? 'ok' : 'not ok'; | ||
this.push(`${outcome} ${testNumber} ${test.fullName}\n`); | ||
this.pushToBuffer(`${outcome} ${testNumber} ${test.fullName}\n`); | ||
this.buildTapDiagnostics(test).forEach((s) => { | ||
this.push(`# ${s}\n`); | ||
this.pushToBuffer(`# ${s}\n`); | ||
}); | ||
@@ -72,3 +117,3 @@ }); | ||
if (testResult.stackTrace) { | ||
testResult.stackTrace.split('\n').forEach((line) => { | ||
testResult.stackTrace.split(os.EOL).forEach((line) => { | ||
message.push(line); | ||
@@ -75,0 +120,0 @@ }); |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
@@ -8,21 +24,35 @@ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TapReporter = void 0; | ||
const elapsedTime_1 = require("../utils/elapsedTime"); | ||
const utils_1 = require("../utils"); | ||
const os = __importStar(require("node:os")); | ||
class TapReporter { | ||
format(testResult, epilog) { | ||
const results = this.buildTapResults(testResult); | ||
const testPointCount = results.length; | ||
let out = ''; | ||
out = out.concat(`1..${testPointCount}\n`); | ||
results.forEach((testPoint) => { | ||
out = out.concat(`${testPoint.outcome} ${testPoint.testNumber} ${testPoint.description}\n`); | ||
testPoint.diagnostics.forEach((s) => { | ||
out = out.concat(`# ${s}\n`); | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('TapReporter.format'); | ||
try { | ||
const results = this.buildTapResults(testResult); | ||
const testPointCount = results.length; | ||
let out = ''; | ||
out = out.concat(`1..${testPointCount}\n`); | ||
results.forEach((testPoint) => { | ||
out = out.concat(`${testPoint.outcome} ${testPoint.testNumber} ${testPoint.description}\n`); | ||
testPoint.diagnostics.forEach((s) => { | ||
out = out.concat(`# ${s}\n`); | ||
}); | ||
}); | ||
}); | ||
epilog?.forEach((c) => { | ||
out = out.concat(`# ${c}\n`); | ||
}); | ||
return out; | ||
epilog?.forEach((c) => { | ||
out = out.concat(`# ${c}\n`); | ||
}); | ||
return out; | ||
} | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('TapReporter.format'); | ||
} | ||
} | ||
@@ -63,3 +93,3 @@ buildTapResults(testResult) { | ||
if (testResult.stackTrace) { | ||
testResult.stackTrace.split('\n').forEach((line) => { | ||
testResult.stackTrace.split(os.EOL).forEach((line) => { | ||
message.push(line); | ||
@@ -74,10 +104,10 @@ }); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], TapReporter.prototype, "format", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], TapReporter.prototype, "buildTapResults", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], TapReporter.prototype, "buildTapDiagnostics", null); | ||
//# sourceMappingURL=tapReporter.js.map |
export { AsyncTestRun, StreamingClient } from './streamingClient'; | ||
export { JSONStringifyStream } from './jsonStringifyStream'; | ||
export { TestResultStringifyStream } from './testResultStringifyStream'; | ||
export { determineType, getArrayEntries, getPrimitiveEntries, getObjectEntries, pushArrayToStream } from './utils'; | ||
export { determineType, getArrayEntries, getPrimitiveEntries, getObjectEntries } from './utils'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.pushArrayToStream = exports.getObjectEntries = exports.getPrimitiveEntries = exports.getArrayEntries = exports.determineType = exports.TestResultStringifyStream = exports.JSONStringifyStream = exports.StreamingClient = void 0; | ||
exports.getObjectEntries = exports.getPrimitiveEntries = exports.getArrayEntries = exports.determineType = exports.TestResultStringifyStream = exports.StreamingClient = void 0; | ||
/* | ||
@@ -12,4 +12,2 @@ * Copyright (c) 2020, salesforce.com, inc. | ||
Object.defineProperty(exports, "StreamingClient", { enumerable: true, get: function () { return streamingClient_1.StreamingClient; } }); | ||
var jsonStringifyStream_1 = require("./jsonStringifyStream"); | ||
Object.defineProperty(exports, "JSONStringifyStream", { enumerable: true, get: function () { return jsonStringifyStream_1.JSONStringifyStream; } }); | ||
var testResultStringifyStream_1 = require("./testResultStringifyStream"); | ||
@@ -22,3 +20,2 @@ Object.defineProperty(exports, "TestResultStringifyStream", { enumerable: true, get: function () { return testResultStringifyStream_1.TestResultStringifyStream; } }); | ||
Object.defineProperty(exports, "getObjectEntries", { enumerable: true, get: function () { return utils_1.getObjectEntries; } }); | ||
Object.defineProperty(exports, "pushArrayToStream", { enumerable: true, get: function () { return utils_1.pushArrayToStream; } }); | ||
//# sourceMappingURL=index.js.map |
/// <reference types="node" /> | ||
import { Readable, ReadableOptions } from 'node:stream'; | ||
import { TestResult } from '../tests'; | ||
export type TestResultStringifyStreamOptions = ReadableOptions & { | ||
bufferSize?: number; | ||
}; | ||
export declare class TestResultStringifyStream extends Readable { | ||
private readonly testResult; | ||
constructor(testResult: TestResult, options?: ReadableOptions); | ||
private readonly logger; | ||
private buffer; | ||
private readonly bufferSize; | ||
constructor(testResult: TestResult, options?: TestResultStringifyStreamOptions); | ||
private pushToBuffer; | ||
_read(): void; | ||
@@ -11,3 +18,4 @@ format(): void; | ||
buildCodeCoverage(): void; | ||
static fromTestResult(testResult: TestResult): TestResultStringifyStream; | ||
static fromTestResult(testResult: TestResult, options?: TestResultStringifyStreamOptions): TestResultStringifyStream; | ||
private pushArrayToBuffer; | ||
} |
@@ -16,7 +16,10 @@ "use strict"; | ||
*/ | ||
const core_1 = require("@salesforce/core"); | ||
const node_stream_1 = require("node:stream"); | ||
const utils_1 = require("./utils"); | ||
const utils_2 = require("../utils"); | ||
const utils_1 = require("../utils"); | ||
class TestResultStringifyStream extends node_stream_1.Readable { | ||
testResult; | ||
logger; | ||
buffer; | ||
bufferSize; | ||
constructor(testResult, options) { | ||
@@ -26,6 +29,22 @@ super({ ...options, objectMode: true }); | ||
this.testResult = testResult; | ||
this.logger = core_1.Logger.childFromRoot('TestResultStringifyStream'); | ||
this.buffer = ''; | ||
this.bufferSize = options?.bufferSize || 256; // Default buffer size is 256 | ||
} | ||
pushToBuffer(data) { | ||
this.buffer += data; | ||
if (this.buffer.length >= this.bufferSize) { | ||
this.push(this.buffer); | ||
this.buffer = ''; | ||
} | ||
} | ||
_read() { | ||
this.logger.trace('starting format'); | ||
this.format(); | ||
if (this.buffer.length > 0) { | ||
this.push(this.buffer); | ||
this.buffer = ''; | ||
} | ||
this.push(null); // Signal the end of the stream | ||
this.logger.trace('finishing format'); | ||
} | ||
@@ -36,70 +55,90 @@ format() { | ||
// outer curly | ||
this.push('{'); | ||
this.pushToBuffer('{'); | ||
// summary | ||
this.push(`"summary":${JSON.stringify(summary)},`); | ||
this.pushToBuffer(`"summary":${JSON.stringify(summary)},`); | ||
this.buildTests(); | ||
this.buildCodeCoverage(); | ||
// closing outer curly | ||
this.push(`}`); | ||
this.pushToBuffer(`}`); | ||
} | ||
buildTests() { | ||
this.push('"tests":['); | ||
this.pushToBuffer('"tests":['); | ||
const numberOfTests = this.testResult.tests.length - 1; | ||
this.testResult.tests.forEach((test, index) => { | ||
const { perClassCoverage, ...testRest } = test; | ||
this.push(`${JSON.stringify(testRest).slice(0, -1)}`); | ||
this.pushToBuffer(`${JSON.stringify(testRest).slice(0, -1)}`); | ||
if (perClassCoverage) { | ||
const numberOfPerClassCoverage = perClassCoverage.length - 1; | ||
this.push(',"perClassCoverage":['); | ||
this.pushToBuffer(',"perClassCoverage":['); | ||
perClassCoverage.forEach((pcc, index) => { | ||
const { coverage, ...coverageRest } = pcc; | ||
this.push(`${JSON.stringify(coverageRest).slice(0, -1)}`); | ||
this.push(`,"coverage":${JSON.stringify(coverage)}}`); | ||
this.pushToBuffer(`${JSON.stringify(coverageRest).slice(0, -1)}`); | ||
this.pushToBuffer(`,"coverage":${JSON.stringify(coverage)}}`); | ||
if (numberOfPerClassCoverage !== index) { | ||
this.push(','); | ||
this.pushToBuffer(','); | ||
} | ||
}); | ||
this.push(']'); | ||
this.pushToBuffer(']'); | ||
// this call to setImmediate will schedule the closure on the event loop | ||
// this action causing the current code to yield to the event loop | ||
// allowing other processes to get time on the event loop | ||
setImmediate(() => { }); | ||
} | ||
// close the tests | ||
this.push('}'); | ||
this.pushToBuffer('}'); | ||
if (numberOfTests !== index) { | ||
this.push(','); | ||
this.pushToBuffer(','); | ||
} | ||
}); | ||
this.push(']'); | ||
this.pushToBuffer(']'); | ||
} | ||
buildCodeCoverage() { | ||
if (this.testResult.codecoverage) { | ||
this.push(',"codecoverage":['); | ||
this.pushToBuffer(',"codecoverage":['); | ||
const numberOfCodeCoverage = this.testResult.codecoverage.length - 1; | ||
this.testResult.codecoverage.forEach((coverage, index) => { | ||
const { coveredLines, uncoveredLines, ...theRest } = coverage; | ||
this.push(`${JSON.stringify(theRest).slice(0, -1)}`); | ||
this.push(',"coveredLines":['); | ||
(0, utils_1.pushArrayToStream)(coveredLines, this); | ||
this.push('],"uncoveredLines":['); | ||
(0, utils_1.pushArrayToStream)(uncoveredLines, this); | ||
this.push(']}'); | ||
this.pushToBuffer(`${JSON.stringify(theRest).slice(0, -1)}`); | ||
this.pushToBuffer(',"coveredLines":['); | ||
this.pushArrayToBuffer(coveredLines); | ||
this.pushToBuffer('],"uncoveredLines":['); | ||
this.pushArrayToBuffer(uncoveredLines); | ||
this.pushToBuffer(']}'); | ||
if (numberOfCodeCoverage !== index) { | ||
this.push(','); | ||
this.pushToBuffer(','); | ||
} | ||
// this call to setImmediate will schedule the closure on the event loop | ||
// this action causing the current code to yield to the event loop | ||
// allowing other processes to get time on the event loop | ||
setImmediate(() => { }); | ||
}); | ||
this.push(']'); | ||
this.pushToBuffer(']'); | ||
} | ||
} | ||
static fromTestResult(testResult) { | ||
return new TestResultStringifyStream(testResult); | ||
static fromTestResult(testResult, options) { | ||
return new TestResultStringifyStream(testResult, options); | ||
} | ||
pushArrayToBuffer(array) { | ||
const chunkSize = 1000; | ||
for (let i = 0; i < array.length; i += chunkSize) { | ||
const chunk = array.slice(i, i + chunkSize); | ||
let jsonString = JSON.stringify(chunk); | ||
jsonString = jsonString.slice(1, -1); // remove '[' and ']' | ||
this.pushToBuffer(jsonString); | ||
if (i + chunkSize < array.length) { | ||
this.pushToBuffer(','); // add comma for all but the last chunk | ||
} | ||
} | ||
} | ||
} | ||
exports.TestResultStringifyStream = TestResultStringifyStream; | ||
__decorate([ | ||
(0, utils_2.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], TestResultStringifyStream.prototype, "format", null); | ||
__decorate([ | ||
(0, utils_2.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], TestResultStringifyStream.prototype, "buildTests", null); | ||
__decorate([ | ||
(0, utils_2.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], TestResultStringifyStream.prototype, "buildCodeCoverage", null); | ||
//# sourceMappingURL=testResultStringifyStream.js.map |
@@ -1,4 +0,1 @@ | ||
/// <reference types="node" /> | ||
import { Readable } from 'node:stream'; | ||
export declare const pushArrayToStream: (array: unknown[], stream: Readable) => void; | ||
export declare const getPrimitiveEntries: (obj: object) => [string, unknown][]; | ||
@@ -5,0 +2,0 @@ export declare const getComplexEntries: (obj: object) => [string, unknown][]; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.determineType = exports.getArrayEntries = exports.getObjectEntries = exports.getComplexEntries = exports.getPrimitiveEntries = exports.pushArrayToStream = void 0; | ||
exports.determineType = exports.getArrayEntries = exports.getObjectEntries = exports.getComplexEntries = exports.getPrimitiveEntries = void 0; | ||
/* | ||
* Copyright (c) 2023, salesforce.com, inc. | ||
* All rights reserved. | ||
* Licensed under the BSD 3-Clause license. | ||
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
const narrowing_1 = require("../narrowing"); | ||
const pushArrayToStream = (array, stream) => { | ||
const chunkSize = 1000; | ||
for (let i = 0; i < array.length; i += chunkSize) { | ||
const chunk = array.slice(i, i + chunkSize); | ||
let jsonString = JSON.stringify(chunk); | ||
jsonString = jsonString.slice(1, -1); // remove '[' and ']' | ||
stream.push(jsonString); | ||
if (i + chunkSize < array.length) { | ||
stream.push(','); // add comma for all but the last chunk | ||
} | ||
} | ||
}; | ||
exports.pushArrayToStream = pushArrayToStream; | ||
const getPrimitiveEntries = (obj) => { | ||
@@ -19,0 +12,0 @@ return Object.entries(obj).filter((entry) => (0, narrowing_1.isPrimitive)(entry[1])); |
@@ -9,2 +9,3 @@ import { Connection } from '@salesforce/core'; | ||
private readonly codecoverage; | ||
private readonly logger; | ||
constructor(connection: Connection); | ||
@@ -21,2 +22,3 @@ /** | ||
runTests(options: AsyncTestConfiguration | AsyncTestArrayConfiguration, codeCoverage?: boolean, exitOnTestRunId?: boolean, progress?: Progress<ApexTestProgressValue>, token?: CancellationToken, timeout?: Duration): Promise<TestResult | TestRunIdResult>; | ||
private writeResultsToFile; | ||
/** | ||
@@ -48,2 +50,3 @@ * Report Asynchronous Test Run Results | ||
* @param testRunId | ||
* @param progress | ||
*/ | ||
@@ -50,0 +53,0 @@ abortTestRun(testRunId: string, progress?: Progress<ApexTestProgressValue>): Promise<void>; |
@@ -37,4 +37,8 @@ "use strict"; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AsyncTests = void 0; | ||
const core_1 = require("@salesforce/core"); | ||
const i18n_1 = require("../i18n"); | ||
@@ -49,2 +53,9 @@ const streaming_1 = require("../streaming"); | ||
const narrowing_1 = require("../narrowing"); | ||
const node_fs_1 = require("node:fs"); | ||
const promises_1 = require("node:stream/promises"); | ||
const os = __importStar(require("node:os")); | ||
const path_1 = __importDefault(require("path")); | ||
const promises_2 = __importDefault(require("node:fs/promises")); | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const bfj = require('bfj'); | ||
const finishedStatuses = [ | ||
@@ -60,5 +71,7 @@ "Aborted" /* ApexTestRunResultStatus.Aborted */, | ||
codecoverage; | ||
logger; | ||
constructor(connection) { | ||
this.connection = connection; | ||
this.codecoverage = new codeCoverage_1.CodeCoverage(this.connection); | ||
this.logger = core_1.Logger.childFromRoot('AsyncTests'); | ||
} | ||
@@ -75,2 +88,3 @@ /** | ||
async runTests(options, codeCoverage = false, exitOnTestRunId = false, progress, token, timeout) { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.runTests'); | ||
try { | ||
@@ -99,3 +113,5 @@ const sClient = new streaming_1.StreamingClient(this.connection, progress); | ||
const runResult = await this.checkRunStatus(asyncRunResult.runId); | ||
return await this.formatAsyncResults(asyncRunResult, (0, utils_1.getCurrentTime)(), codeCoverage, runResult.testRunSummary, progress); | ||
const formattedResults = await this.formatAsyncResults(asyncRunResult, (0, utils_1.getCurrentTime)(), codeCoverage, runResult.testRunSummary, progress); | ||
await this.writeResultsToFile(formattedResults, asyncRunResult.runId); | ||
return formattedResults; | ||
} | ||
@@ -105,3 +121,26 @@ catch (e) { | ||
} | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.runTests'); | ||
} | ||
} | ||
async writeResultsToFile(formattedResults, runId) { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.writeResultsToFile'); | ||
try { | ||
if (this.logger.shouldLog(core_1.LoggerLevel.DEBUG)) { | ||
const rawResultsPath = path_1.default.join(os.tmpdir(), runId, 'rawResults.json'); | ||
await promises_2.default.mkdir(path_1.default.dirname(rawResultsPath), { recursive: true }); | ||
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}`); | ||
const stringifyStream = bfj.stringify(formattedResults, { | ||
bufferLength: (0, utils_2.getBufferSize)(), | ||
iterables: 'ignore', | ||
space: (0, utils_2.getJsonIndent)() | ||
}); | ||
return await (0, promises_1.pipeline)(stringifyStream, writeStream); | ||
} | ||
} | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.writeResultsToFile'); | ||
} | ||
} | ||
/** | ||
@@ -114,2 +153,3 @@ * Report Asynchronous Test Run Results | ||
async reportAsyncResults(testRunId, codeCoverage = false, token) { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.reportAsyncResults'); | ||
try { | ||
@@ -135,3 +175,5 @@ const sClient = new streaming_1.StreamingClient(this.connection); | ||
} | ||
return await this.formatAsyncResults({ queueItem, runId: testRunId }, (0, utils_1.getCurrentTime)(), codeCoverage, runResult.testRunSummary); | ||
const formattedResults = await this.formatAsyncResults({ queueItem, runId: testRunId }, (0, utils_1.getCurrentTime)(), codeCoverage, runResult.testRunSummary); | ||
await this.writeResultsToFile(formattedResults, testRunId); | ||
return formattedResults; | ||
} | ||
@@ -141,2 +183,5 @@ catch (e) { | ||
} | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.reportAsyncResults'); | ||
} | ||
} | ||
@@ -176,141 +221,159 @@ async checkRunStatus(testRunId, progress) { | ||
async formatAsyncResults(asyncRunResult, commandStartTime, codeCoverage = false, testRunSummary, progress) { | ||
const coveredApexClassIdSet = new Set(); | ||
const apexTestResults = await this.getAsyncTestResults(asyncRunResult.queueItem); | ||
const { apexTestClassIdSet, testResults, globalTests } = await this.buildAsyncTestResults(apexTestResults); | ||
let outcome = testRunSummary.Status; | ||
if (globalTests.failed > 0) { | ||
outcome = "Failed" /* ApexTestRunResultStatus.Failed */; | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.formatAsyncResults'); | ||
try { | ||
const coveredApexClassIdSet = new Set(); | ||
const apexTestResults = await this.getAsyncTestResults(asyncRunResult.queueItem); | ||
const { apexTestClassIdSet, testResults, globalTests } = await this.buildAsyncTestResults(apexTestResults); | ||
let outcome = testRunSummary.Status; | ||
if (globalTests.failed > 0) { | ||
outcome = "Failed" /* ApexTestRunResultStatus.Failed */; | ||
} | ||
else if (globalTests.passed === 0) { | ||
outcome = "Skipped" /* ApexTestRunResultStatus.Skipped */; | ||
} | ||
else if (testRunSummary.Status === "Completed" /* ApexTestRunResultStatus.Completed */) { | ||
outcome = "Passed" /* ApexTestRunResultStatus.Passed */; | ||
} | ||
// TODO: deprecate testTotalTime | ||
const result = { | ||
summary: { | ||
outcome, | ||
testsRan: testResults.length, | ||
passing: globalTests.passed, | ||
failing: globalTests.failed, | ||
skipped: globalTests.skipped, | ||
passRate: (0, utils_2.calculatePercentage)(globalTests.passed, testResults.length), | ||
failRate: (0, utils_2.calculatePercentage)(globalTests.failed, testResults.length), | ||
skipRate: (0, utils_2.calculatePercentage)(globalTests.skipped, testResults.length), | ||
testStartTime: (0, utils_1.formatStartTime)(testRunSummary.StartTime, 'ISO'), | ||
testExecutionTimeInMs: testRunSummary.TestTime ?? 0, | ||
testTotalTimeInMs: testRunSummary.TestTime ?? 0, | ||
commandTimeInMs: (0, utils_1.getCurrentTime)() - commandStartTime, | ||
hostname: this.connection.instanceUrl, | ||
orgId: this.connection.getAuthInfoFields().orgId, | ||
username: this.connection.getUsername(), | ||
testRunId: asyncRunResult.runId, | ||
userId: testRunSummary.UserId | ||
}, | ||
tests: testResults | ||
}; | ||
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 result; | ||
} | ||
else if (globalTests.passed === 0) { | ||
outcome = "Skipped" /* ApexTestRunResultStatus.Skipped */; | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.formatAsyncResults'); | ||
} | ||
else if (testRunSummary.Status === "Completed" /* ApexTestRunResultStatus.Completed */) { | ||
outcome = "Passed" /* ApexTestRunResultStatus.Passed */; | ||
} | ||
// TODO: deprecate testTotalTime | ||
const result = { | ||
summary: { | ||
outcome, | ||
testsRan: testResults.length, | ||
passing: globalTests.passed, | ||
failing: globalTests.failed, | ||
skipped: globalTests.skipped, | ||
passRate: (0, utils_2.calculatePercentage)(globalTests.passed, testResults.length), | ||
failRate: (0, utils_2.calculatePercentage)(globalTests.failed, testResults.length), | ||
skipRate: (0, utils_2.calculatePercentage)(globalTests.skipped, testResults.length), | ||
testStartTime: (0, utils_1.formatStartTime)(testRunSummary.StartTime, 'ISO'), | ||
testExecutionTimeInMs: testRunSummary.TestTime ?? 0, | ||
testTotalTimeInMs: testRunSummary.TestTime ?? 0, | ||
commandTimeInMs: (0, utils_1.getCurrentTime)() - commandStartTime, | ||
hostname: this.connection.instanceUrl, | ||
orgId: this.connection.getAuthInfoFields().orgId, | ||
username: this.connection.getUsername(), | ||
testRunId: asyncRunResult.runId, | ||
userId: testRunSummary.UserId | ||
}, | ||
tests: testResults | ||
}; | ||
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 result; | ||
} | ||
async getAsyncTestResults(testQueueResult) { | ||
let apexTestResultQuery = 'SELECT Id, QueueItemId, StackTrace, Message, '; | ||
apexTestResultQuery += | ||
'RunTime, TestTimestamp, AsyncApexJobId, MethodName, Outcome, ApexLogId, '; | ||
apexTestResultQuery += | ||
'ApexClass.Id, ApexClass.Name, ApexClass.NamespacePrefix '; | ||
apexTestResultQuery += 'FROM ApexTestResult WHERE QueueItemId IN (%s)'; | ||
const apexResultIds = testQueueResult.records.map((record) => record.Id); | ||
// iterate thru ids, create query with id, & compare query length to char limit | ||
const queries = []; | ||
for (let i = 0; i < apexResultIds.length; i += constants_1.QUERY_RECORD_LIMIT) { | ||
const recordSet = apexResultIds | ||
.slice(i, i + constants_1.QUERY_RECORD_LIMIT) | ||
.map((id) => `'${id}'`); | ||
const query = util.format(apexTestResultQuery, recordSet.join(',')); | ||
queries.push(query); | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.getAsyncTestResults'); | ||
try { | ||
let apexTestResultQuery = 'SELECT Id, QueueItemId, StackTrace, Message, '; | ||
apexTestResultQuery += | ||
'RunTime, TestTimestamp, AsyncApexJobId, MethodName, Outcome, ApexLogId, '; | ||
apexTestResultQuery += | ||
'ApexClass.Id, ApexClass.Name, ApexClass.NamespacePrefix '; | ||
apexTestResultQuery += 'FROM ApexTestResult WHERE QueueItemId IN (%s)'; | ||
const apexResultIds = testQueueResult.records.map((record) => record.Id); | ||
// iterate thru ids, create query with id, & compare query length to char limit | ||
const queries = []; | ||
for (let i = 0; i < apexResultIds.length; i += constants_1.QUERY_RECORD_LIMIT) { | ||
const recordSet = apexResultIds | ||
.slice(i, i + constants_1.QUERY_RECORD_LIMIT) | ||
.map((id) => `'${id}'`); | ||
const query = util.format(apexTestResultQuery, recordSet.join(',')); | ||
queries.push(query); | ||
} | ||
const queryPromises = queries.map((query) => { | ||
return (0, utils_2.queryAll)(this.connection, query, true); | ||
}); | ||
const apexTestResults = await Promise.all(queryPromises); | ||
return apexTestResults; | ||
} | ||
const queryPromises = queries.map((query) => { | ||
return (0, utils_2.queryAll)(this.connection, query, true); | ||
}); | ||
const apexTestResults = await Promise.all(queryPromises); | ||
return apexTestResults; | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.getAsyncTestResults'); | ||
} | ||
} | ||
async buildAsyncTestResults(apexTestResults) { | ||
const apexTestClassIdSet = new Set(); | ||
let passed = 0; | ||
let failed = 0; | ||
let skipped = 0; | ||
// Iterate over test results, format and add them as results.tests | ||
const testResults = []; | ||
for (const result of apexTestResults) { | ||
result.records.forEach((item) => { | ||
switch (item.Outcome) { | ||
case "Pass" /* ApexTestResultOutcome.Pass */: | ||
passed++; | ||
break; | ||
case "Fail" /* ApexTestResultOutcome.Fail */: | ||
case "CompileFail" /* ApexTestResultOutcome.CompileFail */: | ||
failed++; | ||
break; | ||
case "Skip" /* ApexTestResultOutcome.Skip */: | ||
skipped++; | ||
break; | ||
} | ||
apexTestClassIdSet.add(item.ApexClass.Id); | ||
// Can only query the FullName field if a single record is returned, so manually build the field | ||
item.ApexClass.FullName = item.ApexClass.NamespacePrefix | ||
? `${item.ApexClass.NamespacePrefix}.${item.ApexClass.Name}` | ||
: item.ApexClass.Name; | ||
const diagnostic = item.Message || item.StackTrace ? (0, diagnosticUtil_1.getAsyncDiagnostic)(item) : null; | ||
testResults.push({ | ||
id: item.Id, | ||
queueItemId: item.QueueItemId, | ||
stackTrace: item.StackTrace, | ||
message: item.Message, | ||
asyncApexJobId: item.AsyncApexJobId, | ||
methodName: item.MethodName, | ||
outcome: item.Outcome, | ||
apexLogId: item.ApexLogId, | ||
apexClass: { | ||
id: item.ApexClass.Id, | ||
name: item.ApexClass.Name, | ||
namespacePrefix: item.ApexClass.NamespacePrefix, | ||
fullName: item.ApexClass.FullName | ||
}, | ||
runTime: item.RunTime ?? 0, | ||
testTimestamp: item.TestTimestamp, // TODO: convert timestamp | ||
fullName: `${item.ApexClass.FullName}.${item.MethodName}`, | ||
...(diagnostic ? { diagnostic } : {}) | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.buildAsyncTestResults'); | ||
try { | ||
const apexTestClassIdSet = new Set(); | ||
let passed = 0; | ||
let failed = 0; | ||
let skipped = 0; | ||
// Iterate over test results, format and add them as results.tests | ||
const testResults = []; | ||
for (const result of apexTestResults) { | ||
result.records.forEach((item) => { | ||
switch (item.Outcome) { | ||
case "Pass" /* ApexTestResultOutcome.Pass */: | ||
passed++; | ||
break; | ||
case "Fail" /* ApexTestResultOutcome.Fail */: | ||
case "CompileFail" /* ApexTestResultOutcome.CompileFail */: | ||
failed++; | ||
break; | ||
case "Skip" /* ApexTestResultOutcome.Skip */: | ||
skipped++; | ||
break; | ||
} | ||
apexTestClassIdSet.add(item.ApexClass.Id); | ||
// Can only query the FullName field if a single record is returned, so manually build the field | ||
item.ApexClass.FullName = item.ApexClass.NamespacePrefix | ||
? `${item.ApexClass.NamespacePrefix}.${item.ApexClass.Name}` | ||
: item.ApexClass.Name; | ||
const diagnostic = item.Message || item.StackTrace ? (0, diagnosticUtil_1.getAsyncDiagnostic)(item) : null; | ||
testResults.push({ | ||
id: item.Id, | ||
queueItemId: item.QueueItemId, | ||
stackTrace: item.StackTrace, | ||
message: item.Message, | ||
asyncApexJobId: item.AsyncApexJobId, | ||
methodName: item.MethodName, | ||
outcome: item.Outcome, | ||
apexLogId: item.ApexLogId, | ||
apexClass: { | ||
id: item.ApexClass.Id, | ||
name: item.ApexClass.Name, | ||
namespacePrefix: item.ApexClass.NamespacePrefix, | ||
fullName: item.ApexClass.FullName | ||
}, | ||
runTime: item.RunTime ?? 0, | ||
testTimestamp: item.TestTimestamp, // TODO: convert timestamp | ||
fullName: `${item.ApexClass.FullName}.${item.MethodName}`, | ||
...(diagnostic ? { diagnostic } : {}) | ||
}); | ||
}); | ||
}); | ||
} | ||
return { | ||
apexTestClassIdSet, | ||
testResults, | ||
globalTests: { passed, failed, skipped } | ||
}; | ||
} | ||
return { | ||
apexTestClassIdSet, | ||
testResults, | ||
globalTests: { passed, failed, skipped } | ||
}; | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('asyncTests.buildAsyncTestResults'); | ||
} | ||
} | ||
@@ -320,2 +383,3 @@ /** | ||
* @param testRunId | ||
* @param progress | ||
*/ | ||
@@ -342,3 +406,3 @@ async abortTestRun(testRunId, progress) { | ||
getTestRunRequestAction(options) { | ||
const requestTestRun = async () => { | ||
return async () => { | ||
const url = `${this.connection.tooling._baseUrl()}/runTestsAsynchronous`; | ||
@@ -358,3 +422,2 @@ try { | ||
}; | ||
return requestTestRun; | ||
} | ||
@@ -361,0 +424,0 @@ } |
@@ -42,3 +42,3 @@ "use strict"; | ||
const constants_1 = require("./constants"); | ||
const elapsedTime_1 = require("../utils/elapsedTime"); | ||
const utils_2 = require("../utils"); | ||
class CodeCoverage { | ||
@@ -54,7 +54,13 @@ connection; | ||
async getOrgWideCoverage() { | ||
const orgWideCoverageResult = (await this.connection.tooling.query('SELECT PercentCovered FROM ApexOrgWideCoverage')); | ||
if (orgWideCoverageResult.records.length === 0) { | ||
return '0%'; | ||
utils_2.HeapMonitor.getInstance().checkHeapSize('codeCoverage.getOrgWideCoverage'); | ||
try { | ||
const orgWideCoverageResult = (await this.connection.tooling.query('SELECT PercentCovered FROM ApexOrgWideCoverage')); | ||
if (orgWideCoverageResult.records.length === 0) { | ||
return '0%'; | ||
} | ||
return `${orgWideCoverageResult.records[0].PercentCovered}%`; | ||
} | ||
return `${orgWideCoverageResult.records[0].PercentCovered}%`; | ||
finally { | ||
utils_2.HeapMonitor.getInstance().checkHeapSize('codeCoverage.getOrgWideCoverage'); | ||
} | ||
} | ||
@@ -68,31 +74,37 @@ /** | ||
async getPerClassCodeCoverage(apexTestClassSet) { | ||
if (apexTestClassSet.size === 0) { | ||
return new Map(); | ||
utils_2.HeapMonitor.getInstance().checkHeapSize('codeCoverage.getPerClassCodeCoverage'); | ||
try { | ||
if (apexTestClassSet.size === 0) { | ||
return new Map(); | ||
} | ||
const perClassCodeCovResults = await this.queryPerClassCodeCov(apexTestClassSet); | ||
const perClassCoverageMap = new Map(); | ||
perClassCodeCovResults.forEach((chunk) => { | ||
chunk.records.forEach((item) => { | ||
const totalLines = item.NumLinesCovered + item.NumLinesUncovered; | ||
const percentage = (0, utils_1.calculatePercentage)(item.NumLinesCovered, totalLines); | ||
const value = { | ||
apexClassOrTriggerName: item.ApexClassOrTrigger.Name, | ||
apexClassOrTriggerId: item.ApexClassOrTrigger.Id, | ||
apexTestClassId: item.ApexTestClassId, | ||
apexTestMethodName: item.TestMethodName, | ||
numLinesCovered: item.NumLinesCovered, | ||
numLinesUncovered: item.NumLinesUncovered, | ||
percentage, | ||
...(item.Coverage ? { coverage: item.Coverage } : {}) | ||
}; | ||
const key = `${item.ApexTestClassId}-${item.TestMethodName}`; | ||
if (perClassCoverageMap.get(key)) { | ||
perClassCoverageMap.get(key).push(value); | ||
} | ||
else { | ||
perClassCoverageMap.set(`${item.ApexTestClassId}-${item.TestMethodName}`, [value]); | ||
} | ||
}); | ||
}); | ||
return perClassCoverageMap; | ||
} | ||
const perClassCodeCovResults = await this.queryPerClassCodeCov(apexTestClassSet); | ||
const perClassCoverageMap = new Map(); | ||
perClassCodeCovResults.forEach((chunk) => { | ||
chunk.records.forEach((item) => { | ||
const totalLines = item.NumLinesCovered + item.NumLinesUncovered; | ||
const percentage = (0, utils_1.calculatePercentage)(item.NumLinesCovered, totalLines); | ||
const value = { | ||
apexClassOrTriggerName: item.ApexClassOrTrigger.Name, | ||
apexClassOrTriggerId: item.ApexClassOrTrigger.Id, | ||
apexTestClassId: item.ApexTestClassId, | ||
apexTestMethodName: item.TestMethodName, | ||
numLinesCovered: item.NumLinesCovered, | ||
numLinesUncovered: item.NumLinesUncovered, | ||
percentage, | ||
...(item.Coverage ? { coverage: item.Coverage } : {}) | ||
}; | ||
const key = `${item.ApexTestClassId}-${item.TestMethodName}`; | ||
if (perClassCoverageMap.get(key)) { | ||
perClassCoverageMap.get(key).push(value); | ||
} | ||
else { | ||
perClassCoverageMap.set(`${item.ApexTestClassId}-${item.TestMethodName}`, [value]); | ||
} | ||
}); | ||
}); | ||
return perClassCoverageMap; | ||
finally { | ||
utils_2.HeapMonitor.getInstance().checkHeapSize('codeCoverage.getPerClassCodeCoverage'); | ||
} | ||
} | ||
@@ -105,32 +117,38 @@ /** | ||
async getAggregateCodeCoverage(apexClassIdSet) { | ||
const codeCoverageAggregates = await this.queryAggregateCodeCov(apexClassIdSet); | ||
let totalLinesCovered = 0; | ||
let totalLinesUncovered = 0; | ||
const totalCodeCoverageResults = []; | ||
codeCoverageAggregates.forEach((chunk) => { | ||
const codeCoverageResults = chunk.records.map((item) => { | ||
totalLinesCovered += item.NumLinesCovered; | ||
totalLinesUncovered += item.NumLinesUncovered; | ||
const totalLines = item.NumLinesCovered + item.NumLinesUncovered; | ||
const percentage = (0, utils_1.calculatePercentage)(item.NumLinesCovered, totalLines); | ||
return { | ||
apexId: item.ApexClassOrTrigger.Id, | ||
name: item.ApexClassOrTrigger.Name, | ||
type: item.ApexClassOrTrigger.Id.startsWith('01p') | ||
? 'ApexClass' | ||
: 'ApexTrigger', | ||
numLinesCovered: item.NumLinesCovered, | ||
numLinesUncovered: item.NumLinesUncovered, | ||
percentage, | ||
coveredLines: item.Coverage.coveredLines, | ||
uncoveredLines: item.Coverage.uncoveredLines | ||
}; | ||
utils_2.HeapMonitor.getInstance().checkHeapSize('codeCoverage.getAggregateCodeCoverage'); | ||
try { | ||
const codeCoverageAggregates = await this.queryAggregateCodeCov(apexClassIdSet); | ||
let totalLinesCovered = 0; | ||
let totalLinesUncovered = 0; | ||
const totalCodeCoverageResults = []; | ||
codeCoverageAggregates.forEach((chunk) => { | ||
const codeCoverageResults = chunk.records.map((item) => { | ||
totalLinesCovered += item.NumLinesCovered; | ||
totalLinesUncovered += item.NumLinesUncovered; | ||
const totalLines = item.NumLinesCovered + item.NumLinesUncovered; | ||
const percentage = (0, utils_1.calculatePercentage)(item.NumLinesCovered, totalLines); | ||
return { | ||
apexId: item.ApexClassOrTrigger.Id, | ||
name: item.ApexClassOrTrigger.Name, | ||
type: item.ApexClassOrTrigger.Id.startsWith('01p') | ||
? 'ApexClass' | ||
: 'ApexTrigger', | ||
numLinesCovered: item.NumLinesCovered, | ||
numLinesUncovered: item.NumLinesUncovered, | ||
percentage, | ||
coveredLines: item.Coverage.coveredLines, | ||
uncoveredLines: item.Coverage.uncoveredLines | ||
}; | ||
}); | ||
totalCodeCoverageResults.push(...codeCoverageResults); | ||
}); | ||
totalCodeCoverageResults.push(...codeCoverageResults); | ||
}); | ||
return { | ||
codeCoverageResults: totalCodeCoverageResults, | ||
totalLines: totalLinesCovered + totalLinesUncovered, | ||
coveredLines: totalLinesCovered | ||
}; | ||
return { | ||
codeCoverageResults: totalCodeCoverageResults, | ||
totalLines: totalLinesCovered + totalLinesUncovered, | ||
coveredLines: totalLinesCovered | ||
}; | ||
} | ||
finally { | ||
utils_2.HeapMonitor.getInstance().checkHeapSize('codeCoverage.getAggregateCodeCoverage'); | ||
} | ||
} | ||
@@ -187,19 +205,19 @@ async queryPerClassCodeCov(apexTestClassSet) { | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_2.elapsedTime)() | ||
], CodeCoverage.prototype, "getOrgWideCoverage", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_2.elapsedTime)() | ||
], CodeCoverage.prototype, "getPerClassCodeCoverage", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_2.elapsedTime)() | ||
], CodeCoverage.prototype, "getAggregateCodeCoverage", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_2.elapsedTime)() | ||
], CodeCoverage.prototype, "queryPerClassCodeCov", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_2.elapsedTime)() | ||
], CodeCoverage.prototype, "queryAggregateCodeCov", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_2.elapsedTime)() | ||
], CodeCoverage.prototype, "fetchResults", null); | ||
//# sourceMappingURL=codeCoverage.js.map |
@@ -20,3 +20,2 @@ "use strict"; | ||
const utils_2 = require("./utils"); | ||
const elapsedTime_1 = require("../utils/elapsedTime"); | ||
class SyncTests { | ||
@@ -36,2 +35,3 @@ connection; | ||
async runTests(options, codeCoverage = false, token) { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('synctests.runTests'); | ||
try { | ||
@@ -54,106 +54,121 @@ const url = `${this.connection.tooling._baseUrl()}/runTestsSynchronous`; | ||
} | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('synctests.runTests'); | ||
} | ||
} | ||
async formatSyncResults(apiTestResult, startTime, codeCoverage = false) { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('synctests.formatSyncResults'); | ||
const coveredApexClassIdSet = new Set(); | ||
const { apexTestClassIdSet, testResults } = this.buildSyncTestResults(apiTestResult); | ||
const globalTestFailed = apiTestResult.failures.length; | ||
const globalTestPassed = apiTestResult.successes.length; | ||
const result = { | ||
summary: { | ||
outcome: globalTestFailed === 0 | ||
? "Passed" /* ApexTestRunResultStatus.Passed */ | ||
: "Failed" /* ApexTestRunResultStatus.Failed */, | ||
testsRan: apiTestResult.numTestsRun, | ||
passing: globalTestPassed, | ||
failing: globalTestFailed, | ||
skipped: 0, | ||
passRate: (0, utils_2.calculatePercentage)(globalTestPassed, apiTestResult.numTestsRun), | ||
failRate: (0, utils_2.calculatePercentage)(globalTestFailed, apiTestResult.numTestsRun), | ||
skipRate: (0, utils_2.calculatePercentage)(0, apiTestResult.numTestsRun), | ||
testStartTime: (0, utils_1.formatStartTime)(startTime, 'ISO'), | ||
testExecutionTimeInMs: apiTestResult.totalTime ?? 0, | ||
testTotalTimeInMs: apiTestResult.totalTime ?? 0, | ||
commandTimeInMs: (0, utils_1.getCurrentTime)() - startTime, | ||
hostname: this.connection.instanceUrl, | ||
orgId: this.connection.getAuthInfoFields().orgId, | ||
username: this.connection.getUsername(), | ||
testRunId: '', | ||
userId: this.connection.getConnectionOptions().userId | ||
}, | ||
tests: testResults | ||
}; | ||
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; | ||
} | ||
}); | ||
try { | ||
const globalTestFailed = apiTestResult.failures.length; | ||
const globalTestPassed = apiTestResult.successes.length; | ||
const result = { | ||
summary: { | ||
outcome: globalTestFailed === 0 | ||
? "Passed" /* ApexTestRunResultStatus.Passed */ | ||
: "Failed" /* ApexTestRunResultStatus.Failed */, | ||
testsRan: apiTestResult.numTestsRun, | ||
passing: globalTestPassed, | ||
failing: globalTestFailed, | ||
skipped: 0, | ||
passRate: (0, utils_2.calculatePercentage)(globalTestPassed, apiTestResult.numTestsRun), | ||
failRate: (0, utils_2.calculatePercentage)(globalTestFailed, apiTestResult.numTestsRun), | ||
skipRate: (0, utils_2.calculatePercentage)(0, apiTestResult.numTestsRun), | ||
testStartTime: (0, utils_1.formatStartTime)(startTime, 'ISO'), | ||
testExecutionTimeInMs: apiTestResult.totalTime ?? 0, | ||
testTotalTimeInMs: apiTestResult.totalTime ?? 0, | ||
commandTimeInMs: (0, utils_1.getCurrentTime)() - startTime, | ||
hostname: this.connection.instanceUrl, | ||
orgId: this.connection.getAuthInfoFields().orgId, | ||
username: this.connection.getUsername(), | ||
testRunId: '', | ||
userId: this.connection.getConnectionOptions().userId | ||
}, | ||
tests: testResults | ||
}; | ||
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(); | ||
} | ||
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; | ||
} | ||
return result; | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('synctests.formatSyncResults'); | ||
} | ||
} | ||
buildSyncTestResults(apiTestResult) { | ||
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}` | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('syncTests.buildSyncTestResults'); | ||
try { | ||
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}` | ||
}); | ||
}); | ||
}); | ||
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 } : {}) | ||
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 } : {}) | ||
}); | ||
}); | ||
}); | ||
return { apexTestClassIdSet, testResults }; | ||
return { apexTestClassIdSet, testResults }; | ||
} | ||
finally { | ||
utils_1.HeapMonitor.getInstance().checkHeapSize('syncTests.buildSyncTestResults'); | ||
} | ||
} | ||
@@ -163,10 +178,10 @@ } | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], SyncTests.prototype, "runTests", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], SyncTests.prototype, "formatSyncResults", null); | ||
__decorate([ | ||
(0, elapsedTime_1.elapsedTime)() | ||
(0, utils_1.elapsedTime)() | ||
], SyncTests.prototype, "buildSyncTestResults", null); | ||
//# sourceMappingURL=syncTests.js.map |
@@ -0,1 +1,2 @@ | ||
/// <reference types="node" /> | ||
import { Connection } from '@salesforce/core'; | ||
@@ -5,2 +6,3 @@ import { ApexTestProgressValue, AsyncTestArrayConfiguration, AsyncTestConfiguration, OutputDirConfig, SyncTestConfiguration, TestLevel, TestResult, TestRunIdResult, TestSuiteMembershipRecord } from './types'; | ||
import { AsyncTests } from './asyncTests'; | ||
import { Writable } from 'node:stream'; | ||
import { Duration } from '@salesforce/kit'; | ||
@@ -60,2 +62,3 @@ export declare class TestService { | ||
* @param token cancellation token | ||
* @param timeout | ||
*/ | ||
@@ -82,2 +85,4 @@ runTestAsynchronous(options: AsyncTestConfiguration | AsyncTestArrayConfiguration, codeCoverage?: boolean, immediatelyReturn?: boolean, progress?: Progress<ApexTestProgressValue>, token?: CancellationToken, timeout?: Duration): Promise<TestResult | TestRunIdResult>; | ||
private buildTestPayload; | ||
private runPipeline; | ||
createStream(filePath: string): Writable; | ||
} |
@@ -19,9 +19,10 @@ "use strict"; | ||
const promises_1 = require("node:fs/promises"); | ||
const node_fs_1 = require("node:fs"); | ||
const node_stream_1 = require("node:stream"); | ||
const promises_2 = require("node:stream/promises"); | ||
const streaming_1 = require("../streaming"); | ||
const codeCoverageStringifyStream_1 = require("../streaming/codeCoverageStringifyStream"); | ||
const utils_2 = require("../utils"); | ||
const narrowing_1 = require("../narrowing"); | ||
const promises_2 = require("node:stream/promises"); | ||
const node_fs_1 = require("node:fs"); | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const bfj = require('bfj'); | ||
class TestService { | ||
@@ -134,3 +135,9 @@ connection; | ||
async runTestSynchronous(options, codeCoverage = false, token) { | ||
return await this.syncService.runTests(options, codeCoverage, token); | ||
utils_2.HeapMonitor.getInstance().startMonitoring(); | ||
try { | ||
return await this.syncService.runTests(options, codeCoverage, token); | ||
} | ||
finally { | ||
utils_2.HeapMonitor.getInstance().stopMonitoring(); | ||
} | ||
} | ||
@@ -144,5 +151,12 @@ /** | ||
* @param token cancellation token | ||
* @param timeout | ||
*/ | ||
async runTestAsynchronous(options, codeCoverage = false, immediatelyReturn = false, progress, token, timeout) { | ||
return await this.asyncService.runTests(options, codeCoverage, immediatelyReturn, progress, token, timeout); | ||
utils_2.HeapMonitor.getInstance().startMonitoring(); | ||
try { | ||
return await this.asyncService.runTests(options, codeCoverage, immediatelyReturn, progress, token, timeout); | ||
} | ||
finally { | ||
utils_2.HeapMonitor.getInstance().stopMonitoring(); | ||
} | ||
} | ||
@@ -156,3 +170,9 @@ /** | ||
async reportAsyncResults(testRunId, codeCoverage = false, token) { | ||
return await this.asyncService.reportAsyncResults(testRunId, codeCoverage, token); | ||
utils_2.HeapMonitor.getInstance().startMonitoring(); | ||
try { | ||
return await this.asyncService.reportAsyncResults(testRunId, codeCoverage, token); | ||
} | ||
finally { | ||
utils_2.HeapMonitor.getInstance().stopMonitoring(); | ||
} | ||
} | ||
@@ -167,97 +187,87 @@ /** | ||
async writeResultFiles(result, outputDirConfig, codeCoverage = false) { | ||
const filesWritten = []; | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const { dirPath, resultFormats, fileInfos } = outputDirConfig; | ||
// ensure supplied result formats are support here | ||
if (resultFormats && | ||
!resultFormats.every((format) => format in types_1.ResultFormat)) { | ||
throw new Error(i18n_1.nls.localize('resultFormatErr')); | ||
} | ||
const testRunId = (0, narrowing_1.isTestResult)(result) | ||
? result.summary.testRunId | ||
: result.testRunId; | ||
const pipeThese = []; | ||
await (0, promises_1.mkdir)(dirPath, { recursive: true }); | ||
pipeThese.push([ | ||
node_stream_1.Readable.from([testRunId]), | ||
(0, node_fs_1.createWriteStream)((0, path_1.join)(dirPath, 'test-run-id.txt'), 'utf8') | ||
]); | ||
filesWritten.push((0, path_1.join)(dirPath, 'test-run-id.txt')); | ||
// produce result formats | ||
if (resultFormats) { | ||
if (!(0, narrowing_1.isTestResult)(result)) { | ||
throw new Error(i18n_1.nls.localize('runIdFormatErr')); | ||
utils_2.HeapMonitor.getInstance().startMonitoring(); | ||
utils_2.HeapMonitor.getInstance().checkHeapSize('testService.writeResultFiles'); | ||
try { | ||
const filesWritten = []; | ||
const { dirPath, resultFormats, fileInfos } = outputDirConfig; | ||
if (resultFormats && | ||
!resultFormats.every((format) => format in types_1.ResultFormat)) { | ||
throw new Error(i18n_1.nls.localize('resultFormatErr')); | ||
} | ||
for (const format of resultFormats) { | ||
switch (format) { | ||
case types_1.ResultFormat.json: | ||
// Create a readable stream from the JSON object | ||
const jsonFilePath = (0, path_1.join)(dirPath, testRunId ? `test-result-${testRunId}.json` : `test-result.json`); | ||
filesWritten.push(jsonFilePath); | ||
pipeThese.push([ | ||
streaming_1.TestResultStringifyStream.fromTestResult(result), | ||
(0, node_fs_1.createWriteStream)(jsonFilePath) | ||
]); | ||
break; | ||
case types_1.ResultFormat.tap: | ||
const tapFilePath = (0, path_1.join)(dirPath, `test-result-${testRunId}-tap.txt`); | ||
filesWritten.push(tapFilePath); | ||
pipeThese.push([ | ||
new reporters_1.TapFormatTransformer(result), | ||
(0, node_fs_1.createWriteStream)(tapFilePath) | ||
]); | ||
break; | ||
case types_1.ResultFormat.junit: | ||
const filePath = (0, path_1.join)(dirPath, testRunId | ||
? `test-result-${testRunId}-junit.xml` | ||
: `test-result-junit.xml`); | ||
filesWritten.push(filePath); | ||
pipeThese.push([ | ||
new reporters_1.JUnitFormatTransformer(result), | ||
(0, node_fs_1.createWriteStream)(filePath) | ||
]); | ||
break; | ||
await (0, promises_1.mkdir)(dirPath, { recursive: true }); | ||
const testRunId = (0, narrowing_1.isTestResult)(result) | ||
? result.summary.testRunId | ||
: result.testRunId; | ||
try { | ||
await (0, promises_1.writeFile)((0, path_1.join)(dirPath, 'test-run-id.txt'), testRunId); | ||
filesWritten.push((0, path_1.join)(dirPath, 'test-run-id.txt')); | ||
} | ||
catch (err) { | ||
console.error(`Error writing file: ${err}`); | ||
} | ||
if (resultFormats) { | ||
if (!(0, narrowing_1.isTestResult)(result)) { | ||
throw new Error(i18n_1.nls.localize('runIdFormatErr')); | ||
} | ||
for (const format of resultFormats) { | ||
let filePath; | ||
let readable; | ||
switch (format) { | ||
case types_1.ResultFormat.json: | ||
filePath = (0, path_1.join)(dirPath, `test-result-${testRunId || 'default'}.json`); | ||
readable = streaming_1.TestResultStringifyStream.fromTestResult(result, { | ||
bufferSize: (0, utils_1.getBufferSize)() | ||
}); | ||
break; | ||
case types_1.ResultFormat.tap: | ||
filePath = (0, path_1.join)(dirPath, `test-result-${testRunId}-tap.txt`); | ||
readable = new reporters_1.TapFormatTransformer(result, undefined, { | ||
bufferSize: (0, utils_1.getBufferSize)() | ||
}); | ||
break; | ||
case types_1.ResultFormat.junit: | ||
filePath = (0, path_1.join)(dirPath, `test-result-${testRunId || 'default'}-junit.xml`); | ||
readable = new reporters_1.JUnitFormatTransformer(result, { | ||
bufferSize: (0, utils_1.getBufferSize)() | ||
}); | ||
break; | ||
} | ||
if (filePath && readable) { | ||
filesWritten.push(await this.runPipeline(readable, filePath)); | ||
} | ||
} | ||
} | ||
} | ||
// produce code coverage | ||
if (codeCoverage) { | ||
if (!(0, narrowing_1.isTestResult)(result)) { | ||
throw new Error(i18n_1.nls.localize('covIdFormatErr')); | ||
if (codeCoverage) { | ||
if (!(0, narrowing_1.isTestResult)(result)) { | ||
throw new Error(i18n_1.nls.localize('covIdFormatErr')); | ||
} | ||
const filePath = (0, path_1.join)(dirPath, `test-result-${testRunId}-codecoverage.json`); | ||
const c = result.tests | ||
.map((record) => record.perClassCoverage) | ||
.filter((pcc) => pcc?.length); | ||
filesWritten.push(await this.runPipeline(bfj.stringify(c, { | ||
bufferLength: (0, utils_1.getBufferSize)(), | ||
iterables: 'ignore', | ||
space: (0, utils_1.getJsonIndent)() | ||
}), filePath)); | ||
} | ||
const filePath = (0, path_1.join)(dirPath, `test-result-${testRunId}-codecoverage.json`); | ||
const c = result.tests | ||
.map((record) => { | ||
return record.perClassCoverage; | ||
}) | ||
.filter((pcc) => pcc?.length); | ||
pipeThese.push([ | ||
node_stream_1.Readable.from(c), | ||
new codeCoverageStringifyStream_1.CodeCoverageStringifyStream(), | ||
(0, node_fs_1.createWriteStream)(filePath) | ||
]); | ||
filesWritten.push(filePath); | ||
if (fileInfos) { | ||
for (const fileInfo of fileInfos) { | ||
const filePath = (0, path_1.join)(dirPath, fileInfo.filename); | ||
const readable = typeof fileInfo.content === 'string' | ||
? node_stream_1.Readable.from([fileInfo.content]) | ||
: bfj.stringify(fileInfo.content, { | ||
bufferLength: (0, utils_1.getBufferSize)(), | ||
iterables: 'ignore', | ||
space: (0, utils_1.getJsonIndent)() | ||
}); | ||
filesWritten.push(await this.runPipeline(readable, filePath)); | ||
} | ||
} | ||
return filesWritten; | ||
} | ||
fileInfos?.forEach((fileInfo) => { | ||
const fileInfoPath = (0, path_1.join)(dirPath, fileInfo.filename); | ||
if (typeof fileInfo.content === 'string') { | ||
pipeThese.push([ | ||
node_stream_1.Readable.from([fileInfo.content]), | ||
(0, node_fs_1.createWriteStream)(fileInfoPath) | ||
]); | ||
} | ||
else { | ||
pipeThese.push([ | ||
streaming_1.JSONStringifyStream.from(fileInfo.content), | ||
(0, node_fs_1.createWriteStream)(fileInfoPath) | ||
]); | ||
} | ||
filesWritten.push(fileInfoPath); | ||
}); | ||
await Promise.all(pipeThese.map((streams) => (0, promises_2.pipeline)(streams))).catch((err) => { | ||
const error = new Error('An error occurred writing files'); | ||
error.stack = err.stack; | ||
throw error; | ||
}); | ||
return filesWritten; | ||
finally { | ||
utils_2.HeapMonitor.getInstance().checkHeapSize('testService.writeResultFiles'); | ||
utils_2.HeapMonitor.getInstance().stopMonitoring(); | ||
} | ||
} | ||
@@ -397,2 +407,15 @@ // utils to build test run payloads that may contain namespaces | ||
} | ||
async runPipeline(readable, filePath, transform) { | ||
const writable = this.createStream(filePath); | ||
if (transform) { | ||
await (0, promises_2.pipeline)(readable, transform, writable); | ||
} | ||
else { | ||
await (0, promises_2.pipeline)(readable, writable); | ||
} | ||
return filePath; | ||
} | ||
createStream(filePath) { | ||
return (0, node_fs_1.createWriteStream)(filePath, 'utf8'); | ||
} | ||
} | ||
@@ -399,0 +422,0 @@ exports.TestService = TestService; |
@@ -8,1 +8,4 @@ import { Connection } from '@salesforce/core'; | ||
export declare const queryAll: <R>(connection: Connection, query: string, tooling?: boolean) => Promise<QueryResult<R>>; | ||
export declare const getJsonIndent: () => number | undefined; | ||
export declare const getBufferSize: () => number; | ||
export declare const resetLimitsForTesting: () => void; |
@@ -9,3 +9,12 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.queryAll = exports.queryNamespaces = exports.stringify = exports.calculatePercentage = void 0; | ||
exports.resetLimitsForTesting = exports.getBufferSize = exports.getJsonIndent = exports.queryAll = exports.queryNamespaces = exports.stringify = exports.calculatePercentage = void 0; | ||
const core_1 = require("@salesforce/core"); | ||
const DEFAULT_BUFFER_SIZE = 256; | ||
const MIN_BUFFER_SIZE = 256; | ||
const MAX_BUFFER_SIZE = 32_768; | ||
const DEFAULT_JSON_INDENT = undefined; | ||
const MIN_JSON_INDENT = 0; | ||
const MAX_JSON_INDENT = 8; | ||
let jsonIndent = null; | ||
let bufferSize = null; | ||
function calculatePercentage(dividend, divisor) { | ||
@@ -55,2 +64,45 @@ let percentage = '0%'; | ||
exports.queryAll = queryAll; | ||
const getJsonIndent = () => { | ||
if (jsonIndent !== null) { | ||
return jsonIndent; | ||
} | ||
let jsonIndentNum = DEFAULT_JSON_INDENT; | ||
const envJsonIndent = process.env.SF_APEX_RESULTS_JSON_INDENT; | ||
if (envJsonIndent && Number.isInteger(Number(envJsonIndent))) { | ||
jsonIndentNum = Number(envJsonIndent); | ||
} | ||
if (jsonIndentNum < MIN_JSON_INDENT || jsonIndentNum > MAX_JSON_INDENT) { | ||
const logger = core_1.Logger.childFromRoot('utils'); | ||
logger.warn(`Json indent ${jsonIndentNum} is outside of the valid range (${MIN_JSON_INDENT}-${MAX_JSON_INDENT}). Using default json indent of ${DEFAULT_JSON_INDENT}.`); | ||
jsonIndentNum = DEFAULT_JSON_INDENT; | ||
} | ||
jsonIndent = jsonIndentNum; | ||
return jsonIndent; | ||
}; | ||
exports.getJsonIndent = getJsonIndent; | ||
const getBufferSize = () => { | ||
if (bufferSize !== null) { | ||
return bufferSize; | ||
} | ||
let bufferSizeNum = DEFAULT_BUFFER_SIZE; | ||
const jsonBufferSize = process.env.SF_APEX_JSON_BUFFER_SIZE; | ||
if (jsonBufferSize && Number.isInteger(Number(jsonBufferSize))) { | ||
bufferSizeNum = Number(jsonBufferSize); | ||
} | ||
if (bufferSizeNum < MIN_BUFFER_SIZE || bufferSizeNum > MAX_BUFFER_SIZE) { | ||
const logger = core_1.Logger.childFromRoot('utils'); | ||
logger.warn(`Buffer size ${bufferSizeNum} is outside of the valid range (${MIN_BUFFER_SIZE}-${MAX_BUFFER_SIZE}). Using default buffer size of ${DEFAULT_BUFFER_SIZE}.`); | ||
bufferSizeNum = DEFAULT_BUFFER_SIZE; | ||
} | ||
bufferSize = bufferSizeNum; | ||
JSON.stringify(bufferSize); | ||
return bufferSize; | ||
}; | ||
exports.getBufferSize = getBufferSize; | ||
// exported for testing | ||
const resetLimitsForTesting = () => { | ||
bufferSize = null; | ||
jsonIndent = null; | ||
}; | ||
exports.resetLimitsForTesting = resetLimitsForTesting; | ||
//# sourceMappingURL=utils.js.map |
@@ -7,1 +7,2 @@ export { createFile } from './fileSystemHandler'; | ||
export { elapsedTime } from './elapsedTime'; | ||
export { HeapMonitor } from './heapMonitor'; |
@@ -9,3 +9,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.elapsedTime = exports.refreshAuth = exports.msToSecond = exports.formatStartTime = exports.getCurrentTime = exports.Table = exports.createFile = void 0; | ||
exports.HeapMonitor = exports.elapsedTime = exports.refreshAuth = exports.msToSecond = exports.formatStartTime = exports.getCurrentTime = exports.Table = exports.createFile = void 0; | ||
var fileSystemHandler_1 = require("./fileSystemHandler"); | ||
@@ -23,2 +23,4 @@ Object.defineProperty(exports, "createFile", { enumerable: true, get: function () { return fileSystemHandler_1.createFile; } }); | ||
Object.defineProperty(exports, "elapsedTime", { enumerable: true, get: function () { return elapsedTime_1.elapsedTime; } }); | ||
var heapMonitor_1 = require("./heapMonitor"); | ||
Object.defineProperty(exports, "HeapMonitor", { enumerable: true, get: function () { return heapMonitor_1.HeapMonitor; } }); | ||
//# sourceMappingURL=index.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
@@ -8,2 +24,9 @@ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -13,2 +36,3 @@ exports.TableWriteableStream = void 0; | ||
const core_1 = require("@salesforce/core"); | ||
const os = __importStar(require("node:os")); | ||
const COLUMN_SEPARATOR = ' '; | ||
@@ -42,3 +66,3 @@ const COLUMN_FILLER = ' '; | ||
if (columnHeader && headerSeparator) { | ||
this.stream.push(`${title ? `=== ${title}\n` : ''}${columnHeader}\n${headerSeparator}\n`); | ||
this.stream.push(`${title ? `=== ${title}${os.EOL}` : ''}${columnHeader}${os.EOL}${headerSeparator}${os.EOL}`); | ||
} | ||
@@ -51,3 +75,3 @@ rows.forEach((row) => { | ||
const rowWidth = outputRow.length; | ||
cell.split('\n').forEach((line, lineIndex) => { | ||
cell.split(os.EOL).forEach((line, lineIndex) => { | ||
const cellWidth = maxColWidths.get(col.key); | ||
@@ -60,3 +84,3 @@ if (cellWidth) { | ||
outputRow += | ||
'\n' + | ||
os.EOL + | ||
this.fillColumn('', rowWidth, COLUMN_FILLER, true) + | ||
@@ -68,3 +92,7 @@ this.fillColumn(line, cellWidth, COLUMN_FILLER, isLastCol); | ||
}); | ||
this.stream.push(outputRow + '\n'); | ||
this.stream.push(outputRow + os.EOL); | ||
// this call to setImmediate will schedule the closure on the event loop | ||
// this action causing the current code to yield to the event loop | ||
// allowing other processes to get time on the event loop | ||
setImmediate(() => { }); | ||
}); | ||
@@ -87,3 +115,3 @@ } | ||
const longestLineWidth = cell | ||
.split('\n') | ||
.split(os.EOL) | ||
.reduce((maxLine, line) => line.length > maxLine.length ? line : maxLine).length; | ||
@@ -90,0 +118,0 @@ if (longestLineWidth > maxColWidth) { |
{ | ||
"name": "@salesforce/apex-node", | ||
"description": "Salesforce JS library for Apex", | ||
"version": "6.0.1", | ||
"version": "6.1.0", | ||
"author": "Salesforce", | ||
@@ -10,10 +10,11 @@ "bugs": "https://github.com/forcedotcom/salesforcedx-apex/issues", | ||
"@jsforce/jsforce-node": "^3.2.0", | ||
"@salesforce/core": "^7.3.9", | ||
"@salesforce/core": "^7.3.10", | ||
"@salesforce/kit": "^3.1.2", | ||
"@types/istanbul-reports": "^3.0.4", | ||
"bfj": "^8.0.0", | ||
"faye": "1.4.0", | ||
"glob": "^10.3.10", | ||
"glob": "^10.3.16", | ||
"istanbul-lib-coverage": "^3.2.2", | ||
"istanbul-lib-report": "^3.0.1", | ||
"istanbul-reports": "^3.1.6" | ||
"istanbul-reports": "^3.1.7" | ||
}, | ||
@@ -24,9 +25,9 @@ "devDependencies": { | ||
"@salesforce/ts-types": "^2.0.9", | ||
"@types/chai": "^4.3.10", | ||
"@types/chai": "^4.3.16", | ||
"@types/glob": "^8.1.0", | ||
"@types/istanbul-lib-coverage": "^2.0.6", | ||
"@types/istanbul-lib-report": "^3.0.3", | ||
"@types/mocha": "^10.0.4", | ||
"@types/mocha": "^10.0.6", | ||
"@types/node": "^18", | ||
"@types/sinon": "^17.0.1", | ||
"@types/sinon": "^17.0.3", | ||
"@typescript-eslint/eslint-plugin": "^6.10.0", | ||
@@ -41,14 +42,14 @@ "@typescript-eslint/parser": "^6.10.0", | ||
"eslint-plugin-jsdoc": "^46.8.2", | ||
"eslint-plugin-prettier": "^5.0.1", | ||
"eslint-plugin-prettier": "^5.1.3", | ||
"husky": "^8.0.0", | ||
"lint-staged": "^15.0.2", | ||
"mocha": "^10.2.0", | ||
"lint-staged": "^15.2.4", | ||
"mocha": "^10.4.0", | ||
"mocha-junit-reporter": "^2.2.1", | ||
"nyc": "^15.1.0", | ||
"prettier": "^3.0.3", | ||
"prettier": "^3.2.5", | ||
"shx": "^0.3.4", | ||
"sinon": "^17.0.1", | ||
"source-map-support": "^0.5.16", | ||
"ts-node": "^10.7.0", | ||
"typescript": "^5.2.2" | ||
"ts-node": "^10.9.2", | ||
"typescript": "^5.4.5" | ||
}, | ||
@@ -55,0 +56,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
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
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances 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
410360
6463
10
150
7
+ Addedbfj@^8.0.0
+ Addedbfj@8.0.0(transitive)
+ Addedbluebird@3.7.2(transitive)
+ Addedcheck-types@11.2.3(transitive)
+ Addeddeep-is@0.1.4(transitive)
+ Addedescodegen@1.14.3(transitive)
+ Addedesprima@1.2.24.0.1(transitive)
+ Addedestraverse@4.3.0(transitive)
+ Addedesutils@2.0.3(transitive)
+ Addedfast-levenshtein@2.0.6(transitive)
+ Addedhoopy@0.1.4(transitive)
+ Addedjsonpath@1.1.1(transitive)
+ Addedlevn@0.3.0(transitive)
+ Addedoptionator@0.8.3(transitive)
+ Addedprelude-ls@1.1.2(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedstatic-eval@2.0.2(transitive)
+ Addedtryer@1.0.1(transitive)
+ Addedtype-check@0.3.2(transitive)
+ Addedunderscore@1.12.1(transitive)
+ Addedword-wrap@1.2.5(transitive)
Updated@salesforce/core@^7.3.10
Updatedglob@^10.3.16
Updatedistanbul-reports@^3.1.7