Skip to content

Commit

Permalink
feat: show test failures while polling for status
Browse files Browse the repository at this point in the history
  • Loading branch information
cristiand391 committed Nov 27, 2024
1 parent dcd59c2 commit d95f0a3
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 6 deletions.
6 changes: 4 additions & 2 deletions src/formatters/testResultsFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
Successes,
} from '@salesforce/source-deploy-retrieve';
import { ensureArray } from '@salesforce/kit';
import { TestLevel, Verbosity } from '../utils/types.js';
import { isTruthy, TestLevel, Verbosity } from '../utils/types.js';
import { tableHeader, error, success, check } from '../utils/output.js';
import { coverageOutput } from '../utils/coverage.js';

Expand All @@ -45,7 +45,9 @@ export class TestResultsFormatter {
return;
}

displayVerboseTestFailures(this.result.response);
if (!isTruthy(process.env.CI)) {
displayVerboseTestFailures(this.result.response);
}

if (this.verbosity === 'verbose') {
displayVerboseTestSuccesses(this.result.response.details.runTestResult?.successes);
Expand Down
42 changes: 38 additions & 4 deletions src/utils/deployStages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@
* 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
*/
import os from 'node:os';
import { MultiStageOutput } from '@oclif/multi-stage-output';
import { Lifecycle, Messages } from '@salesforce/core';
import { MetadataApiDeploy, MetadataApiDeployStatus, RequestStatus } from '@salesforce/source-deploy-retrieve';
import {
Failures,
MetadataApiDeploy,
MetadataApiDeployStatus,
RequestStatus,
Successes,
} from '@salesforce/source-deploy-retrieve';
import { SourceMemberPollingEvent } from '@salesforce/source-tracking';
import terminalLink from 'terminal-link';
import { ensureArray } from '@salesforce/kit';
import ansis from 'ansis';
import { getZipFileSize } from './output.js';
import { isTruthy } from './types.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const mdTransferMessages = Messages.loadMessages('@salesforce/plugin-deploy-retrieve', 'metadata.transfer');
Expand Down Expand Up @@ -129,7 +139,7 @@ export class DeployStages {
type: 'dynamic-key-value',
},
{
label: 'Completed',
label: 'Successful',
get: (data): string | undefined =>
data?.mdapiDeploy?.numberTestsTotal && data?.mdapiDeploy?.numberTestsCompleted
? formatProgress(data?.mdapiDeploy?.numberTestsCompleted, data?.mdapiDeploy?.numberTestsTotal)
Expand All @@ -138,10 +148,11 @@ export class DeployStages {
type: 'dynamic-key-value',
},
{
label: 'Failures',
label: 'Failed',
get: (data): string | undefined =>
data?.mdapiDeploy?.numberTestsTotal && data?.mdapiDeploy?.numberTestErrors
? formatProgress(data?.mdapiDeploy?.numberTestErrors, data?.mdapiDeploy?.numberTestsTotal)
? formatProgress(data?.mdapiDeploy?.numberTestErrors, data?.mdapiDeploy?.numberTestsTotal) +
(isTruthy(process.env.CI) ? os.EOL + formatTestFailures(data) : '')
: undefined,
stage: 'Running Tests',
type: 'dynamic-key-value',
Expand Down Expand Up @@ -241,3 +252,26 @@ export class DeployStages {
this.mso.skipTo('Done', data);
}
}

function formatTestFailures(data: Data): string {
if (data.mdapiDeploy.details.runTestResult?.failures === undefined) return '';
const failures = ensureArray(data.mdapiDeploy.details.runTestResult?.failures).sort(testResultSort);

let output = '';

for (const test of failures) {
const testName = ansis.underline(`${test.name}.${test.methodName}`);
output += ` • ${testName}${os.EOL}`;
output += ` message: ${test.message}${os.EOL}`;
if (test.stackTrace) {
const stackTrace = test.stackTrace.replace(/\n/g, `${os.EOL} `);
output += ` stacktrace:${os.EOL} ${stackTrace}${os.EOL}${os.EOL}`;
}
}

// remove last EOL char
return output.slice(0, -1);
}

const testResultSort = <T extends Successes | Failures>(a: T, b: T): number =>
a.methodName === b.methodName ? a.name.localeCompare(b.name) : a.methodName.localeCompare(b.methodName);
4 changes: 4 additions & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,7 @@ export const isFileResponseDeleted = (fileResponse: FileResponseSuccess): boolea
fileResponse.state === ComponentStatus.Deleted;

export const isDefined = <T>(value?: T): value is T => value !== undefined;

export function isTruthy(value: string | undefined): boolean {
return value !== '0' && value !== 'false';
}

0 comments on commit d95f0a3

Please sign in to comment.