]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
feat(cli): display failure reasons in human-readable table output
authorJérôme Benoit <jerome.benoit@sap.com>
Wed, 15 Apr 2026 17:53:08 +0000 (19:53 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Wed, 15 Apr 2026 17:53:08 +0000 (19:53 +0200)
ui/cli/src/output/table.ts
ui/cli/tests/output.test.ts
ui/common/src/types/UIProtocol.ts

index 4ce7280867031719af2b21418a5a31a938de0f02..b6b13e73f819a1cb0ef2ce725bd4534cbc13a2db 100644 (file)
@@ -17,11 +17,19 @@ export const outputTable = (payload: ResponsePayload): void => {
 
   if (payload.hashIdsFailed != null && payload.hashIdsFailed.length > 0) {
     process.stderr.write(chalk.red(`✗ Failed (${payload.hashIdsFailed.length.toString()}):\n`))
-    const table = new Table({ head: [chalk.white('Hash ID')] })
-    for (const id of payload.hashIdsFailed) {
-      table.push([id])
+    if (payload.responsesFailed != null && payload.responsesFailed.length > 0) {
+      const table = new Table({ head: [chalk.white('Hash ID'), chalk.white('Error')] })
+      for (const entry of payload.responsesFailed) {
+        table.push([entry.hashId ?? '(unknown)', entry.errorMessage ?? 'Unknown error'])
+      }
+      process.stderr.write(table.toString() + '\n')
+    } else {
+      const table = new Table({ head: [chalk.white('Hash ID')] })
+      for (const id of payload.hashIdsFailed) {
+        table.push([id])
+      }
+      process.stderr.write(table.toString() + '\n')
     }
-    process.stderr.write(table.toString() + '\n')
   }
 
   if (
index e70fcf2edcb8b0136813e61e5d00113d883a4f26..fa2d787970089291c4a0cd9df2e70fe4e73b1087 100644 (file)
@@ -165,4 +165,76 @@ await describe('output formatters', async () => {
     })
     assert.ok(output.includes('table err'))
   })
+
+  await it('should display responsesFailed with errorMessage in two-column table', () => {
+    const payload = {
+      hashIdsFailed: ['cs-001'],
+      responsesFailed: [
+        {
+          command: 'startChargingStation',
+          errorMessage: 'Station not found',
+          hashId: 'cs-001',
+          status: ResponseStatus.FAILURE,
+        },
+      ],
+      status: ResponseStatus.FAILURE,
+    }
+    const output = captureStderr(() => {
+      outputTable(payload)
+    })
+    assert.ok(output.includes('Station not found'))
+    assert.ok(output.includes('cs-001'))
+    assert.ok(output.includes('Error'))
+  })
+
+  await it('should display responsesFailed with missing errorMessage as Unknown error', () => {
+    const payload = {
+      hashIdsFailed: ['cs-002'],
+      responsesFailed: [
+        {
+          command: 'stopChargingStation',
+          hashId: 'cs-002',
+          status: ResponseStatus.FAILURE,
+        },
+      ],
+      status: ResponseStatus.FAILURE,
+    }
+    const output = captureStderr(() => {
+      outputTable(payload)
+    })
+    assert.ok(output.includes('Unknown error'))
+    assert.ok(output.includes('cs-002'))
+  })
+
+  await it('should display responsesFailed with undefined hashId as (unknown)', () => {
+    const payload = {
+      hashIdsFailed: ['cs-003'],
+      responsesFailed: [
+        {
+          command: 'openConnection',
+          errorMessage: 'Timeout',
+          hashId: undefined,
+          status: ResponseStatus.FAILURE,
+        },
+      ],
+      status: ResponseStatus.FAILURE,
+    }
+    const output = captureStderr(() => {
+      outputTable(payload)
+    })
+    assert.ok(output.includes('(unknown)'))
+    assert.ok(output.includes('Timeout'))
+  })
+
+  await it('should display hashIdsFailed without responsesFailed as single-column table', () => {
+    const payload = {
+      hashIdsFailed: ['cs-001'],
+      status: ResponseStatus.FAILURE,
+    }
+    const output = captureStderr(() => {
+      outputTable(payload)
+    })
+    assert.ok(output.includes('cs-001'))
+    assert.ok(!output.includes('Error'))
+  })
 })
index 901573e7d7c941a62cb55a76fbb4afde10bf7a92..6fb1e547be3fc1b5dacaf216e4dc686e8c0b5519 100644 (file)
@@ -57,6 +57,8 @@ export enum ServerNotification {
 }
 
 export interface BroadcastChannelResponsePayload extends JsonObject {
+  command?: string
+  errorMessage?: string
   hashId: string | undefined
   status: ResponseStatus
 }