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.', + ); }); });