use super::expression::Expression; use super::shell::{Bash, Fish, PowerShell, Shell, WinCmd, Zsh}; use indoc::writedoc; use std::fmt::Write; #[derive(Debug)] pub(crate) struct ExpectCommandOutput<S: Shell, Command: Expression<S>> { _shell: std::marker::PhantomData<S>, command: Command, expected_output: &'static str, message: &'static str, } impl<S: Shell, Command: Expression<S>> ExpectCommandOutput<S, Command> { pub(crate) fn new( command: Command, expected_output: &'static str, message: &'static str, ) -> Self { Self { _shell: std::marker::PhantomData, command, expected_output, message, } } } impl<E: Expression<Bash>> Expression<Bash> for ExpectCommandOutput<Bash, E> { fn write_shell(&self, writer: &mut impl Write) -> std::fmt::Result { let mut command = String::new(); self.command.write_shell(&mut command)?; writedoc!( writer, r#" if [ "$({command})" != "{expected_output}" ]; then echo 'Expected {message} to be {expected_output:?}, Got: '"$({command})" exit 1 fi "#, command = command, message = self.message, expected_output = self.expected_output, ) } } impl<E: Expression<Zsh>> Expression<Zsh> for ExpectCommandOutput<Zsh, E> { fn write_shell(&self, writer: &mut impl Write) -> std::fmt::Result { let mut command = String::new(); self.command.write_shell(&mut command)?; writedoc!( writer, r#" if [ "$({command})" != "{expected_output}" ]; then echo 'Expected {message} to be {expected_output:?}, Got: '"$({command})" exit 1 fi "#, command = command, message = self.message, expected_output = self.expected_output, ) } } impl<E: Expression<Fish>> Expression<Fish> for ExpectCommandOutput<Fish, E> { fn write_shell(&self, writer: &mut impl Write) -> std::fmt::Result { let mut command = String::new(); self.command.write_shell(&mut command)?; writedoc!( writer, r#" if test ({command}) != "{expected_output}" echo 'Expected {message} to be {expected_output:?}, Got: '({command}) exit 1 end "#, command = command, expected_output = self.expected_output, message = self.message, ) } } impl<E: Expression<PowerShell>> Expression<PowerShell> for ExpectCommandOutput<PowerShell, E> { fn write_shell(&self, writer: &mut impl Write) -> std::fmt::Result { let mut command = String::new(); self.command.write_shell(&mut command)?; writedoc!( writer, r#" If ("$({command})" -ne "{expected_output}") {{ Write-Output ('Expected {message} to be {expected_output:?}, Got: ' + $({command})) exit 1 }} "#, command = command, expected_output = self.expected_output, message = self.message, ) } } impl<E: Expression<WinCmd>> Expression<WinCmd> for ExpectCommandOutput<WinCmd, E> { fn write_shell(&self, writer: &mut impl Write) -> std::fmt::Result { let mut command = String::new(); self.command.write_shell(&mut command)?; writedoc!( writer, r#" {command} | findstr {expected_output} if %errorlevel% neq 0 ( echo {message} does not match {expected_output:?} exit 1 ) "#, command = command, expected_output = WinCmd::shell_escape(self.expected_output), message = self.message, ) } }