44 * Licensed under the BSD 3-Clause license.
55 * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66 */
7+ import os from 'node:os' ;
78import { MultiStageOutput } from '@oclif/multi-stage-output' ;
89import { Lifecycle , Messages } from '@salesforce/core' ;
9- import { MetadataApiDeploy , MetadataApiDeployStatus , RequestStatus } from '@salesforce/source-deploy-retrieve' ;
10+ import {
11+ Failures ,
12+ MetadataApiDeploy ,
13+ MetadataApiDeployStatus ,
14+ RequestStatus ,
15+ Successes ,
16+ } from '@salesforce/source-deploy-retrieve' ;
1017import { SourceMemberPollingEvent } from '@salesforce/source-tracking' ;
1118import terminalLink from 'terminal-link' ;
19+ import { ensureArray } from '@salesforce/kit' ;
20+ import ansis from 'ansis' ;
1221import { getZipFileSize } from './output.js' ;
22+ import { isTruthy } from './types.js' ;
1323
1424Messages . importMessagesDirectoryFromMetaUrl ( import . meta. url ) ;
1525const mdTransferMessages = Messages . loadMessages ( '@salesforce/plugin-deploy-retrieve' , 'metadata.transfer' ) ;
@@ -129,7 +139,7 @@ export class DeployStages {
129139 type : 'dynamic-key-value' ,
130140 } ,
131141 {
132- label : 'Completed ' ,
142+ label : 'Successful ' ,
133143 get : ( data ) : string | undefined =>
134144 data ?. mdapiDeploy ?. numberTestsTotal && data ?. mdapiDeploy ?. numberTestsCompleted
135145 ? formatProgress ( data ?. mdapiDeploy ?. numberTestsCompleted , data ?. mdapiDeploy ?. numberTestsTotal )
@@ -138,10 +148,11 @@ export class DeployStages {
138148 type : 'dynamic-key-value' ,
139149 } ,
140150 {
141- label : 'Failures ' ,
151+ label : 'Failed ' ,
142152 get : ( data ) : string | undefined =>
143153 data ?. mdapiDeploy ?. numberTestsTotal && data ?. mdapiDeploy ?. numberTestErrors
144- ? formatProgress ( data ?. mdapiDeploy ?. numberTestErrors , data ?. mdapiDeploy ?. numberTestsTotal )
154+ ? formatProgress ( data ?. mdapiDeploy ?. numberTestErrors , data ?. mdapiDeploy ?. numberTestsTotal ) +
155+ ( isTruthy ( process . env . CI ) ? os . EOL + formatTestFailures ( data ) : '' )
145156 : undefined ,
146157 stage : 'Running Tests' ,
147158 type : 'dynamic-key-value' ,
@@ -241,3 +252,26 @@ export class DeployStages {
241252 this . mso . skipTo ( 'Done' , data ) ;
242253 }
243254}
255+
256+ function formatTestFailures ( data : Data ) : string {
257+ if ( data . mdapiDeploy . details . runTestResult ?. failures === undefined ) return '' ;
258+ const failures = ensureArray ( data . mdapiDeploy . details . runTestResult ?. failures ) . sort ( testResultSort ) ;
259+
260+ let output = '' ;
261+
262+ for ( const test of failures ) {
263+ const testName = ansis . underline ( `${ test . name } .${ test . methodName } ` ) ;
264+ output += ` • ${ testName } ${ os . EOL } ` ;
265+ output += ` message: ${ test . message } ${ os . EOL } ` ;
266+ if ( test . stackTrace ) {
267+ const stackTrace = test . stackTrace . replace ( / \n / g, `${ os . EOL } ` ) ;
268+ output += ` stacktrace:${ os . EOL } ${ stackTrace } ${ os . EOL } ${ os . EOL } ` ;
269+ }
270+ }
271+
272+ // remove last EOL char
273+ return output . slice ( 0 , - 1 ) ;
274+ }
275+
276+ const testResultSort = < T extends Successes | Failures > ( a : T , b : T ) : number =>
277+ a . methodName === b . methodName ? a . name . localeCompare ( b . name ) : a . methodName . localeCompare ( b . methodName ) ;
0 commit comments