From f7efa2edde9b1a33e8a0d1ce8f6cdd208bf181e9 Mon Sep 17 00:00:00 2001 From: Viccodes11 Date: Sat, 17 Oct 2026 16:30:56 +0100 Subject: [PATCH] refactor(diagnostics): normalize Rust and Cargo remediation guidance Make rustc and Cargo remediation guidance independently actionable, preserve failure severity for missing and malformed states, and prevent raw stderr or process error details from being reflected. Closes #128 --- src/diagnostics/rust.ts | 5 +-- tests/rust-diagnostics.test.ts | 74 ++++++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/src/diagnostics/rust.ts b/src/diagnostics/rust.ts index b271bcc..8393c0d 100644 --- a/src/diagnostics/rust.ts +++ b/src/diagnostics/rust.ts @@ -84,8 +84,7 @@ export function createCargoDiagnostic( label: 'Cargo', status: 'fail', message: 'Cargo is unavailable or could not be executed.', - remediation: - 'Install Cargo with the Rust toolchain and ensure `cargo` is available on PATH.', + remediation: 'Install Cargo and ensure `cargo` is available on PATH.', }; } @@ -98,7 +97,7 @@ export function createCargoDiagnostic( status: 'fail', message: 'Cargo returned an unrecognized version.', remediation: - 'Verify `cargo --version` works and reinstall Rust if necessary.', + 'Verify `cargo --version` works and reinstall Cargo if necessary.', }; } diff --git a/tests/rust-diagnostics.test.ts b/tests/rust-diagnostics.test.ts index 6924282..0fe1b7f 100644 --- a/tests/rust-diagnostics.test.ts +++ b/tests/rust-diagnostics.test.ts @@ -37,7 +37,9 @@ describe('Rust diagnostic', () => { const diagnostic = createRustDiagnostic(execute).run(); expect(diagnostic.status).toBe('fail'); - expect(diagnostic.remediation).toContain('>=1.84.0'); + expect(diagnostic.remediation).toBe( + 'Upgrade to Rust >=1.84.0 before building Stellar smart contracts.', + ); }); it('fails when rustc is unavailable without leaking process details', () => { @@ -55,16 +57,24 @@ describe('Rust diagnostic', () => { expect(diagnostic.message).toBe( 'Rust is unavailable or could not be executed.', ); + expect(diagnostic.remediation).toBe( + 'Install Rust >=1.84.0 and ensure `rustc` is available on PATH.', + ); expect(JSON.stringify(diagnostic)).not.toContain('SECRET_TOKEN'); }); - it('fails malformed rustc output', () => { - const execute: RunCommand = () => result(0, 'rustc unknown\n'); + it('fails malformed rustc output without leaking stderr or process details', () => { + const execute: RunCommand = () => + result(0, 'rustc unknown\n', 'SECRET_TOKEN=do-not-render'); const diagnostic = createRustDiagnostic(execute).run(); expect(diagnostic.status).toBe('fail'); expect(diagnostic.message).toBe('Rust returned an unrecognized version.'); + expect(diagnostic.remediation).toBe( + 'Verify `rustc --version` works and reinstall Rust if necessary.', + ); + expect(JSON.stringify(diagnostic)).not.toContain('SECRET_TOKEN'); }); }); @@ -83,22 +93,70 @@ describe('Cargo diagnostic', () => { expect(diagnostic.message).toContain('1.89.0'); }); - it('fails when Cargo is unavailable without affecting Rust checks', () => { + it('fails when Cargo is unavailable without leaking process details', () => { const execute: RunCommand = () => - result(null, '', '', new Error('spawn cargo ENOENT')); + result( + null, + '', + 'SECRET_TOKEN=do-not-render', + new Error('spawn cargo ENOENT SECRET_TOKEN=do-not-render'), + ); const diagnostic = createCargoDiagnostic(execute).run(); expect(diagnostic.status).toBe('fail'); - expect(diagnostic.remediation).toContain('cargo'); + expect(diagnostic.message).toBe( + 'Cargo is unavailable or could not be executed.', + ); + expect(diagnostic.remediation).toBe( + 'Install Cargo and ensure `cargo` is available on PATH.', + ); + expect(JSON.stringify(diagnostic)).not.toContain('SECRET_TOKEN'); }); - it('fails malformed Cargo output', () => { - const execute: RunCommand = () => result(0, 'cargo unknown\n'); + it('fails malformed Cargo output without leaking stderr or process details', () => { + const execute: RunCommand = () => + result(0, 'cargo unknown\n', 'SECRET_TOKEN=do-not-render'); const diagnostic = createCargoDiagnostic(execute).run(); expect(diagnostic.status).toBe('fail'); expect(diagnostic.message).toBe('Cargo returned an unrecognized version.'); + expect(diagnostic.remediation).toBe( + 'Verify `cargo --version` works and reinstall Cargo if necessary.', + ); + expect(JSON.stringify(diagnostic)).not.toContain('SECRET_TOKEN'); + }); + + it('provides independently actionable guidance when rustc fails and cargo passes', () => { + const rustExecute: RunCommand = () => + result(null, '', '', new Error('spawn rustc ENOENT')); + const cargoExecute: RunCommand = () => + result(0, 'cargo 1.89.0 (c24e10642 2025-06-23)\n'); + + const rustDiag = createRustDiagnostic(rustExecute).run(); + const cargoDiag = createCargoDiagnostic(cargoExecute).run(); + + expect(rustDiag.status).toBe('fail'); + expect(rustDiag.remediation).toBe( + 'Install Rust >=1.84.0 and ensure `rustc` is available on PATH.', + ); + expect(cargoDiag.status).toBe('pass'); + }); + + it('provides independently actionable guidance when cargo fails and rustc passes', () => { + const rustExecute: RunCommand = () => + result(0, 'rustc 1.84.0 (9fc6b4312 2025-01-07)\n'); + const cargoExecute: RunCommand = () => + result(null, '', '', new Error('spawn cargo ENOENT')); + + const rustDiag = createRustDiagnostic(rustExecute).run(); + const cargoDiag = createCargoDiagnostic(cargoExecute).run(); + + expect(rustDiag.status).toBe('pass'); + expect(cargoDiag.status).toBe('fail'); + expect(cargoDiag.remediation).toBe( + 'Install Cargo and ensure `cargo` is available on PATH.', + ); }); });