mirror of
https://github.com/alexpasmantier/television.git
synced 2025-07-28 13:51:41 +00:00
test(e2e): add e2e tests for secondary cli commands (version, init, list-channels, ...)
This commit is contained in:
parent
bc8d636005
commit
8d822cd2fc
63
Cargo.lock
generated
63
Cargo.lock
generated
@ -159,6 +159,12 @@ dependencies = [
|
||||
"console",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.0"
|
||||
@ -341,6 +347,12 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "comma"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335"
|
||||
|
||||
[[package]]
|
||||
name = "compact_str"
|
||||
version = "0.8.1"
|
||||
@ -461,7 +473,7 @@ version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.9.0",
|
||||
"crossterm_winapi",
|
||||
"filedescriptor",
|
||||
"mio",
|
||||
@ -963,7 +975,7 @@ version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.9.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -1019,6 +1031,15 @@ version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
@ -1046,6 +1067,20 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bitflags 1.2.1",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset",
|
||||
"pin-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@ -1290,7 +1325,7 @@ version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.9.0",
|
||||
"cassowary",
|
||||
"compact_str",
|
||||
"crossterm",
|
||||
@ -1332,7 +1367,7 @@ version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1396,6 +1431,19 @@ version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "rexpect"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01ff60778f96fb5a48adbe421d21bf6578ed58c0872d712e7e08593c195adff8"
|
||||
dependencies = [
|
||||
"comma",
|
||||
"nix",
|
||||
"regex",
|
||||
"tempfile",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
@ -1434,7 +1482,7 @@ version = "0.38.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.9.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
@ -1447,7 +1495,7 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.9.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.4",
|
||||
@ -1742,6 +1790,7 @@ dependencies = [
|
||||
"nucleo",
|
||||
"parking_lot",
|
||||
"ratatui",
|
||||
"rexpect",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -2378,7 +2427,7 @@ version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -75,6 +75,7 @@ clipboard-win = "5.4.0"
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.5", features = ["async_tokio"] }
|
||||
tempfile = "3.16.0"
|
||||
rexpect = "0.5"
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
|
@ -10,7 +10,6 @@ use walkdir::WalkDir;
|
||||
|
||||
use crate::{
|
||||
channels::prototypes::ChannelPrototype, cli::unknown_channel_exit,
|
||||
config::get_config_dir,
|
||||
};
|
||||
|
||||
/// A neat `HashMap` of channel prototypes indexed by their name.
|
||||
@ -129,16 +128,13 @@ where
|
||||
/// ├── channel_2.toml
|
||||
/// └── ...
|
||||
/// ```
|
||||
pub fn load_cable<P>(cable_dir: Option<P>) -> Option<Cable>
|
||||
pub fn load_cable<P>(cable_dir: P) -> Option<Cable>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let cable_dir = match cable_dir {
|
||||
Some(dir) => PathBuf::from(dir.as_ref()),
|
||||
None => get_config_dir().join(CABLE_DIR_NAME),
|
||||
};
|
||||
let cable_dir = cable_dir.as_ref();
|
||||
debug!("Using cable directory: {}", cable_dir.to_string_lossy());
|
||||
let cable_files = get_cable_files(&cable_dir);
|
||||
let cable_files = get_cable_files(cable_dir);
|
||||
debug!("Found cable channel files: {:?}", cable_files);
|
||||
|
||||
if cable_files.is_empty() {
|
||||
|
@ -156,9 +156,12 @@ fn parse_keybindings_literal(
|
||||
toml::from_str(&toml_definition).map_err(|e| anyhow!(e))
|
||||
}
|
||||
|
||||
pub fn list_channels(cable_dir: Option<&Path>) {
|
||||
let channels = cable::load_cable::<&Path>(cable_dir)
|
||||
.expect("Failed to load cable channels");
|
||||
pub fn list_channels<P>(cable_dir: P)
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let channels =
|
||||
cable::load_cable(cable_dir).expect("Failed to load cable channels");
|
||||
for c in channels.keys() {
|
||||
println!("\t{c}");
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ pub struct AppConfig {
|
||||
pub data_dir: PathBuf,
|
||||
#[serde(default = "get_config_dir")]
|
||||
pub config_dir: PathBuf,
|
||||
#[serde(default = "default_cable_dir")]
|
||||
pub cable_dir: PathBuf,
|
||||
#[serde(default = "default_frame_rate")]
|
||||
pub frame_rate: f64,
|
||||
#[serde(default = "default_tick_rate")]
|
||||
@ -290,6 +292,10 @@ pub fn get_config_dir() -> PathBuf {
|
||||
}
|
||||
}
|
||||
|
||||
fn default_cable_dir() -> PathBuf {
|
||||
get_config_dir().join(CABLE_DIR_NAME)
|
||||
}
|
||||
|
||||
fn project_directory() -> Option<ProjectDirs> {
|
||||
ProjectDirs::from("com", "", env!("CARGO_PKG_NAME"))
|
||||
}
|
||||
|
@ -47,22 +47,23 @@ async fn main() -> Result<()> {
|
||||
let mut config =
|
||||
Config::new(&ConfigEnv::init()?, args.config_file.as_deref())?;
|
||||
|
||||
// override configuration values with provided CLI arguments
|
||||
debug!("Applying CLI overrides...");
|
||||
apply_cli_overrides(&args, &mut config);
|
||||
|
||||
// handle subcommands
|
||||
debug!("Handling subcommands...");
|
||||
if let Some(subcommand) = &args.command {
|
||||
handle_subcommand(subcommand, &config, &args)?;
|
||||
handle_subcommand(subcommand, &config)?;
|
||||
}
|
||||
|
||||
debug!("Loading cable channels...");
|
||||
let cable = load_cable(args.cable_dir.as_ref()).unwrap_or_else(|| exit(1));
|
||||
let cable =
|
||||
load_cable(&config.application.cable_dir).unwrap_or_else(|| exit(1));
|
||||
|
||||
// optionally change the working directory
|
||||
args.working_directory.as_ref().map(set_current_dir);
|
||||
|
||||
// optionally override configuration values with CLI arguments
|
||||
debug!("Applying CLI overrides...");
|
||||
apply_cli_overrides(&args, &mut config);
|
||||
|
||||
// determine the channel to use based on the CLI arguments and configuration
|
||||
debug!("Determining channel...");
|
||||
let channel_prototype =
|
||||
@ -106,6 +107,9 @@ async fn main() -> Result<()> {
|
||||
///
|
||||
/// This function mutates the configuration in place.
|
||||
fn apply_cli_overrides(args: &PostProcessedCli, config: &mut Config) {
|
||||
if let Some(cable_dir) = &args.cable_dir {
|
||||
config.application.cable_dir.clone_from(cable_dir);
|
||||
}
|
||||
if let Some(tick_rate) = args.tick_rate {
|
||||
config.application.tick_rate = tick_rate;
|
||||
}
|
||||
@ -140,14 +144,10 @@ pub fn set_current_dir(path: &String) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn handle_subcommand(
|
||||
command: &Command,
|
||||
config: &Config,
|
||||
args: &PostProcessedCli,
|
||||
) -> Result<()> {
|
||||
pub fn handle_subcommand(command: &Command, config: &Config) -> Result<()> {
|
||||
match command {
|
||||
Command::ListChannels => {
|
||||
list_channels(args.cable_dir.as_deref());
|
||||
list_channels(&config.application.cable_dir);
|
||||
exit(0);
|
||||
}
|
||||
Command::InitShell { shell } => {
|
||||
|
97
tests/e2e.rs
Normal file
97
tests/e2e.rs
Normal file
@ -0,0 +1,97 @@
|
||||
use std::path::Path;
|
||||
|
||||
use rexpect::error::Error;
|
||||
use rexpect::process::wait::WaitStatus;
|
||||
use rexpect::spawn;
|
||||
use television::channels::prototypes::ChannelPrototype;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn setup_config(content: &str) -> TempDir {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let config_path = temp_dir.path().join("config.toml");
|
||||
std::fs::write(&config_path, content).unwrap();
|
||||
temp_dir
|
||||
}
|
||||
|
||||
fn setup_cable_channels<D>(channels: Vec<&str>, cable_dir: D)
|
||||
where
|
||||
D: AsRef<Path>,
|
||||
{
|
||||
let cable_dir = cable_dir.as_ref();
|
||||
std::fs::create_dir_all(cable_dir).unwrap();
|
||||
for channel in channels {
|
||||
let name = toml::from_str::<ChannelPrototype>(channel)
|
||||
.unwrap()
|
||||
.metadata
|
||||
.name;
|
||||
let channel_path = cable_dir.join(format!("{}.toml", name));
|
||||
std::fs::write(&channel_path, channel).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tv_version() -> Result<(), Error> {
|
||||
let mut p = spawn("./target/debug/tv --version", Some(500))?;
|
||||
p.exp_regex("television [0-9]+\\.[0-9]+\\.[0-9]+")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tv_help() -> Result<(), Error> {
|
||||
let mut p = spawn("./target/debug/tv --help", Some(500))?;
|
||||
p.exp_regex("A cross-platform")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
const BASIC_FILE_CHANNEL: &str = r#"
|
||||
[metadata]
|
||||
name = "files"
|
||||
|
||||
[source]
|
||||
command = "fd -t f"
|
||||
"#;
|
||||
|
||||
const BASIC_DIR_CHANNEL: &str = r#"
|
||||
[metadata]
|
||||
name = "dirs"
|
||||
|
||||
[source]
|
||||
command = "fd -t d"
|
||||
"#;
|
||||
|
||||
#[test]
|
||||
fn tv_list_channels() -> Result<(), Error> {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
setup_cable_channels(
|
||||
vec![BASIC_FILE_CHANNEL, BASIC_DIR_CHANNEL],
|
||||
&temp_dir,
|
||||
);
|
||||
|
||||
let mut p = spawn(
|
||||
&format!(
|
||||
"./target/debug/tv --cable-dir {} list-channels ",
|
||||
temp_dir.path().display()
|
||||
),
|
||||
Some(500),
|
||||
)?;
|
||||
p.exp_regex("files")?;
|
||||
p.exp_regex("dirs")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tv_init_zsh() -> Result<(), Error> {
|
||||
let p = spawn("./target/debug/tv init zsh", Some(500))?;
|
||||
// check that the process exits successfully
|
||||
if let Ok(w) = p.process.wait() {
|
||||
assert_eq!(w, WaitStatus::Exited(w.pid().unwrap(), 0));
|
||||
} else {
|
||||
panic!("Failed to wait for process");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user