chore: merge release-v0.10.1 into main

This commit is contained in:
Jack Wills
2025-04-18 13:12:33 +00:00
139 changed files with 2560 additions and 2094 deletions
+1 -1
View File
@@ -15,7 +15,7 @@
"--security-opt", "--security-opt",
"seccomp=unconfined" "seccomp=unconfined"
], ],
"postCreateCommand": "cargo install cross typos-cli cargo-expand", "postCreateCommand": "cargo install cross typos-cli cargo-expand cargo-insta",
"customizations": { "customizations": {
"vscode": { "vscode": {
// Add the IDs of extensions you want installed when the container is created. // Add the IDs of extensions you want installed when the container is created.
+13 -10
View File
@@ -1,18 +1,21 @@
### 2025-02-23 ### 2025-04-18
### Chores ### Chores
+ dependencies updated, [e5f355a1928f78abdb64e4c5617d6fac06340016], [4539d8ad0705b46d7c89c51c7be482b696d26e5f], [6aee6181136235a1a4f79af9b9748c1801be8bf8], [64d1bdf2bf88407e02f0eded1e03fcfc5ee2d8e3] + dependencies updated, [8f959c5408995527485e817514c3f4a10bca31bd], [69d1801ea1e71e7d84c00fb2142ba27577e3bb73], [188490e13fd1255eecb305ac0a99a7a1913e0294]
+ .devcontainer dependencies updated, [5c8e76e7bb4d7aab8543c9be09fdbc4ffa446b10] + Rust 1.86.0 linting, [9acf60334c5224faa9ee4ecf7030b2e9b13b7d67]
+ example docker-compose.yml updated, [2354b0b9be1ab3795a421512594b2650b9cbdd74]
+ Rust 1.84 linting, [3065265e26c30d78ba738cfe731d3901ec1948d0]
### Features ### Docs
+ Config file introduced, including customizing color scheme of application, closes #47, [f4d54e1ba8ea1516394aef19511a63e6271f27bf] + comment typo, [723b220c6aa6393b8eebd84a6ddba69f35dc18b8]
+ Enable log timestamps to be set to any given timezone, plus custom timestamp format via the config file, closes #56, [7a5e7a25873d2c270e5808730721ebb5427a051]
+ update Rust edition to 2024, [7e4a960b888f1dab524d6045504162cea1171d20]
### Fixes ### Fixes
+ Only draw screen if data or layout has changed, drastically reduces CPU usage, [bfc295c50e982886ccaa5e60b57f10d3690b3f09] + github workflow update, [997eebca20a2883dcfcb35009dd4d7b0d438dec6]
+ config merging, [a468827f02c5243b9bd4e0183fed16854ae6c851]
### Refactors
+ rename ChartType to ChartVariant, [bca67116f3b71451156a39a7b0957568b26fa183], [d0caa9271b6f92f52ccfe3dec69708efe54e5170]
+ rename FileType to FileFormat, [848f64d0da429e547a2f6c8de62e4da5f5c9a187]
### Tests
+ Use insta, closes #57, [9362d7b481ea22eab6f902dc7f3c10150c7ddf22]
see <a href='https://github.com/mrjackwills/oxker/blob/main/CHANGELOG.md'>CHANGELOG.md</a> for more details see <a href='https://github.com/mrjackwills/oxker/blob/main/CHANGELOG.md'>CHANGELOG.md</a> for more details
+30 -19
View File
@@ -88,29 +88,12 @@ jobs:
artifacts: | artifacts: |
**/oxker_*.zip **/oxker_*.zip
**/oxker_*.tar.gz **/oxker_*.tar.gz
##################
## Cargo publish #
##################
cargo_publish:
needs: [create_release]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: publish to crates.io
uses: katyo/publish-crates@v2
with:
registry-token: ${{ secrets.CRATES_IO_TOKEN }}
######################################### #########################################
## Build images for Dockerhub & ghcr.io # ## Build images for Dockerhub & ghcr.io #
######################################### #########################################
image_build: container_image_build:
needs: [cargo_publish] needs: [create_release]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
@@ -148,3 +131,31 @@ jobs:
--provenance=false --sbom=false \ --provenance=false --sbom=false \
--push \ --push \
-f containerised/Dockerfile . -f containerised/Dockerfile .
########################
# Publish to crates.io #
########################
# This could be moved to before a github release is made
dry_run_cargo_publish:
runs-on: ubuntu-latest
needs: [container_image_build]
steps:
- name: update rust stable
run: rustup update stable
- uses: actions/checkout@v4
- name: Publish Dry Run
run: cargo publish --dry-run
cargo_publish:
environment: crates.io
runs-on: ubuntu-latest
needs: [dry_run_cargo_publish]
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
steps:
- name: update rust stable
run: rustup update stable
- uses: actions/checkout@v4
- name: Publish
run: cargo publish
+21
View File
@@ -1,3 +1,24 @@
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.10.1'>v0.10.1</a>
### 2025-04-18
### Chores
+ dependencies updated, [8f959c54](https://github.com/mrjackwills/oxker/commit/8f959c5408995527485e817514c3f4a10bca31bd), [69d1801e](https://github.com/mrjackwills/oxker/commit/69d1801ea1e71e7d84c00fb2142ba27577e3bb73), [188490e1](https://github.com/mrjackwills/oxker/commit/188490e13fd1255eecb305ac0a99a7a1913e0294)
+ Rust 1.86.0 linting, [9acf6033](https://github.com/mrjackwills/oxker/commit/9acf60334c5224faa9ee4ecf7030b2e9b13b7d67)
### Docs
+ comment typo, [723b220c](https://github.com/mrjackwills/oxker/commit/723b220c6aa6393b8eebd84a6ddba69f35dc18b8)
### Fixes
+ github workflow update, [997eebca](https://github.com/mrjackwills/oxker/commit/997eebca20a2883dcfcb35009dd4d7b0d438dec6)
+ config merging, [a468827f](https://github.com/mrjackwills/oxker/commit/a468827f02c5243b9bd4e0183fed16854ae6c851)
### Refactors
+ rename ChartType to ChartVariant, [bca67116](https://github.com/mrjackwills/oxker/commit/bca67116f3b71451156a39a7b0957568b26fa183), [d0caa927](https://github.com/mrjackwills/oxker/commit/d0caa9271b6f92f52ccfe3dec69708efe54e5170)
+ rename FileType to FileFormat, [848f64d0](https://github.com/mrjackwills/oxker/commit/848f64d0da429e547a2f6c8de62e4da5f5c9a187)
### Tests
+ Use insta, closes [#57](https://github.com/mrjackwills/oxker/issues/57), [9362d7b4](https://github.com/mrjackwills/oxker/commit/9362d7b481ea22eab6f902dc7f3c10150c7ddf22)
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.10.0'>v0.10.0</a> # <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.10.0'>v0.10.0</a>
### 2025-02-23 ### 2025-02-23
Generated
+372 -185
View File
File diff suppressed because it is too large Load Diff
+7 -5
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "oxker" name = "oxker"
version = "0.10.0" version = "0.10.1"
edition = "2024" edition = "2024"
authors = ["Jack Wills <email@mrjackwills.com>"] authors = ["Jack Wills <email@mrjackwills.com>"]
description = "A simple tui to view & control docker containers" description = "A simple tui to view & control docker containers"
@@ -30,7 +30,7 @@ anyhow = "1.0"
bollard = "0.18" bollard = "0.18"
cansi = "2.2" cansi = "2.2"
clap = { version = "4.5", features = ["color", "derive", "unicode"] } clap = { version = "4.5", features = ["color", "derive", "unicode"] }
crossterm = "0.28" crossterm = "0.29"
directories = "6.0" directories = "6.0"
futures-util = "0.3" futures-util = "0.3"
jiff = { version = "0.2", features = ["tzdb-bundle-always"] } jiff = { version = "0.2", features = ["tzdb-bundle-always"] }
@@ -39,13 +39,12 @@ ratatui = "0.29"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
serde_jsonc = "1.0" serde_jsonc = "1.0"
tokio = { version = "1.43", features = ["full"] } tokio = { version = "1.44", features = ["full"] }
tokio-util = "0.7" tokio-util = "0.7"
toml = { version = "0.8", default-features = false, features = ["parse"] } toml = { version = "0.8", default-features = false, features = ["parse"] }
tracing = "0.1" tracing = "0.1"
tracing-subscriber = "0.3" tracing-subscriber = "0.3"
uuid = { version = "1.14", features = ["fast-rng", "v4"] } uuid = { version = "1.16", features = ["fast-rng", "v4"] }
[profile.release] [profile.release]
lto = true lto = true
@@ -53,3 +52,6 @@ codegen-units = 1
panic = 'abort' panic = 'abort'
strip = true strip = true
debug = false debug = false
[dev-dependencies]
insta = "1.42.2"
+1 -1
View File
@@ -13,7 +13,7 @@
// Show self (the oxker container) when running as a docker container // Show self (the oxker container) when running as a docker container
"show_self": false, "show_self": false,
// Show std_err in logs // Show std_err in logs
"show_std_err": false, "show_std_err": true,
// Show a timestamp for every log entry // Show a timestamp for every log entry
"show_timestamp": true, "show_timestamp": true,
// Don't draw gui - for debugging - mostly pointless // Don't draw gui - for debugging - mostly pointless
+1 -1
View File
@@ -16,7 +16,7 @@ raw_logs = false
show_self = false show_self = false
# Show std_err in logs # Show std_err in logs
show_std_err = false show_std_err = true
# Show a timestamp for every log entry # Show a timestamp for every log entry
show_timestamp = true show_timestamp = true
+4 -4
View File
@@ -35,7 +35,7 @@ impl ContainerId {
} }
/// Only return first 8 chars of id, is usually more than enough for uniqueness /// Only return first 8 chars of id, is usually more than enough for uniqueness
/// TODO container id is a hex string, so can assume that 0..=8 will always return a 8 char ascii &str - need to update tests to use real ids, or atleast strings of the correct-ish length /// need to update tests to use real ids, or atleast strings of the correct-ish length
pub fn get_short(&self) -> String { pub fn get_short(&self) -> String {
self.0.chars().take(8).collect::<String>() self.0.chars().take(8).collect::<String>()
} }
@@ -481,7 +481,7 @@ impl ByteStats {
pub const fn new(value: u64) -> Self { pub const fn new(value: u64) -> Self {
Self(value) Self(value)
} }
pub fn update(&mut self, value: u64) { pub const fn update(&mut self, value: u64) {
self.0 = value; self.0 = value;
} }
} }
@@ -567,7 +567,7 @@ impl Logs {
pub fn insert(&mut self, line: ListItem<'static>, tz: LogsTz) { pub fn insert(&mut self, line: ListItem<'static>, tz: LogsTz) {
if self.tz.insert(tz) { if self.tz.insert(tz) {
self.logs.items.push(line); self.logs.items.push(line);
}; }
} }
pub fn to_vec(&self) -> Vec<ListItem<'static>> { pub fn to_vec(&self) -> Vec<ListItem<'static>> {
@@ -598,7 +598,7 @@ impl Logs {
self.logs.items.len() self.logs.items.len()
} }
pub fn state(&mut self) -> &mut ListState { pub const fn state(&mut self) -> &mut ListState {
&mut self.logs.state &mut self.logs.state
} }
} }
+10 -8
View File
@@ -237,7 +237,7 @@ impl AppData {
term.push(c); term.push(c);
} else { } else {
self.filter.term = Some(format!("{c}")); self.filter.term = Some(format!("{c}"));
}; }
self.filter_containers(); self.filter_containers();
} }
@@ -275,7 +275,7 @@ impl AppData {
while let Some(i) = self.hidden_containers.pop() { while let Some(i) = self.hidden_containers.pop() {
if self.get_container_by_id(&i.id).is_none() { if self.get_container_by_id(&i.id).is_none() {
self.containers.items.push(i); self.containers.items.push(i);
}; }
} }
self.sort_containers(); self.sort_containers();
} }
@@ -420,6 +420,8 @@ impl AppData {
} }
/// Get all the ContainerItems /// Get all the ContainerItems
/// Thnk this allow block can be removed with the 1.87 release of Clippy
#[allow(clippy::missing_const_for_fn)]
pub fn get_container_items(&self) -> &[ContainerItem] { pub fn get_container_items(&self) -> &[ContainerItem] {
&self.containers.items &self.containers.items
} }
@@ -459,7 +461,7 @@ impl AppData {
} }
/// Get ListState of containers /// Get ListState of containers
pub fn get_container_state(&mut self) -> &mut ListState { pub const fn get_container_state(&mut self) -> &mut ListState {
&mut self.containers.state &mut self.containers.state
} }
@@ -886,10 +888,10 @@ impl AppData {
if let Some(item) = self.get_any_container_by_id(&id) { if let Some(item) = self.get_any_container_by_id(&id) {
if item.name.get() != name { if item.name.get() != name {
item.name.set(name); item.name.set(name);
}; }
if item.status != status { if item.status != status {
item.status = status; item.status = status;
}; }
if item.state != state { if item.state != state {
item.docker_controls.items = DockerCommand::gen_vec(state); item.docker_controls.items = DockerCommand::gen_vec(state);
// Update the list state, needs to be None if the gen_vec returns an empty vec // Update the list state, needs to be None if the gen_vec returns an empty vec
@@ -898,15 +900,15 @@ impl AppData {
item.docker_controls.state.select(None); item.docker_controls.state.select(None);
} }
_ => item.docker_controls.start(), _ => item.docker_controls.start(),
}; }
item.state = state; item.state = state;
}; }
item.ports = ports; item.ports = ports;
if item.image.get() != image { if item.image.get() != image {
item.image.set(image); item.image.set(image);
}; }
} else { } else {
// container not known, so make new ContainerItem and push into containers Ve // container not known, so make new ContainerItem and push into containers Ve
let container = ContainerItem::new( let container = ContainerItem::new(
+1 -1
View File
@@ -16,7 +16,7 @@ raw_logs = false
show_self = false show_self = false
# Show std_err in logs # Show std_err in logs
show_std_err = false show_std_err = true
# Show a timestamp for every log entry # Show a timestamp for every log entry
show_timestamp = true show_timestamp = true
+36 -16
View File
@@ -126,19 +126,44 @@ impl Config {
} }
/// Combine config from CLI into config file, the cli take priority /// Combine config from CLI into config file, the cli take priority
/// make sure color_logs and raw_logs can't clash /// and also make sure color_logs and raw_logs can't clash
fn merge_args(mut self, config_from_cli: Self) -> Self { fn merge_args(mut self, config_from_cli: Self) -> Self {
let default_args = Args::default();
if config_from_cli.color_logs != default_args.color {
self.color_logs = config_from_cli.color_logs; self.color_logs = config_from_cli.color_logs;
self.docker_interval_ms = config_from_cli.docker_interval_ms; }
if config_from_cli.gui != default_args.gui {
self.gui = config_from_cli.gui; self.gui = config_from_cli.gui;
self.raw_logs = config_from_cli.raw_logs; }
self.show_self = config_from_cli.show_self;
self.show_std_err = config_from_cli.show_std_err; if config_from_cli.docker_interval_ms != default_args.docker_interval {
self.show_timestamp = config_from_cli.show_timestamp; self.docker_interval_ms = config_from_cli.docker_interval_ms;
self.use_cli = config_from_cli.use_cli; }
if config_from_cli.docker_interval_ms < 1000 { if config_from_cli.docker_interval_ms < 1000 {
self.docker_interval_ms = 1000; self.docker_interval_ms = default_args.docker_interval;
}
if config_from_cli.raw_logs != default_args.raw {
self.raw_logs = config_from_cli.raw_logs;
}
if config_from_cli.show_self != default_args.show_self {
self.show_self = config_from_cli.show_self;
}
if config_from_cli.show_std_err != default_args.no_std_err {
self.show_std_err = config_from_cli.show_std_err;
}
if config_from_cli.show_timestamp != default_args.timestamp {
self.show_timestamp = config_from_cli.show_timestamp;
}
if config_from_cli.use_cli != default_args.use_cli {
self.use_cli = config_from_cli.use_cli;
} }
if let Some(host) = config_from_cli.host { if let Some(host) = config_from_cli.host {
@@ -153,10 +178,7 @@ impl Config {
self.timezone = Some(tz); self.timezone = Some(tz);
} }
if config_from_cli.raw_logs { if self.color_logs && self.raw_logs {
self.color_logs = false;
}
if config_from_cli.color_logs {
self.raw_logs = false; self.raw_logs = false;
} }
self self
@@ -232,11 +254,9 @@ mod tests {
#[test] #[test]
/// Test various timezones get parsed correctly /// Test various timezones get parsed correctly
fn test_config_parse_timezone() { fn test_config_parse_timezone() {
assert!(super::Config::parse_timezone(None).is_none());
// Timezone with no offset just return None // Timezone with no offset just return None
for i in ["Europe/London", "Africa/Accra"] { for i in [None, Some("UTC".to_owned())] {
assert!(super::Config::parse_timezone(Some(i.to_owned())).is_none()); assert!(super::Config::parse_timezone(i).is_none());
} }
let expected = Some(TimeZone::get("Asia/Tokyo").unwrap()); let expected = Some(TimeZone::get("Asia/Tokyo").unwrap());
+19
View File
@@ -53,3 +53,22 @@ pub struct Args {
#[clap(long="use-cli", short = None)] #[clap(long="use-cli", short = None)]
pub use_cli: bool, pub use_cli: bool,
} }
impl Default for Args {
fn default() -> Self {
Self {
docker_interval: 1000,
timestamp: true,
color: false,
raw: false,
show_self: false,
gui: true,
host: None,
no_std_err: true,
timezone: None,
save_dir: None,
config_file: None,
use_cli: false,
}
}
}
+34 -53
View File
@@ -10,14 +10,14 @@ use crate::app_error::AppError;
use super::{color_parser::ConfigColors, keymap_parser::ConfigKeymap}; use super::{color_parser::ConfigColors, keymap_parser::ConfigKeymap};
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ConfigFileType { enum ConfigFileFormat {
Toml, Toml,
Jsonc, Jsonc,
Json, Json,
JsoncAsJson, JsoncAsJson,
} }
impl TryFrom<&PathBuf> for ConfigFileType { impl TryFrom<&PathBuf> for ConfigFileFormat {
type Error = AppError; type Error = AppError;
/// Only allow toml, json, or jsonc files /// Only allow toml, json, or jsonc files
@@ -38,7 +38,7 @@ impl TryFrom<&PathBuf> for ConfigFileType {
} }
} }
impl ConfigFileType { impl ConfigFileFormat {
/// Get the local config directory, to be used by default config parser /// Get the local config directory, to be used by default config parser
fn get_config_dir(in_container: bool) -> Option<PathBuf> { fn get_config_dir(in_container: bool) -> Option<PathBuf> {
if in_container { if in_container {
@@ -48,7 +48,7 @@ impl ConfigFileType {
.map(|base_dirs| base_dirs.config_local_dir().join(env!("CARGO_PKG_NAME"))) .map(|base_dirs| base_dirs.config_local_dir().join(env!("CARGO_PKG_NAME")))
} }
} }
/// Return the default filename + path for a given filetype /// Return the default filename + path for a given fileformat
fn get_default_path_name(self, in_container: bool) -> PathBuf { fn get_default_path_name(self, in_container: bool) -> PathBuf {
let suffix = match self { let suffix = match self {
Self::Json | Self::JsoncAsJson => "config.json", Self::Json | Self::JsoncAsJson => "config.json",
@@ -84,7 +84,7 @@ impl ConfigFile {
return Ok(()); return Ok(());
} }
let config_dir = ConfigFileType::get_config_dir(in_container) let config_dir = ConfigFileFormat::get_config_dir(in_container)
.ok_or_else(|| AppError::IO("config_dir".to_owned()))?; .ok_or_else(|| AppError::IO("config_dir".to_owned()))?;
let file_name = config_dir.join("config.toml"); let file_name = config_dir.join("config.toml");
@@ -105,22 +105,22 @@ impl ConfigFile {
} }
/// parse a given &str (read from the configfile) into Self /// parse a given &str (read from the configfile) into Self
fn parse(file_type: ConfigFileType, input: &str) -> Result<Self, AppError> { fn parse(file_format: ConfigFileFormat, input: &str) -> Result<Self, AppError> {
match file_type { match file_format {
ConfigFileType::Json => { ConfigFileFormat::Json => {
serde_json::from_str::<Self>(input).map_err(|i| AppError::Parse(i.to_string())) serde_json::from_str::<Self>(input).map_err(|i| AppError::Parse(i.to_string()))
} }
ConfigFileType::Jsonc | ConfigFileType::JsoncAsJson => { ConfigFileFormat::Jsonc | ConfigFileFormat::JsoncAsJson => {
serde_jsonc::from_str::<Self>(input).map_err(|i| AppError::Parse(i.to_string())) serde_jsonc::from_str::<Self>(input).map_err(|i| AppError::Parse(i.to_string()))
} }
ConfigFileType::Toml => { ConfigFileFormat::Toml => {
toml::from_str::<Self>(input).map_err(|i| AppError::Parse(i.message().to_owned())) toml::from_str::<Self>(input).map_err(|i| AppError::Parse(i.message().to_owned()))
} }
} }
} }
/// Read the config file path to string, then attempt to parse /// Read the config file path to string, then attempt to parse
fn parse_config_file(file_type: ConfigFileType, path: &PathBuf) -> Result<Self, AppError> { fn parse_config_file(file_format: ConfigFileFormat, path: &PathBuf) -> Result<Self, AppError> {
let mut file = std::fs::File::open(path).map_err(|_| { let mut file = std::fs::File::open(path).map_err(|_| {
AppError::IO( AppError::IO(
path.to_str() path.to_str()
@@ -130,53 +130,32 @@ impl ConfigFile {
let mut input = String::new(); let mut input = String::new();
file.read_to_string(&mut input) file.read_to_string(&mut input)
.map_err(|i| AppError::IO(i.to_string()))?; .map_err(|i| AppError::IO(i.to_string()))?;
Self::parse(file_type, &input) Self::parse(file_format, &input)
}
/// Resolve conflict in the args, this is handled automatically by Clap, basically just by rejecting it
/// But here we can just change the options - although maybe should be also reject to follow the same behaviour as Clap?
/// TODO I think this is duplicated with the merge_args fn
fn resolve_conflict(&mut self) {
if let Some(color) = self.color_logs.as_ref() {
if *color {
self.raw_logs = Some(false);
}
}
if let Some(interval) = self.docker_interval.as_ref() {
if interval < &1000 {
self.docker_interval = Some(1000);
}
}
} }
/// Try to parse the config file when the path is user supplied via cliargs /// Try to parse the config file when the path is user supplied via cliargs
pub fn try_parse_from_file(path: &str) -> Option<Self> { pub fn try_parse_from_file(path: &str) -> Option<Self> {
let path = PathBuf::from(path); let path = PathBuf::from(path);
let Ok(file_type) = ConfigFileType::try_from(&path) else { let Ok(file_format) = ConfigFileFormat::try_from(&path) else {
return None; return None;
}; };
Self::parse_config_file(file_format, &path).ok()
Self::parse_config_file(file_type, &path).map_or(None, |mut config_file| {
config_file.resolve_conflict();
Some(config_file)
})
} }
/// Parse a config file using default config_file location /// Parse a config file using default config_file location
/// This is executed first, then the CLI args are read, and if they contain a "--config-file" entry, then Self::try_parse_from_file() is executed /// This is executed first, then the CLI args are read, and if they contain a "--config-file" entry, then Self::try_parse_from_file() is executed
pub fn try_parse(in_container: bool) -> Option<Self> { pub fn try_parse(in_container: bool) -> Option<Self> {
let mut config = None; let mut config = None;
for file_type in [ for file_format in [
ConfigFileType::Toml, ConfigFileFormat::Toml,
ConfigFileType::Jsonc, ConfigFileFormat::Jsonc,
ConfigFileType::JsoncAsJson, ConfigFileFormat::JsoncAsJson,
ConfigFileType::Json, ConfigFileFormat::Json,
] { ] {
if let Ok(mut config_file) = if let Ok(config_file) = Self::parse_config_file(
Self::parse_config_file(file_type, &file_type.get_default_path_name(in_container)) file_format,
{ &file_format.get_default_path_name(in_container),
Self::resolve_conflict(&mut config_file); ) {
config = Some(config_file); config = Some(config_file);
break; break;
} }
@@ -202,7 +181,7 @@ mod tests {
/// ./config.toml parses fine - as this is used to write a file on disk, it's vital that this is always valid /// ./config.toml parses fine - as this is used to write a file on disk, it's vital that this is always valid
fn test_parse_config_toml_valid() { fn test_parse_config_toml_valid() {
let example_toml = include_str!("./config.toml"); let example_toml = include_str!("./config.toml");
let result = ConfigFile::parse(super::ConfigFileType::Toml, example_toml); let result = ConfigFile::parse(super::ConfigFileFormat::Toml, example_toml);
assert!(result.is_ok()); assert!(result.is_ok());
} }
@@ -210,7 +189,7 @@ mod tests {
/// make sure config.toml matches the default keymap /// make sure config.toml matches the default keymap
fn test_parse_config_keymap_toml() { fn test_parse_config_keymap_toml() {
let example_toml = include_str!("./config.toml"); let example_toml = include_str!("./config.toml");
let result = ConfigFile::parse(super::ConfigFileType::Toml, example_toml).unwrap(); let result = ConfigFile::parse(super::ConfigFileFormat::Toml, example_toml).unwrap();
assert!(result.keymap.is_some()); assert!(result.keymap.is_some());
assert_eq!(Keymap::from(result.keymap), Keymap::new()); assert_eq!(Keymap::from(result.keymap), Keymap::new());
} }
@@ -219,7 +198,7 @@ mod tests {
/// make sure example.config.jsonc matches the default keymap /// make sure example.config.jsonc matches the default keymap
fn test_parse_config_keymap_jsonc() { fn test_parse_config_keymap_jsonc() {
let example_jsonc = include_str!("../../example_config/example.config.jsonc"); let example_jsonc = include_str!("../../example_config/example.config.jsonc");
let result = ConfigFile::parse(super::ConfigFileType::Jsonc, example_jsonc).unwrap(); let result = ConfigFile::parse(super::ConfigFileFormat::Jsonc, example_jsonc).unwrap();
assert!(result.keymap.is_some()); assert!(result.keymap.is_some());
assert_eq!(Keymap::from(result.keymap), Keymap::new()); assert_eq!(Keymap::from(result.keymap), Keymap::new());
} }
@@ -228,12 +207,13 @@ mod tests {
/// All configs parsed and are equal /// All configs parsed and are equal
fn test_parse_config_keymap_all() { fn test_parse_config_keymap_all() {
let example_jsonc = include_str!("../../example_config/example.config.jsonc"); let example_jsonc = include_str!("../../example_config/example.config.jsonc");
let result_jsonc = ConfigFile::parse(super::ConfigFileType::Jsonc, example_jsonc).unwrap(); let result_jsonc =
ConfigFile::parse(super::ConfigFileFormat::Jsonc, example_jsonc).unwrap();
assert!(result_jsonc.keymap.is_some()); assert!(result_jsonc.keymap.is_some());
let result_jsonc = result_jsonc.keymap.unwrap(); let result_jsonc = result_jsonc.keymap.unwrap();
let example_toml = include_str!("./config.toml"); let example_toml = include_str!("./config.toml");
let result_toml = ConfigFile::parse(super::ConfigFileType::Toml, example_toml).unwrap(); let result_toml = ConfigFile::parse(super::ConfigFileFormat::Toml, example_toml).unwrap();
assert!(result_toml.keymap.is_some()); assert!(result_toml.keymap.is_some());
let result_toml = result_toml.keymap.unwrap(); let result_toml = result_toml.keymap.unwrap();
@@ -245,7 +225,7 @@ mod tests {
/// make sure config.toml matches the default app colors /// make sure config.toml matches the default app colors
fn test_parse_config_colors_toml() { fn test_parse_config_colors_toml() {
let example_toml = include_str!("./config.toml"); let example_toml = include_str!("./config.toml");
let result = ConfigFile::parse(super::ConfigFileType::Toml, example_toml).unwrap(); let result = ConfigFile::parse(super::ConfigFileFormat::Toml, example_toml).unwrap();
assert!(result.colors.is_some()); assert!(result.colors.is_some());
assert_eq!(AppColors::from(result.colors), AppColors::new()); assert_eq!(AppColors::from(result.colors), AppColors::new());
} }
@@ -254,7 +234,7 @@ mod tests {
/// make sure config.toml matches the default app colors /// make sure config.toml matches the default app colors
fn test_parse_config_colors_jsonc() { fn test_parse_config_colors_jsonc() {
let example_jsonc = include_str!("../../example_config/example.config.jsonc"); let example_jsonc = include_str!("../../example_config/example.config.jsonc");
let result = ConfigFile::parse(super::ConfigFileType::Jsonc, example_jsonc).unwrap(); let result = ConfigFile::parse(super::ConfigFileFormat::Jsonc, example_jsonc).unwrap();
assert!(result.colors.is_some()); assert!(result.colors.is_some());
assert_eq!(AppColors::from(result.colors), AppColors::new()); assert_eq!(AppColors::from(result.colors), AppColors::new());
} }
@@ -263,12 +243,13 @@ mod tests {
/// All configs parsed and are equal /// All configs parsed and are equal
fn test_parse_config_colors_all() { fn test_parse_config_colors_all() {
let example_jsonc = include_str!("../../example_config/example.config.jsonc"); let example_jsonc = include_str!("../../example_config/example.config.jsonc");
let result_jsonc = ConfigFile::parse(super::ConfigFileType::Jsonc, example_jsonc).unwrap(); let result_jsonc =
ConfigFile::parse(super::ConfigFileFormat::Jsonc, example_jsonc).unwrap();
assert!(result_jsonc.colors.is_some()); assert!(result_jsonc.colors.is_some());
let result_jsonc = result_jsonc.colors.unwrap(); let result_jsonc = result_jsonc.colors.unwrap();
let example_toml = include_str!("./config.toml"); let example_toml = include_str!("./config.toml");
let result_toml = ConfigFile::parse(super::ConfigFileType::Toml, example_toml).unwrap(); let result_toml = ConfigFile::parse(super::ConfigFileFormat::Toml, example_toml).unwrap();
assert!(result_toml.colors.is_some()); assert!(result_toml.colors.is_some());
let result_toml = result_toml.colors.unwrap(); let result_toml = result_toml.colors.unwrap();
+1 -1
View File
@@ -322,7 +322,7 @@ impl DockerData {
self.config.show_std_err, self.config.show_std_err,
))); )));
} }
}; }
self.update_all_container_stats(); self.update_all_container_stats();
self.app_data.lock().sort_containers(); self.app_data.lock().sort_containers();
} }
+1 -1
View File
@@ -330,7 +330,7 @@ impl ExecMode {
if byte_sequence_valid(&bytes) { if byte_sequence_valid(&bytes) {
waiting_thread.store(false, std::sync::atomic::Ordering::SeqCst); waiting_thread.store(false, std::sync::atomic::Ordering::SeqCst);
} }
}; }
} }
}); });
+3 -3
View File
@@ -167,7 +167,7 @@ impl InputHandler {
.set_info_box("✓ mouse capture enabled"); .set_info_box("✓ mouse capture enabled");
} else { } else {
err(); err();
}; }
self.mouse_capture = !self.mouse_capture; self.mouse_capture = !self.mouse_capture;
} }
@@ -264,7 +264,7 @@ impl InputHandler {
// Poor way of disallowing commands to be sent to a containerised okxer // Poor way of disallowing commands to be sent to a containerised okxer
if self.app_data.lock().is_oxker_in_container() { if self.app_data.lock().is_oxker_in_container() {
return; return;
}; }
let option_id = self.app_data.lock().get_selected_container_id(); let option_id = self.app_data.lock().get_selected_container_id();
if let Some(id) = option_id { if let Some(id) = option_id {
match command { match command {
@@ -639,7 +639,7 @@ impl InputHandler {
SelectablePanel::Containers => self.app_data.lock().containers_next(), SelectablePanel::Containers => self.app_data.lock().containers_next(),
SelectablePanel::Logs => self.app_data.lock().log_next(), SelectablePanel::Logs => self.app_data.lock().log_next(),
SelectablePanel::Commands => self.app_data.lock().docker_controls_next(), SelectablePanel::Commands => self.app_data.lock().docker_controls_next(),
}; }
} }
/// Change state to previous, depending which panel is currently in focus /// Change state to previous, depending which panel is currently in focus
+33 -59
View File
@@ -16,12 +16,12 @@ use crate::{
}; };
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ChartType { enum ChartVariant {
Cpu, Cpu,
Memory, Memory,
} }
impl ChartType { impl ChartVariant {
const fn name(self) -> &'static str { const fn name(self) -> &'static str {
match self { match self {
Self::Cpu => "cpu", Self::Cpu => "cpu",
@@ -75,30 +75,30 @@ impl ChartType {
/// Create charts /// Create charts
fn make_chart<'a, T: Stats + Display>( fn make_chart<'a, T: Stats + Display>(
chart_type: ChartType, chart_variant: ChartVariant,
colors: AppColors, colors: AppColors,
current: &'a T, current: &'a T,
dataset: Vec<Dataset<'a>>, dataset: Vec<Dataset<'a>>,
max: &'a T, max: &'a T,
state: State, state: State,
) -> Chart<'a> { ) -> Chart<'a> {
let max_color = chart_type.get_max_color(colors, state); let max_color = chart_variant.get_max_color(colors, state);
Chart::new(dataset) Chart::new(dataset)
.bg(chart_type.get_bg_color(colors)) .bg(chart_variant.get_bg_color(colors))
.block( .block(
Block::default() Block::default()
.style(Style::default().bg(chart_type.get_bg_color(colors))) .style(Style::default().bg(chart_variant.get_bg_color(colors)))
.title_alignment(Alignment::Center) .title_alignment(Alignment::Center)
.title(Span::styled( .title(Span::styled(
format!(" {} {current} ", chart_type.name()), format!(" {} {current} ", chart_variant.name()),
Style::default() Style::default()
.fg(chart_type.get_title_color(colors, state)) .fg(chart_variant.get_title_color(colors, state))
.add_modifier(Modifier::BOLD), .add_modifier(Modifier::BOLD),
)) ))
.borders(Borders::ALL) .borders(Borders::ALL)
.border_type(BorderType::Rounded) .border_type(BorderType::Rounded)
.border_style(Style::default().fg(chart_type.get_border_color(colors))), .border_style(Style::default().fg(chart_variant.get_border_color(colors))),
) )
.x_axis(Axis::default().bounds([0.00, 60.0])) .x_axis(Axis::default().bounds([0.00, 60.0]))
.y_axis( .y_axis(
@@ -110,7 +110,7 @@ fn make_chart<'a, T: Stats + Display>(
Style::default().add_modifier(Modifier::BOLD).fg(max_color), Style::default().add_modifier(Modifier::BOLD).fg(max_color),
), ),
]) ])
.style(Style::new().fg(chart_type.get_y_axis_color(colors))) .style(Style::new().fg(chart_variant.get_y_axis_color(colors)))
// Add 0.01, so that max point is always visible? // Add 0.01, so that max point is always visible?
.bounds([0.0, max.get_value() + 0.01]), .bounds([0.0, max.get_value() + 0.01]),
) )
@@ -143,7 +143,7 @@ pub fn draw(area: Rect, colors: AppColors, f: &mut Frame, fd: &FrameData) {
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
let mem_stats = ByteStats::new(mem.0.last().map_or(0, |f| f.1 as u64)); let mem_stats = ByteStats::new(mem.0.last().map_or(0, |f| f.1 as u64));
let cpu_chart = make_chart( let cpu_chart = make_chart(
ChartType::Cpu, ChartVariant::Cpu,
colors, colors,
&cpu_stats, &cpu_stats,
cpu_dataset, cpu_dataset,
@@ -151,7 +151,7 @@ pub fn draw(area: Rect, colors: AppColors, f: &mut Frame, fd: &FrameData) {
cpu.2, cpu.2,
); );
let mem_chart = make_chart( let mem_chart = make_chart(
ChartType::Memory, ChartVariant::Memory,
colors, colors,
&mem_stats, &mem_stats,
mem_dataset, mem_dataset,
@@ -167,6 +167,7 @@ pub fn draw(area: Rect, colors: AppColors, f: &mut Frame, fd: &FrameData) {
#[cfg(test)] #[cfg(test)]
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
mod tests { mod tests {
use insta::assert_snapshot;
use ratatui::style::{Color, Modifier}; use ratatui::style::{Color, Modifier};
use crate::{ use crate::{
@@ -174,14 +175,12 @@ mod tests {
config::AppColors, config::AppColors,
ui::{ ui::{
FrameData, FrameData,
draw_blocks::tests::{ draw_blocks::tests::{COLOR_ORANGE, get_result, insert_chart_data, test_setup},
COLOR_ORANGE, expected_to_vec, get_result, insert_chart_data, test_setup,
},
}, },
}; };
/// CPU and Memory charts used in multiple tests, based on data from above insert_chart_data() /// CPU and Memory charts used in multiple tests, based on data from above insert_chart_data()
const EXPECTED: [&str; 10] = [ const _EXPECTED: [&str; 10] = [
"╭───────────── cpu 03.00% ─────────────╮╭────────── memory 30.00 kB ───────────╮", "╭───────────── cpu 03.00% ─────────────╮╭────────── memory 30.00 kB ───────────╮",
"│10.00%│ • ││100.00 kB│ •• │", "│10.00%│ • ││100.00 kB│ •• │",
"│ │ •• ││ │ •• │", "│ │ •• ││ │ •• │",
@@ -236,8 +235,7 @@ mod tests {
#[test] #[test]
/// When status is Running, but not data, charts drawn without dots etc, colours correct /// When status is Running, but not data, charts drawn without dots etc, colours correct
fn test_draw_blocks_charts_running_none() { fn test_draw_blocks_charts_running_none() {
let (w, h) = (80, 10); let mut setup = test_setup(80, 10, true, true);
let mut setup = test_setup(w, h, true, true);
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
setup setup
@@ -246,25 +244,10 @@ mod tests {
super::draw(setup.area, setup.app_data.lock().config.app_colors, f, &fd); super::draw(setup.area, setup.app_data.lock().config.app_colors, f, &fd);
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
let expected = [ for (row_index, result_row) in get_result(&setup) {
"╭───────────── cpu 00.00% ─────────────╮╭─────────── memory 0.00 kB ───────────╮",
"│00.00%│ ││0.00 kB│ │",
"│ │ ││ │ │",
"│ │ ││ │ │",
"│ │ ││ │ │",
"│ │ ││ │ │",
"│ │ ││ │ │",
"│ │ ││ │ │",
"│ │ ││ │ │",
"╰──────────────────────────────────────╯╰──────────────────────────────────────╯",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0, 14..=25 | 52..=67) => { (0, 14..=25 | 52..=67) => {
assert_eq!(result_cell.fg, Color::Green); assert_eq!(result_cell.fg, Color::Green);
@@ -290,8 +273,7 @@ mod tests {
#[test] #[test]
/// When status is Running, charts correctly drawn /// When status is Running, charts correctly drawn
fn test_draw_blocks_charts_running_some() { fn test_draw_blocks_charts_running_some() {
let (w, h) = (80, 10); let mut setup = test_setup(80, 10, true, true);
let mut setup = test_setup(w, h, true, true);
insert_chart_data(&setup); insert_chart_data(&setup);
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -303,11 +285,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&EXPECTED, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0, 14..=25 | 51..=67) => { (0, 14..=25 | 51..=67) => {
assert_eq!(result_cell.fg, Color::Green); assert_eq!(result_cell.fg, Color::Green);
@@ -341,8 +322,7 @@ mod tests {
#[test] #[test]
/// Whens status paused, some text is now Yellow /// Whens status paused, some text is now Yellow
fn test_draw_blocks_charts_paused() { fn test_draw_blocks_charts_paused() {
let (w, h) = (80, 10); let mut setup = test_setup(80, 10, true, true);
let mut setup = test_setup(w, h, true, true);
insert_chart_data(&setup); insert_chart_data(&setup);
setup.app_data.lock().containers.items[0].state = State::Paused; setup.app_data.lock().containers.items[0].state = State::Paused;
@@ -355,11 +335,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&EXPECTED, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0, 14..=25 | 51..=67) | (1, 1..=6 | 41..=49) => { (0, 14..=25 | 51..=67) | (1, 1..=6 | 41..=49) => {
assert_eq!(result_cell.fg, Color::Yellow); assert_eq!(result_cell.fg, Color::Yellow);
@@ -389,8 +368,7 @@ mod tests {
#[test] #[test]
/// When dead, text is red /// When dead, text is red
fn test_draw_blocks_charts_dead() { fn test_draw_blocks_charts_dead() {
let (w, h) = (80, 10); let mut setup = test_setup(80, 10, true, true);
let mut setup = test_setup(w, h, true, true);
insert_chart_data(&setup); insert_chart_data(&setup);
setup.app_data.lock().containers.items[0].state = State::Dead; setup.app_data.lock().containers.items[0].state = State::Dead;
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -401,12 +379,9 @@ mod tests {
super::draw(setup.area, setup.app_data.lock().config.app_colors, f, &fd); super::draw(setup.area, setup.app_data.lock().config.app_colors, f, &fd);
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&EXPECTED, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0, 14..=25 | 51..=67) | (1, 1..=6 | 41..=49) => { (0, 14..=25 | 51..=67) | (1, 1..=6 | 41..=49) => {
assert_eq!(result_cell.fg, Color::Red); assert_eq!(result_cell.fg, Color::Red);
@@ -452,8 +427,7 @@ mod tests {
colors.chart_memory.points = Color::Black; colors.chart_memory.points = Color::Black;
colors.chart_memory.y_axis = Color::Blue; colors.chart_memory.y_axis = Color::Blue;
let (w, h) = (80, 10); let mut setup = test_setup(80, 10, true, true);
let mut setup = test_setup(w, h, true, true);
insert_chart_data(&setup); insert_chart_data(&setup);
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -465,10 +439,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&EXPECTED, row_index);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::White); assert_eq!(result_cell.bg, Color::White);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
+83 -95
View File
@@ -55,6 +55,7 @@ pub fn draw(
#[cfg(test)] #[cfg(test)]
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
mod tests { mod tests {
use insta::assert_snapshot;
use ratatui::style::{Color, Modifier}; use ratatui::style::{Color, Modifier};
use crate::{ use crate::{
@@ -62,16 +63,16 @@ mod tests {
tests::gen_container_summary, tests::gen_container_summary,
ui::{ ui::{
FrameData, FrameData,
draw_blocks::tests::{BORDER_CHARS, expected_to_vec, get_result, test_setup}, draw_blocks::tests::{BORDER_CHARS, get_result, test_setup},
}, },
}; };
// cusomt border colors // cusomt border colors
#[test] #[test]
/// Test that when DockerCommands are available, they are drawn correctly, dependant on container state /// Test that when DockerCommands are available, they are drawn correctly, dependant on container state
/// In this case, no commands are drawn
fn test_draw_blocks_commands_none() { fn test_draw_blocks_commands_none() {
let (w, h) = (12, 6); let mut setup = test_setup(12, 6, false, false);
let mut setup = test_setup(w, h, false, false);
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
setup setup
@@ -88,28 +89,14 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
"╭──────────╮",
"│ │",
"│ │",
"│ │",
"│ │",
"╰──────────╯",
];
for (row_index, row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (cell_index, cell) in row.iter().enumerate() {
assert_eq!(cell.symbol(), expected_row[cell_index]);
}
}
} }
#[test] #[test]
/// Test that when DockerCommands are available, they are drawn correctly, dependant on container state /// Test that when DockerCommands are available, they are drawn correctly, dependant on container state
/// In this test, container is running
fn test_draw_blocks_commands_some() { fn test_draw_blocks_commands_some() {
let (w, h) = (12, 6); let mut setup = test_setup(12, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
setup setup
@@ -126,19 +113,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
"╭──────────╮",
"│▶ pause │",
"│ restart │",
"│ stop │",
"│ delete │",
"╰──────────╯",
];
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
// Borders & delete // Borders & delete
@@ -163,22 +141,36 @@ mod tests {
} }
} }
} }
// Change the controls state }
#[test]
/// Test that when DockerCommands are available, they are drawn correctly, dependant on container state
/// In this test, container is paused
fn test_draw_blocks_commands_some_paused() {
let mut setup = test_setup(12, 6, true, true);
let colors = setup.app_data.lock().config.app_colors;
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&setup.fd,
&setup.gui_state,
);
})
.unwrap();
// Set the container state to paused
setup setup
.app_data .app_data
.lock() .lock()
.update_containers(vec![gen_container_summary(1, "paused")]); .update_containers(vec![gen_container_summary(1, "paused")]);
setup.app_data.lock().docker_controls_next(); setup.app_data.lock().docker_controls_next();
let expected = [
"╭──────────╮",
"│ resume │",
"│▶ stop │",
"│ delete │",
"│ │",
"╰──────────╯",
];
setup setup
.terminal .terminal
.draw(|f| { .draw(|f| {
@@ -193,10 +185,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
// resume // resume
@@ -222,16 +214,7 @@ mod tests {
#[test] #[test]
/// When control panel is selected, the border is blue, if not then white, selected text is highlighted /// When control panel is selected, the border is blue, if not then white, selected text is highlighted
fn test_draw_blocks_commands_panel_selected_color() { fn test_draw_blocks_commands_panel_selected_color() {
let (w, h) = (12, 6); let mut setup = test_setup(12, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭──────────╮",
"│▶ pause │",
"│ restart │",
"│ stop │",
"│ delete │",
"╰──────────╯",
];
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
// Unselected, has a grey border // Unselected, has a grey border
setup setup
@@ -248,10 +231,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (_, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for result_cell in result_row {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if BORDER_CHARS.contains(&result_cell.symbol()) { if BORDER_CHARS.contains(&result_cell.symbol()) {
assert_eq!(result_cell.fg, Color::Gray); assert_eq!(result_cell.fg, Color::Gray);
} }
@@ -275,10 +257,8 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if row_index == 0 if row_index == 0
|| row_index == 5 || row_index == 5
|| result_cell_index == 0 || result_cell_index == 0
@@ -296,10 +276,9 @@ mod tests {
} }
#[test] #[test]
/// Custom colors are rendered correctlty /// Custom colors are rendered correctly
fn test_draw_blocks_commands_custom_colors() { fn test_draw_blocks_commands_custom_colors_running() {
let (w, h) = (12, 6); let mut setup = test_setup(12, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let mut colors = AppColors::new(); let mut colors = AppColors::new();
colors.commands.background = Color::White; colors.commands.background = Color::White;
colors.commands.pause = Color::Black; colors.commands.pause = Color::Black;
@@ -323,19 +302,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
"╭──────────╮", for (row_index, result_row) in get_result(&setup) {
"│▶ pause │",
"│ restart │",
"│ stop │",
"│ delete │",
"╰──────────╯",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::White); assert_eq!(result_cell.bg, Color::White);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
// pause // pause
@@ -358,21 +327,19 @@ mod tests {
} }
} }
} }
// Change the controls state }
setup #[test]
.app_data /// Custom colors are rendered correctly
.lock() fn test_draw_blocks_commands_custom_colors_paused() {
.update_containers(vec![gen_container_summary(1, "paused")]); let mut setup = test_setup(12, 6, true, true);
setup.app_data.lock().docker_controls_next(); let mut colors = AppColors::new();
colors.commands.background = Color::White;
let expected = [ colors.commands.pause = Color::Black;
"╭──────────╮", colors.commands.restart = Color::Green;
"│ resume │", colors.commands.stop = Color::Blue;
"│▶ stop │", colors.commands.delete = Color::Magenta;
"│ delete │", colors.commands.resume = Color::Yellow;
"│ │", colors.commands.start = Color::Cyan;
"╰──────────╯",
];
setup setup
.terminal .terminal
@@ -388,10 +355,31 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { // Set the controls state
let expected_row = expected_to_vec(&expected, row_index); setup
.app_data
.lock()
.update_containers(vec![gen_container_summary(1, "paused")]);
setup.app_data.lock().docker_controls_next();
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
colors,
f,
&setup.fd,
&setup.gui_state,
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::White); assert_eq!(result_cell.bg, Color::White);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
+72 -284
View File
@@ -136,6 +136,7 @@ pub fn draw(
#[cfg(test)] #[cfg(test)]
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
mod tests { mod tests {
use insta::assert_snapshot;
use ratatui::style::{Color, Modifier}; use ratatui::style::{Color, Modifier};
use crate::{ use crate::{
@@ -144,8 +145,8 @@ mod tests {
ui::{ ui::{
FrameData, FrameData,
draw_blocks::tests::{ draw_blocks::tests::{
BORDER_CHARS, COLOR_ORANGE, COLOR_RX, COLOR_TX, TuiTestSetup, expected_to_vec, BORDER_CHARS, COLOR_ORANGE, COLOR_RX, COLOR_TX, TuiTestSetup, get_result,
get_result, test_setup, test_setup,
}, },
}, },
}; };
@@ -153,19 +154,9 @@ mod tests {
#[test] #[test]
/// No containers, panel unselected, then selected, border color changes correctly /// No containers, panel unselected, then selected, border color changes correctly
fn test_draw_blocks_containers_none() { fn test_draw_blocks_containers_none() {
let (w, h) = (25, 6); let mut setup = test_setup(40, 6, true, true);
let mut setup = test_setup(w, h, true, true);
setup.app_data.lock().containers = StatefulList::new(vec![]); setup.app_data.lock().containers = StatefulList::new(vec![]);
let expected = [
"╭ Containers ───────────╮",
"│ no containers running │",
"│ │",
"│ │",
"│ │",
"╰───────────────────────╯",
];
setup.gui_state.lock().next_panel(); setup.gui_state.lock().next_panel();
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
@@ -184,10 +175,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (_, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for result_cell in result_row {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if BORDER_CHARS.contains(&result_cell.symbol()) { if BORDER_CHARS.contains(&result_cell.symbol()) {
assert_eq!(result_cell.fg, Color::Gray); assert_eq!(result_cell.fg, Color::Gray);
} }
@@ -211,10 +201,8 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { for (_, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index); for result_cell in result_row {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if BORDER_CHARS.contains(&result_cell.symbol()) { if BORDER_CHARS.contains(&result_cell.symbol()) {
assert_eq!(result_cell.fg, Color::LightCyan); assert_eq!(result_cell.fg, Color::LightCyan);
} }
@@ -225,17 +213,8 @@ mod tests {
#[test] #[test]
/// Containers panel drawn, selected line is bold, border is blue /// Containers panel drawn, selected line is bold, border is blue
fn test_draw_blocks_containers_selected_bold() { fn test_draw_blocks_containers_selected_bold() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ✓ running Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
setup setup
@@ -252,11 +231,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if BORDER_CHARS.contains(&result_cell.symbol()) { if BORDER_CHARS.contains(&result_cell.symbol()) {
assert_eq!(result_cell.fg, Color::LightCyan); assert_eq!(result_cell.fg, Color::LightCyan);
} }
@@ -294,11 +271,8 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { for (_, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index); for result_cell in result_row {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if BORDER_CHARS.contains(&result_cell.symbol()) { if BORDER_CHARS.contains(&result_cell.symbol()) {
assert_eq!(result_cell.fg, Color::Gray); assert_eq!(result_cell.fg, Color::Gray);
} }
@@ -309,17 +283,8 @@ mod tests {
#[test] #[test]
/// Columns on all rows are coloured correctly /// Columns on all rows are coloured correctly
fn test_draw_blocks_containers_colors() { fn test_draw_blocks_containers_colors() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ✓ running Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
@@ -337,12 +302,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
//border //border
(0 | 5, _) | (1..=4, 0 | 129) => { (0 | 5, _) | (1..=4, 0 | 129) => {
@@ -373,21 +336,12 @@ mod tests {
#[test] #[test]
/// Long container + image name is truncated correctly /// Long container + image name is truncated correctly
fn test_draw_blocks_containers_long_name_image() { fn test_draw_blocks_containers_long_name_image() {
let (w, h) = (170, 6); let mut setup = test_setup(170, 6, true, true);
let mut setup = test_setup(w, h, true, true);
setup.app_data.lock().containers.items[0].name = setup.app_data.lock().containers.items[0].name =
ContainerName::from("a_long_container_name_for_the_purposes_of_this_test"); ContainerName::from("a_long_container_name_for_the_purposes_of_this_test");
setup.app_data.lock().containers.items[0].image = setup.app_data.lock().containers.items[0].image =
ContainerImage::from("a_long_image_name_for_the_purposes_of_this_test"); ContainerImage::from("a_long_image_name_for_the_purposes_of_this_test");
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ a_long_container_name_for_the… ॥ paused Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 a_long_image_name_for_the_pur… 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
setup.app_data.lock().containers.items[0].state = State::Paused; setup.app_data.lock().containers.items[0].state = State::Paused;
@@ -405,22 +359,14 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
} }
// Check that the correct colour is applied to the state/status/cpu/memory section // Check that the correct colour is applied to the state/status/cpu/memory section
fn check_expected(expected: [&str; 6], w: u16, _h: u16, setup: &TuiTestSetup, color: Color) {
for (row_index, result_row) in get_result(setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
fn check_colour(setup: &TuiTestSetup, color: Color) {
for (row_index, result_row) in get_result(setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
// border // border
(0 | 5, _) | (1..=4, 0 | 129) => { (0 | 5, _) | (1..=4, 0 | 129) => {
@@ -455,17 +401,8 @@ mod tests {
#[test] #[test]
/// When container is paused, correct colors displayed /// When container is paused, correct colors displayed
fn test_draw_blocks_containers_paused() { fn test_draw_blocks_containers_paused() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ॥ paused Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
setup.app_data.lock().containers.items[0].state = State::Paused; setup.app_data.lock().containers.items[0].state = State::Paused;
@@ -484,23 +421,14 @@ mod tests {
}) })
.unwrap(); .unwrap();
check_expected(expected, w, h, &setup, Color::Yellow); check_colour(&setup, Color::Yellow);
assert_snapshot!(setup.terminal.backend());
} }
#[test] #[test]
/// When container is dead, correct colors displayed /// When container is dead, correct colors displayed
fn test_draw_blocks_containers_dead() { fn test_draw_blocks_containers_dead() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ✖ dead Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
setup.app_data.lock().containers.items[0].state = State::Dead; setup.app_data.lock().containers.items[0].state = State::Dead;
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
@@ -519,23 +447,15 @@ mod tests {
}) })
.unwrap(); .unwrap();
check_expected(expected, w, h, &setup, Color::Red); check_colour(&setup, Color::Red);
assert_snapshot!(setup.terminal.backend());
} }
#[test] #[test]
/// When container is exited, correct colors displayed /// When container is exited, correct colors displayed
fn test_draw_blocks_containers_exited() { fn test_draw_blocks_containers_exited() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ✖ exited Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
setup.app_data.lock().containers.items[0].state = State::Exited; setup.app_data.lock().containers.items[0].state = State::Exited;
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
@@ -554,22 +474,14 @@ mod tests {
}) })
.unwrap(); .unwrap();
check_expected(expected, w, h, &setup, Color::Red); check_colour(&setup, Color::Red);
assert_snapshot!(setup.terminal.backend());
} }
#[test] #[test]
/// When container is paused, correct colors displayed /// When container is paused, correct colors displayed
fn test_draw_blocks_containers_removing() { fn test_draw_blocks_containers_removing() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 removing Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
setup.app_data.lock().containers.items[0].state = State::Removing; setup.app_data.lock().containers.items[0].state = State::Removing;
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
@@ -588,23 +500,15 @@ mod tests {
}) })
.unwrap(); .unwrap();
check_expected(expected, w, h, &setup, Color::LightRed); check_colour(&setup, Color::LightRed);
assert_snapshot!(setup.terminal.backend());
} }
#[test] #[test]
/// When container state is restarting, correct colors displayed /// When container state is restarting, correct colors displayed
fn test_draw_blocks_containers_restarting() { fn test_draw_blocks_containers_restarting() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ↻ restarting Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
setup.app_data.lock().containers.items[0].state = State::Restarting; setup.app_data.lock().containers.items[0].state = State::Restarting;
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
@@ -623,11 +527,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
// border // border
(0 | 5, _) | (1..=4, 0 | 129) => { (0 | 5, _) | (1..=4, 0 | 129) => {
@@ -664,21 +567,12 @@ mod tests {
#[test] #[test]
/// When container state is unhealthy, correct colors displayed /// When container state is unhealthy, correct colors displayed
fn test_draw_blocks_containers_unhealthy() { fn test_draw_blocks_containers_unhealthy() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let status = ContainerStatus::from("Up 1 hour (unhealthy)".to_owned()); let status = ContainerStatus::from("Up 1 hour (unhealthy)".to_owned());
setup.app_data.lock().containers.items[0].state = State::from(("running", &status)); setup.app_data.lock().containers.items[0].state = State::from(("running", &status));
setup.app_data.lock().containers.items[0].status = status; setup.app_data.lock().containers.items[0].status = status;
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ! running Up 1 hour (unhealthy) 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
@@ -696,10 +590,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
// border // border
(0 | 5, _) | (1..=4, 0 | 129) => { (0 | 5, _) | (1..=4, 0 | 129) => {
@@ -734,17 +628,8 @@ mod tests {
#[test] #[test]
/// When container state is unknown, correct colors displayed /// When container state is unknown, correct colors displayed
fn test_draw_blocks_containers_unknown() { fn test_draw_blocks_containers_unknown() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ? unknown Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
setup.app_data.lock().containers.items[0].state = State::Unknown; setup.app_data.lock().containers.items[0].state = State::Unknown;
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
@@ -763,23 +648,15 @@ mod tests {
}) })
.unwrap(); .unwrap();
check_expected(expected, w, h, &setup, Color::Red); check_colour(&setup, Color::Red);
assert_snapshot!(setup.terminal.backend());
} }
#[test] #[test]
/// Custom colors applied correctly /// Custom colors applied correctly
fn test_draw_blocks_containers_custom_colors() { fn test_draw_blocks_containers_custom_colors() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ✓ running Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let mut colors = AppColors::new(); let mut colors = AppColors::new();
colors.borders.selected = Color::Green; colors.borders.selected = Color::Green;
@@ -804,11 +681,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
// The highlight symbol can't correctly be colored // The highlight symbol can't correctly be colored
if (row_index, result_cell_index) != (1, 2) { if (row_index, result_cell_index) != (1, 2) {
assert_eq!(result_cell.bg, Color::Black); assert_eq!(result_cell.bg, Color::Black);
@@ -843,17 +718,8 @@ mod tests {
#[test] #[test]
/// Make sure that the state has the correctly color applied to it /// Make sure that the state has the correctly color applied to it
fn test_draw_blocks_containers_custom_colors_state_healthy() { fn test_draw_blocks_containers_custom_colors_state_healthy() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ✓ running Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
// Healthy // Healthy
@@ -874,11 +740,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if let (1..=3, 18..=70) = (row_index, result_cell_index) { if let (1..=3, 18..=70) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Magenta); assert_eq!(result_cell.fg, Color::Magenta);
} }
@@ -888,18 +752,8 @@ mod tests {
#[test] #[test]
/// Make sure that the state has the correctly color applied to it /// Make sure that the state has the correctly color applied to it
fn test_draw_blocks_containers_custom_colors_state_unhealthy() { fn test_draw_blocks_containers_custom_colors_state_unhealthy() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
// Unhealthy
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ! running Up 1 hour (unhealthy) 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let mut colors = AppColors::new(); let mut colors = AppColors::new();
@@ -922,11 +776,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if let (1, 18..=70) = (row_index, result_cell_index) { if let (1, 18..=70) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Red); assert_eq!(result_cell.fg, Color::Red);
} }
@@ -937,16 +789,7 @@ mod tests {
#[test] #[test]
/// Make sure that the state has the correctly color applied to it /// Make sure that the state has the correctly color applied to it
fn test_draw_blocks_containers_custom_colors_state_dead() { fn test_draw_blocks_containers_custom_colors_state_dead() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ✖ dead Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -967,12 +810,9 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if let (1, 18..=70) = (row_index, result_cell_index) { if let (1, 18..=70) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Magenta); assert_eq!(result_cell.fg, Color::Magenta);
} }
@@ -983,16 +823,7 @@ mod tests {
#[test] #[test]
/// Make sure that the state has the correctly color applied to it /// Make sure that the state has the correctly color applied to it
fn test_draw_blocks_containers_custom_colors_state_exited() { fn test_draw_blocks_containers_custom_colors_state_exited() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ✖ exited Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -1014,11 +845,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if let (1, 18..=70) = (row_index, result_cell_index) { if let (1, 18..=70) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Gray); assert_eq!(result_cell.fg, Color::Gray);
} }
@@ -1029,16 +859,7 @@ mod tests {
#[test] #[test]
/// Make sure that the state has the correctly color applied to it /// Make sure that the state has the correctly color applied to it
fn test_draw_blocks_containers_custom_colors_state_paused() { fn test_draw_blocks_containers_custom_colors_state_paused() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ॥ paused Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -1059,12 +880,10 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if let (1, 18..=70) = (row_index, result_cell_index) { if let (1, 18..=70) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Cyan); assert_eq!(result_cell.fg, Color::Cyan);
} }
@@ -1075,16 +894,7 @@ mod tests {
#[test] #[test]
/// Make sure that the state has the correctly color applied to it /// Make sure that the state has the correctly color applied to it
fn test_draw_blocks_containers_custom_colors_state_removing() { fn test_draw_blocks_containers_custom_colors_state_removing() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 removing Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -1105,12 +915,10 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if let (1, 18..=70) = (row_index, result_cell_index) { if let (1, 18..=70) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::White); assert_eq!(result_cell.fg, Color::White);
} }
@@ -1121,16 +929,7 @@ mod tests {
#[test] #[test]
/// Make sure that the state has the correctly color applied to it /// Make sure that the state has the correctly color applied to it
fn test_draw_blocks_containers_custom_colors_state_restarting() { fn test_draw_blocks_containers_custom_colors_state_restarting() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ↻ restarting Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -1152,11 +951,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if let (1, 18..=70) = (row_index, result_cell_index) { if let (1, 18..=70) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::LightYellow); assert_eq!(result_cell.fg, Color::LightYellow);
} }
@@ -1167,16 +965,7 @@ mod tests {
#[test] #[test]
/// Make sure that the state has the correctly color applied to it /// Make sure that the state has the correctly color applied to it
fn test_draw_blocks_containers_custom_colors_state_unknown() { fn test_draw_blocks_containers_custom_colors_state_unknown() {
let (w, h) = (130, 6); let mut setup = test_setup(130, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│⚪ container_1 ? unknown Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -1198,11 +987,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if let (1, 18..=70) = (row_index, result_cell_index) { if let (1, 18..=70) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, COLOR_ORANGE); assert_eq!(result_cell.fg, COLOR_ORANGE);
} }
+25 -117
View File
@@ -128,32 +128,20 @@ pub fn draw(
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
mod tests { mod tests {
use crossterm::event::KeyCode; use crossterm::event::KeyCode;
use insta::assert_snapshot;
use ratatui::style::{Color, Modifier}; use ratatui::style::{Color, Modifier};
use crate::{ use crate::{
app_data::ContainerName, app_data::ContainerName,
config::{AppColors, Keymap}, config::{AppColors, Keymap},
ui::draw_blocks::tests::{expected_to_vec, get_result, test_setup}, ui::draw_blocks::tests::{get_result, test_setup},
}; };
#[test] #[test]
/// Delete container popup is drawn correctly /// Delete container popup is drawn correctly
fn test_draw_blocks_delete() { fn test_draw_blocks_delete() {
let (w, h) = (82, 10); let mut setup = test_setup(82, 10, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
" ",
" ╭──────────────────────── Confirm Delete ────────────────────────╮ ",
" │ │ ",
" │ Are you sure you want to delete container: container_1 │ ",
" │ │ ",
" │ ╭─────────────────────╮ ╭─────────────────────╮ │ ",
" │ │ ( n ) no │ │ ( y ) yes │ │ ",
" │ ╰─────────────────────╯ ╰─────────────────────╯ │ ",
" ╰────────────────────────────────────────────────────────────────╯ ",
" ",
];
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
let keymap = &setup.app_data.lock().config.keymap; let keymap = &setup.app_data.lock().config.keymap;
@@ -170,11 +158,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0 | 9, _) | (1..=8, 0..=7 | 74..=81) => { (0 | 9, _) | (1..=8, 0..=7 | 74..=81) => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
@@ -197,23 +183,10 @@ mod tests {
#[test] #[test]
/// Delete container popup is drawn correctly /// Delete container popup is drawn correctly
fn test_draw_blocks_delete_long_name() { fn test_draw_blocks_delete_long_name() {
let (w, h) = (106, 10); let mut setup = test_setup(106, 10, true, true);
let mut setup = test_setup(w, h, true, true);
let name = ContainerName::from("container_1_container_1_container_1"); let name = ContainerName::from("container_1_container_1_container_1");
setup.app_data.lock().containers.items[0].name = name.clone(); setup.app_data.lock().containers.items[0].name = name.clone();
let expected = [
" ",
" ╭──────────────────────────────────── Confirm Delete ────────────────────────────────────╮ ",
" │ │ ",
" │ Are you sure you want to delete container: container_1_container_1_container_1 │ ",
" │ │ ",
" │ ╭──────────────────────────────╮ ╭─────────────────────────────╮ │ ",
" │ │ ( n ) no │ │ ( y ) yes │ │ ",
" │ ╰──────────────────────────────╯ ╰─────────────────────────────╯ │ ",
" ╰────────────────────────────────────────────────────────────────────────────────────────╯ ",
" ",
];
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
let keymap = &setup.app_data.lock().config.keymap; let keymap = &setup.app_data.lock().config.keymap;
@@ -223,12 +196,9 @@ mod tests {
super::draw(colors, f, &setup.gui_state, keymap, &name); super::draw(colors, f, &setup.gui_state, keymap, &name);
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0 | 9, _) | (1..=8, 0..=7 | 98..=106) => { (0 | 9, _) | (1..=8, 0..=7 | 98..=106) => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
@@ -251,21 +221,7 @@ mod tests {
#[test] #[test]
/// Custom colors applied correctly to delete popup /// Custom colors applied correctly to delete popup
fn test_draw_blocks_delete_custom_colors() { fn test_draw_blocks_delete_custom_colors() {
let (w, h) = (82, 10); let mut setup = test_setup(82, 10, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
" ",
" ╭──────────────────────── Confirm Delete ────────────────────────╮ ",
" │ │ ",
" │ Are you sure you want to delete container: container_1 │ ",
" │ │ ",
" │ ╭─────────────────────╮ ╭─────────────────────╮ │ ",
" │ │ ( n ) no │ │ ( y ) yes │ │ ",
" │ ╰─────────────────────╯ ╰─────────────────────╯ │ ",
" ╰────────────────────────────────────────────────────────────────╯ ",
" ",
];
let mut colors = AppColors::new(); let mut colors = AppColors::new();
colors.popup_delete.background = Color::Black; colors.popup_delete.background = Color::Black;
colors.popup_delete.text = Color::Yellow; colors.popup_delete.text = Color::Yellow;
@@ -284,11 +240,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0 | 9, _) | (1..=8, 0..=7 | 74..=81) => { (0 | 9, _) | (1..=8, 0..=7 | 74..=81) => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
@@ -310,22 +265,8 @@ mod tests {
#[test] #[test]
/// Custom keymap, with multiple definitions for each button, applied correctly to delete popup /// Custom keymap, with multiple definitions for each button, applied correctly to delete popup
#[allow(clippy::too_many_lines)] fn test_draw_blocks_delete_custom_keymap_one_definition() {
fn test_draw_blocks_delete_custom_keymap() { let mut setup = test_setup(82, 10, true, true);
let (w, h) = (82, 10);
let mut setup = test_setup(w, h, true, true);
let expected = [
" ",
" ╭──────────────────────── Confirm Delete ────────────────────────╮ ",
" │ │ ",
" │ Are you sure you want to delete container: container_1 │ ",
" │ │ ",
" │ ╭─────────────────────╮ ╭─────────────────────╮ │ ",
" │ │ ( End ) no │ │ ( F10 ) yes │ │ ",
" │ ╰─────────────────────╯ ╰─────────────────────╯ │ ",
" ╰────────────────────────────────────────────────────────────────╯ ",
" ",
];
let mut keymap = Keymap::new(); let mut keymap = Keymap::new();
keymap.delete_confirm = (KeyCode::F(10), None); keymap.delete_confirm = (KeyCode::F(10), None);
keymap.delete_deny = (KeyCode::End, None); keymap.delete_deny = (KeyCode::End, None);
@@ -341,25 +282,12 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
} }
} #[test]
/// Custom keymap, with multiple definitions for each button, applied correctly to delete popup
let expected = [ fn test_draw_blocks_delete_custom_keymap_two_definition() {
" ", let mut setup = test_setup(82, 10, true, true);
" ╭──────────────────────── Confirm Delete ────────────────────────╮ ",
" │ │ ",
" │ Are you sure you want to delete container: container_1 │ ",
" │ │ ",
" │ ╭─────────────────────╮ ╭─────────────────────╮ │ ",
" │ │ ( End | Up ) no │ │ ( F10 | L ) yes │ │ ",
" │ ╰─────────────────────╯ ╰─────────────────────╯ │ ",
" ╰────────────────────────────────────────────────────────────────╯ ",
" ",
];
let mut keymap = Keymap::new(); let mut keymap = Keymap::new();
keymap.delete_confirm = (KeyCode::F(10), Some(KeyCode::Char('L'))); keymap.delete_confirm = (KeyCode::F(10), Some(KeyCode::Char('L')));
keymap.delete_deny = (KeyCode::End, Some(KeyCode::Up)); keymap.delete_deny = (KeyCode::End, Some(KeyCode::Up));
@@ -375,26 +303,12 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
} }
} #[test]
/// Custom keymap, with multiple definitions for each button, applied correctly to delete popup
let expected = [ fn test_draw_blocks_delete_custom_keymap_one_two_definition() {
" ", let mut setup = test_setup(82, 10, true, true);
" ╭──────────────────────── Confirm Delete ────────────────────────╮ ",
" │ │ ",
" │ Are you sure you want to delete container: container_1 │ ",
" │ │ ",
" │ ╭─────────────────────╮ ╭─────────────────────╮ │ ",
" │ │ ( End | Up ) no │ │ ( F10 ) yes │ │ ",
" │ ╰─────────────────────╯ ╰─────────────────────╯ │ ",
" ╰────────────────────────────────────────────────────────────────╯ ",
" ",
];
let mut keymap = Keymap::new(); let mut keymap = Keymap::new();
keymap.delete_confirm = (KeyCode::F(10), None); keymap.delete_confirm = (KeyCode::F(10), None);
keymap.delete_deny = (KeyCode::End, Some(KeyCode::Up)); keymap.delete_deny = (KeyCode::End, Some(KeyCode::Up));
@@ -410,12 +324,6 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
} }
} }
+36 -139
View File
@@ -14,6 +14,9 @@ use crate::{
use super::popup; use super::popup;
const SUFFIX_CLEAR: &str = "clear error";
const SUFFIX_QUIT: &str = "quit oxker";
/// Draw an error popup over whole screen /// Draw an error popup over whole screen
pub fn draw( pub fn draw(
colors: AppColors, colors: AppColors,
@@ -36,24 +39,21 @@ pub fn draw(
seconds.unwrap_or(5) seconds.unwrap_or(5)
) )
} else { } else {
let clear_suffix = "clear error";
let clear_text = if keymap.clear == Keymap::new().clear { let clear_text = if keymap.clear == Keymap::new().clear {
format!("( {} ) {clear_suffix}", keymap.clear.0) format!("( {} ) {SUFFIX_CLEAR}", keymap.clear.0)
} else if let Some(secondary) = keymap.clear.1 { } else if let Some(secondary) = keymap.clear.1 {
format!(" ( {} | {secondary} ) {clear_suffix}", keymap.clear.0) format!(" ( {} | {secondary} ) {SUFFIX_CLEAR}", keymap.clear.0)
} else { } else {
format!(" ( {} ) {clear_suffix}", keymap.clear.0) format!(" ( {} ) {SUFFIX_CLEAR}", keymap.clear.0)
}; };
let quit_suffix = "quit oxker";
let quit_text = if keymap.quit == Keymap::new().quit { let quit_text = if keymap.quit == Keymap::new().quit {
format!("( {} ) {quit_suffix}", keymap.quit.0) format!("( {} ) {SUFFIX_QUIT}", keymap.quit.0)
} else if let Some(secondary) = keymap.quit.1 { } else if let Some(secondary) = keymap.quit.1 {
format!(" ( {} | {secondary} ) {quit_suffix}", keymap.quit.0) format!(" ( {} | {secondary} ) {SUFFIX_QUIT}", keymap.quit.0)
} else { } else {
format!(" ( {} ) {quit_suffix}", keymap.quit.0) format!(" ( {} ) {SUFFIX_QUIT}", keymap.quit.0)
}; };
format!("\n\n{clear_text}\n\n{quit_text}") format!("\n\n{clear_text}\n\n{quit_text}")
}; };
@@ -94,21 +94,19 @@ pub fn draw(
#[cfg(test)] #[cfg(test)]
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
mod tests { mod tests {
use super::VERSION;
use crate::{ use crate::{
app_error::AppError, app_error::AppError,
config::{AppColors, Keymap}, config::{AppColors, Keymap},
ui::draw_blocks::tests::{expected_to_vec, get_result, test_setup}, ui::draw_blocks::tests::{get_result, test_setup},
}; };
use crossterm::event::KeyCode; use crossterm::event::KeyCode;
use insta::assert_snapshot;
use ratatui::style::Color; use ratatui::style::Color;
#[test] #[test]
/// Test that the error popup is centered, red background, white border, white text, and displays the correct text /// Test that the error popup is centered, red background, white border, white text, and displays the correct text
fn test_draw_blocks_error_docker_connect_error() { fn test_draw_blocks_error_docker_connect_error() {
let (w, h) = (46, 9); let mut setup = test_setup(46, 9, true, true);
let mut setup = test_setup(w, h, true, true);
setup setup
.terminal .terminal
@@ -122,44 +120,24 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
let version_row = format!(" │ oxker::v{VERSION} closing in 04 seconds │ "); for (row_index, result_row) in get_result(&setup) {
let expected = [
" ",
" ╭───────────────── Error ──────────────────╮ ",
" │ │ ",
" │ Unable to access docker daemon │ ",
" │ │ ",
version_row.as_str(),
" │ │ ",
" ╰──────────────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]); if let (0 | 8, _) = (row_index, result_cell_index) {
match (row_index, result_cell_index) {
(0 | 8, _) | (1..=7, 0 | 45) => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
assert_eq!(result_cell.fg, Color::Reset); assert_eq!(result_cell.fg, Color::Reset);
} } else {
_ => {
assert_eq!(result_cell.bg, Color::Red); assert_eq!(result_cell.bg, Color::Red);
assert_eq!(result_cell.fg, Color::White); assert_eq!(result_cell.fg, Color::White);
} }
} }
} }
} }
}
#[test] #[test]
/// Test that the clearable error popup is centered, red background, white border, white text, and displays the correct text /// Test that the clearable error popup is centered, red background, white border, white text, and displays the correct text
fn test_draw_blocks_error_clearable_error() { fn test_draw_blocks_error_clearable_error() {
let (w, h) = (39, 11); let mut setup = test_setup(39, 11, true, true);
let mut setup = test_setup(w, h, true, true);
setup setup
.terminal .terminal
@@ -174,25 +152,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
" ",
" ╭────────────── Error ──────────────╮ ",
" │ │ ",
" │ Unable to exec into container │ ",
" │ │ ",
" │ ( c ) clear error │ ",
" │ │ ",
" │ ( q ) quit oxker │ ",
" │ │ ",
" ╰───────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0 | 10, _) | (1..=9, 0 | 38) => { (0 | 10, _) | (1..=9, 0 | 38) => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
@@ -211,8 +174,7 @@ mod tests {
#[test] #[test]
/// Custom colors applied to the error popup correctly /// Custom colors applied to the error popup correctly
fn test_draw_blocks_error_custom_colors() { fn test_draw_blocks_error_custom_colors() {
let (w, h) = (39, 11); let mut setup = test_setup(39, 11, true, true);
let mut setup = test_setup(w, h, true, true);
let mut colors = AppColors::new(); let mut colors = AppColors::new();
colors.popup_error.background = Color::Yellow; colors.popup_error.background = Color::Yellow;
@@ -225,25 +187,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
" ",
" ╭────────────── Error ──────────────╮ ",
" │ │ ",
" │ Unable to exec into container │ ",
" │ │ ",
" │ ( c ) clear error │ ",
" │ │ ",
" │ ( q ) quit oxker │ ",
" │ │ ",
" ╰───────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0 | 10, _) | (1..=9, 0 | 38) => { (0 | 10, _) | (1..=9, 0 | 38) => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
@@ -260,10 +207,9 @@ mod tests {
} }
#[test] #[test]
/// Custom keymap applied correct with both 1 and 2 definitions /// Custom keymap applied correctly
fn test_draw_blocks_error_custom_keymap() { fn test_draw_blocks_error_custom_keymap() {
let (w, h) = (39, 11); let mut setup = test_setup(39, 11, true, true);
let mut setup = test_setup(w, h, true, true);
let mut keymap = Keymap::new(); let mut keymap = Keymap::new();
keymap.clear = (KeyCode::BackTab, None); keymap.clear = (KeyCode::BackTab, None);
@@ -275,27 +221,12 @@ mod tests {
super::draw(AppColors::new(), &AppError::DockerExec, f, &keymap, None); super::draw(AppColors::new(), &AppError::DockerExec, f, &keymap, None);
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
let expected = [
" ",
" ╭────────────── Error ──────────────╮ ",
" │ │ ",
" │ Unable to exec into container │ ",
" │ │ ",
" │ ( Back Tab ) clear error │ ",
" │ │ ",
" │ ( F4 ) quit oxker │ ",
" │ │ ",
" ╰───────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
} }
#[test]
/// Custom keymap applied with two definitions for each option
fn test_draw_blocks_error_custom_keymap_two_definitions() {
let mut setup = test_setup(39, 11, true, true);
let mut keymap = Keymap::new(); let mut keymap = Keymap::new();
keymap.clear = (KeyCode::BackTab, Some(KeyCode::Char('m'))); keymap.clear = (KeyCode::BackTab, Some(KeyCode::Char('m')));
@@ -307,28 +238,14 @@ mod tests {
super::draw(AppColors::new(), &AppError::DockerExec, f, &keymap, None); super::draw(AppColors::new(), &AppError::DockerExec, f, &keymap, None);
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
let expected = [
" ",
" ╭────────────── Error ──────────────╮ ",
" │ │ ",
" │ Unable to exec into container │ ",
" │ │ ",
" │ ( Back Tab | m ) clear error │ ",
" │ │ ",
" │ ( F4 | End ) quit oxker │ ",
" │ │ ",
" ╰───────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
} }
#[test]
/// Custom keymap applied correctly, with 1 definition for the first option, and 2 definitions for the other
fn test_draw_blocks_error_custom_keymap_one_two_definitions() {
let mut setup = test_setup(39, 11, true, true);
let mut keymap = Keymap::new(); let mut keymap = Keymap::new();
keymap.quit = (KeyCode::F(4), Some(KeyCode::End)); keymap.quit = (KeyCode::F(4), Some(KeyCode::End));
@@ -338,26 +255,6 @@ mod tests {
super::draw(AppColors::new(), &AppError::DockerExec, f, &keymap, None); super::draw(AppColors::new(), &AppError::DockerExec, f, &keymap, None);
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
let expected = [
" ",
" ╭────────────── Error ──────────────╮ ",
" │ │ ",
" │ Unable to exec into container │ ",
" │ │ ",
" │ ( c ) clear error │ ",
" │ │ ",
" │ ( F4 | End ) quit oxker │ ",
" │ │ ",
" ╰───────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
} }
} }
+41 -37
View File
@@ -71,23 +71,22 @@ pub fn draw(area: Rect, colors: AppColors, frame: &mut Frame, fd: &FrameData) {
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
mod tests { mod tests {
use insta::assert_snapshot;
use ratatui::style::{Color, Modifier}; use ratatui::style::{Color, Modifier};
use crate::{ use crate::{
config::AppColors, config::AppColors,
ui::{ ui::{
FrameData, FrameData,
draw_blocks::tests::{expected_to_vec, get_result, test_setup}, draw_blocks::tests::{get_result, test_setup},
}, },
}; };
#[test] #[test]
#[allow(clippy::cognitive_complexity, clippy::too_many_lines)]
/// Filter row is drawn correctly & colors are correct /// Filter row is drawn correctly & colors are correct
/// Colours change when filter_by option is changed /// Colours change when filter_by option is changed
fn test_draw_blocks_filter_row() { fn test_draw_blocks_filter_row() {
let (w, h) = (140, 1); let mut setup = test_setup(140, 1, true, true);
let mut setup = test_setup(w, h, true, true);
setup setup
.gui_state .gui_state
@@ -100,15 +99,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
" Esc clear ← by → Name Image Status All term: ",
];
for (row_index, result_row) in get_result(&setup, w) { for (_, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match result_cell_index { match result_cell_index {
0..=4 | 12..=19 => { 0..=4 | 12..=19 => {
assert_eq!(result_cell.bg, Color::Magenta); assert_eq!(result_cell.bg, Color::Magenta);
@@ -134,6 +128,22 @@ mod tests {
} }
} }
} }
}
#[test]
/// Colours change when filter_by option is changed
fn test_draw_blocks_filter_row_text() {
let mut setup = test_setup(140, 1, true, true);
setup
.gui_state
.lock()
.status_push(crate::ui::Status::Filter);
setup
.terminal
.draw(|f| {
super::draw(setup.area, AppColors::new(), f, &setup.fd);
})
.unwrap();
// Test when char added to search term // Test when char added to search term
setup.app_data.lock().filter_term_push('c'); setup.app_data.lock().filter_term_push('c');
@@ -147,15 +157,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
" Esc clear ← by → Name Image Status All term: cd ",
];
for (row_index, result_row) in get_result(&setup, w) { for (_, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match result_cell_index { match result_cell_index {
0..=4 | 12..=19 => { 0..=4 | 12..=19 => {
assert_eq!(result_cell.bg, Color::Magenta); assert_eq!(result_cell.bg, Color::Magenta);
@@ -181,35 +186,39 @@ mod tests {
} }
} }
} }
}
// Test when filter_by changes #[test]
/// Colours change when filter_by option is changed
fn test_draw_blocks_filter_row_filter_by() {
let mut setup = test_setup(140, 1, true, true);
setup
.gui_state
.lock()
.status_push(crate::ui::Status::Filter);
setup.app_data.lock().filter_by_next(); setup.app_data.lock().filter_by_next();
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
setup setup
.terminal .terminal
.draw(|f| { .draw(|f| {
super::draw(setup.area, AppColors::new(), f, &fd); super::draw(setup.area, AppColors::new(), f, &setup.fd);
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
" Esc clear ← by → Name Image Status All term: cd ",
];
for (row_index, result_row) in get_result(&setup, w) { for (_, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match result_cell_index { match result_cell_index {
0..=4 | 12..=19 => { 0..=4 | 12..=19 => {
assert_eq!(result_cell.bg, Color::Magenta); assert_eq!(result_cell.bg, Color::Magenta);
assert_eq!(result_cell.fg, Color::Black); assert_eq!(result_cell.fg, Color::Black);
} }
5..=11 | 21..=26 | 34..=46 | 54..=55 => { 5..=11 | 27..=46 => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
assert_eq!(result_cell.fg, Color::Gray); assert_eq!(result_cell.fg, Color::Gray);
} }
27..=33 => { 21..=26 => {
assert_eq!(result_cell.bg, Color::Gray); assert_eq!(result_cell.bg, Color::Gray);
assert_eq!(result_cell.fg, Color::Black); assert_eq!(result_cell.fg, Color::Black);
} }
@@ -230,8 +239,7 @@ mod tests {
#[test] #[test]
/// Make sure custom colors are applied /// Make sure custom colors are applied
fn test_draw_blocks_filter_row_custom_colors() { fn test_draw_blocks_filter_row_custom_colors() {
let (w, h) = (140, 1); let mut setup = test_setup(140, 1, true, true);
let mut setup = test_setup(w, h, true, true);
setup setup
.gui_state .gui_state
@@ -256,14 +264,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
" Esc clear ← by → Name Image Status All term: cd ",
];
for (row_index, result_row) in get_result(&setup, w) { for (_, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match result_cell_index { match result_cell_index {
0..=4 | 12..=19 => { 0..=4 | 12..=19 => {
assert_eq!(result_cell.bg, Color::Blue); assert_eq!(result_cell.bg, Color::Blue);
+216 -259
View File
@@ -46,8 +46,8 @@ fn gen_header_block<'a>(colors: AppColors, fd: &FrameData, header: Header) -> (C
SortedOrder::Desc => suffix = "", SortedOrder::Desc => suffix = "",
} }
color = colors.headers_bar.text_selected; color = colors.headers_bar.text_selected;
}; }
}; }
(color, suffix) (color, suffix)
} }
@@ -222,6 +222,7 @@ mod tests {
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
use crossterm::event::KeyCode; use crossterm::event::KeyCode;
use insta::assert_snapshot;
use ratatui::style::Color; use ratatui::style::Color;
use uuid::Uuid; use uuid::Uuid;
@@ -230,22 +231,17 @@ mod tests {
config::{AppColors, Keymap}, config::{AppColors, Keymap},
ui::{ ui::{
FrameData, Status, FrameData, Status,
draw_blocks::tests::{expected_to_vec, get_result, test_setup}, draw_blocks::tests::{TuiTestSetup, get_result, test_setup},
}, },
}; };
#[test] #[test]
/// Heading back only has show/exit help when no containers, correctly coloured /// Heading back only has show/exit help when no containers, correctly coloured
fn test_draw_blocks_headers_no_containers() { fn test_draw_blocks_headers_no_containers_show_help() {
let (w, h) = (140, 1); let mut setup = test_setup(140, 1, true, true);
let mut setup = test_setup(w, h, true, true);
setup.app_data.lock().containers = StatefulList::new(vec![]); setup.app_data.lock().containers = StatefulList::new(vec![]);
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let expected = [
" ( h ) show help ",
];
setup setup
.terminal .terminal
@@ -261,19 +257,24 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (_, result_row) in get_result(&setup) {
for result_cell in result_row {
assert_eq!(result_cell.bg, Color::Magenta); assert_eq!(result_cell.bg, Color::Magenta);
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.fg, Color::Gray,); assert_eq!(result_cell.fg, Color::Gray,);
} }
} }
}
#[test]
/// Heading back only has show/exit help when no containers, correctly coloured
fn test_draw_blocks_headers_no_containers_exit_help() {
let mut setup = test_setup(140, 1, true, true);
setup.app_data.lock().containers = StatefulList::new(vec![]);
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
fd.status.insert(Status::Help); fd.status.insert(Status::Help);
let expected = [
" ( h ) exit help ",
];
setup setup
.terminal .terminal
.draw(|f| { .draw(|f| {
@@ -287,11 +288,10 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) { for (_, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index); for result_cell in result_row {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Magenta); assert_eq!(result_cell.bg, Color::Magenta);
assert_eq!(result_cell.fg, Color::Black); assert_eq!(result_cell.fg, Color::Black);
} }
@@ -301,13 +301,8 @@ mod tests {
#[test] #[test]
/// Show all headings when containers present, colors valid /// Show all headings when containers present, colors valid
fn test_draw_blocks_headers_some_containers() { fn test_draw_blocks_headers_some_containers() {
let (w, h) = (140, 1); let mut setup = test_setup(140, 1, true, true);
let mut setup = test_setup(w, h, true, true);
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let expected = [
" name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
];
setup setup
.terminal .terminal
.draw(|f| { .draw(|f| {
@@ -321,11 +316,10 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) { for (_, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Magenta); assert_eq!(result_cell.bg, Color::Magenta);
assert_eq!( assert_eq!(
result_cell.fg, result_cell.fg,
@@ -343,12 +337,9 @@ mod tests {
#[test] #[test]
/// Only show the headings that fit the reduced-in-size header section /// Only show the headings that fit the reduced-in-size header section
fn test_draw_blocks_headers_some_containers_reduced_width() { fn test_draw_blocks_headers_some_containers_reduced_width() {
let (w, h) = (80, 1); let mut setup = test_setup(80, 1, true, true);
let mut setup = test_setup(w, h, true, true);
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let expected =
[" name state status cpu ( h ) show help "];
setup setup
.terminal .terminal
.draw(|f| { .draw(|f| {
@@ -363,10 +354,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (_, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Magenta); assert_eq!(result_cell.bg, Color::Magenta);
assert_eq!( assert_eq!(
result_cell.fg, result_cell.fg,
@@ -381,204 +371,14 @@ mod tests {
} }
} }
#[test]
/// Test all combination of headers & sort by
#[allow(clippy::too_many_lines)]
fn test_draw_blocks_headers_sort_containers() {
let (w, h) = (140, 1);
let mut setup = test_setup(w, h, true, true);
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
// Actual test, used for each header and sorted type
let mut test =
|expected: &[&str], range: RangeInclusive<usize>, x: (Header, SortedOrder)| {
fd.sorted_by = Some(x);
setup
.terminal
.draw(|f| {
super::draw(
setup.area,
AppColors::new(),
f,
&fd,
&setup.gui_state,
&Keymap::new(),
);
})
.unwrap();
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Magenta);
assert_eq!(
result_cell.fg,
match result_cell_index {
0..=3 => Color::White,
122..=139 => Color::Gray,
// given range | help section
x if range.contains(&x) => Color::Gray,
112..=121 => Color::Reset,
_ => Color::Black,
}
);
}
}
};
// Name
test(
&[
" name ▲ state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
],
1..=17,
(Header::Name, SortedOrder::Asc),
);
test(
&[
" name ▼ state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
],
1..=17,
(Header::Name, SortedOrder::Desc),
);
// state
test(
&[
" name state ▲ status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
],
18..=29,
(Header::State, SortedOrder::Asc),
);
test(
&[
" name state ▼ status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
],
18..=29,
(Header::State, SortedOrder::Desc),
);
// status
test(
&[
" name state status ▲ cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
],
30..=41,
(Header::Status, SortedOrder::Asc),
);
test(
&[
" name state status ▼ cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
],
30..=41,
(Header::Status, SortedOrder::Desc),
);
// cpu
test(
&[
" name state status cpu ▲ memory/limit id image ↓ rx ↑ tx ( h ) show help ",
],
42..=50,
(Header::Cpu, SortedOrder::Asc),
);
test(
&[
" name state status cpu ▼ memory/limit id image ↓ rx ↑ tx ( h ) show help ",
],
42..=50,
(Header::Cpu, SortedOrder::Desc),
);
// memory
test(
&[
" name state status cpu memory/limit ▲ id image ↓ rx ↑ tx ( h ) show help ",
],
51..=70,
(Header::Memory, SortedOrder::Asc),
);
test(
&[
" name state status cpu memory/limit ▼ id image ↓ rx ↑ tx ( h ) show help ",
],
51..=70,
(Header::Memory, SortedOrder::Desc),
);
//id
test(
&[
" name state status cpu memory/limit id ▲ image ↓ rx ↑ tx ( h ) show help ",
],
71..=81,
(Header::Id, SortedOrder::Asc),
);
test(
&[
" name state status cpu memory/limit id ▼ image ↓ rx ↑ tx ( h ) show help ",
],
71..=81,
(Header::Id, SortedOrder::Desc),
);
// image
test(
&[
" name state status cpu memory/limit id image ▲ ↓ rx ↑ tx ( h ) show help ",
],
82..=91,
(Header::Image, SortedOrder::Asc),
);
test(
&[
" name state status cpu memory/limit id image ▼ ↓ rx ↑ tx ( h ) show help ",
],
82..=91,
(Header::Image, SortedOrder::Desc),
);
// rx
test(
&[
" name state status cpu memory/limit id image ↓ rx ▲ ↑ tx ( h ) show help ",
],
92..=101,
(Header::Rx, SortedOrder::Asc),
);
test(
&[
" name state status cpu memory/limit id image ↓ rx ▼ ↑ tx ( h ) show help ",
],
92..=101,
(Header::Rx, SortedOrder::Desc),
);
// tx
test(
&[
" name state status cpu memory/limit id image ↓ rx ↑ tx ▲ ( h ) show help ",
],
102..=111,
(Header::Tx, SortedOrder::Asc),
);
test(
&[
" name state status cpu memory/limit id image ↓ rx ↑ tx ▼ ( h ) show help ",
],
102..=111,
(Header::Tx, SortedOrder::Desc),
);
}
#[test] #[test]
/// Show animation /// Show animation
fn test_draw_blocks_headers_animation() { fn test_draw_blocks_headers_animation() {
let (w, h) = (140, 1); let mut setup = test_setup(140, 1, true, true);
let mut setup = test_setup(w, h, true, true);
let uuid = Uuid::new_v4(); let uuid = Uuid::new_v4();
setup.gui_state.lock().next_loading(uuid); setup.gui_state.lock().next_loading(uuid);
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let expected = [
" ⠙ name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
];
setup setup
.terminal .terminal
.draw(|f| { .draw(|f| {
@@ -593,10 +393,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (_, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Magenta); assert_eq!(result_cell.bg, Color::Magenta);
assert_eq!( assert_eq!(
result_cell.fg, result_cell.fg,
@@ -614,8 +413,7 @@ mod tests {
#[test] #[test]
/// Custom colors are applied correctly /// Custom colors are applied correctly
fn test_draw_blocks_headers_custom_colors() { fn test_draw_blocks_headers_custom_colors() {
let (w, h) = (140, 1); let mut setup = test_setup(140, 1, true, true);
let mut setup = test_setup(w, h, true, true);
let uuid = Uuid::new_v4(); let uuid = Uuid::new_v4();
setup.gui_state.lock().next_loading(uuid); setup.gui_state.lock().next_loading(uuid);
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -627,10 +425,6 @@ mod tests {
colors.headers_bar.text = Color::Blue; colors.headers_bar.text = Color::Blue;
colors.headers_bar.text_selected = Color::Yellow; colors.headers_bar.text_selected = Color::Yellow;
let expected = [
" ⠙ name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
];
setup setup
.terminal .terminal
.draw(|f| { .draw(|f| {
@@ -638,10 +432,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (_, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Black); assert_eq!(result_cell.bg, Color::Black);
assert_eq!( assert_eq!(
result_cell.fg, result_cell.fg,
@@ -657,18 +451,14 @@ mod tests {
} }
#[test] #[test]
/// Custom keymap for help panel is correctly display, with one and two definitions /// Custom keymap for help panel is correctly display, with one definitions
fn test_draw_blocks_headers_custom_keymap() { fn test_draw_blocks_headers_custom_keymap_one_definition() {
let (w, h) = (140, 1); let mut setup = test_setup(140, 1, true, true);
let mut setup = test_setup(w, h, true, true);
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let mut keymap = Keymap::new(); let mut keymap = Keymap::new();
keymap.toggle_help = (KeyCode::Char('T'), None); keymap.toggle_help = (KeyCode::Char('T'), None);
let expected = [
" name state status cpu memory/limit id image ↓ rx ↑ tx ( T ) show help ",
];
setup setup
.terminal .terminal
.draw(|f| { .draw(|f| {
@@ -683,17 +473,17 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
} }
#[test]
/// Custom keymap for help panel is correctly display, two definitions
fn test_draw_blocks_headers_custom_keymap_two_definitions() {
let mut setup = test_setup(140, 1, true, true);
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let mut keymap = Keymap::new();
keymap.toggle_help = (KeyCode::Char('T'), Some(KeyCode::Tab)); keymap.toggle_help = (KeyCode::Char('T'), Some(KeyCode::Tab));
let expected = [
" name state status cpu memory/limit id image ↓ rx ↑ tx ( T | Tab ) show help ",
];
setup setup
.terminal .terminal
.draw(|f| { .draw(|f| {
@@ -708,11 +498,178 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); }
fn check_color(setup: &TuiTestSetup, range: RangeInclusive<usize>) {
for (_, result_row) in get_result(setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]); assert_eq!(result_cell.bg, Color::Magenta);
assert_eq!(
result_cell.fg,
match result_cell_index {
0..=3 => Color::White,
122..=139 => Color::Gray,
// given range | help section
x if range.contains(&x) => Color::Gray,
112..=121 => Color::Reset,
_ => Color::Black,
}
);
} }
} }
} }
/// As a macro - headers test, check for asc/desc icon and colors
macro_rules! test_draw_blocks_headers_sort {
($name:ident, $header:expr, $order:expr, $color_range:expr) => {
#[test]
fn $name() {
let mut setup = test_setup(140, 1, true, true);
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
fd.sorted_by = Some(($header, $order));
setup
.terminal
.draw(|f| {
super::draw(
setup.area,
AppColors::new(),
f,
&fd,
&setup.gui_state,
&Keymap::new(),
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
check_color(&setup, $color_range);
}
};
}
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_name_asc,
Header::Name,
SortedOrder::Asc,
1..=17
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_name_desc,
Header::Name,
SortedOrder::Desc,
1..=17
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_state_asc,
Header::State,
SortedOrder::Asc,
18..=29
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_state_desc,
Header::State,
SortedOrder::Desc,
18..=29
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_status_asc,
Header::Status,
SortedOrder::Asc,
30..=41
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_status_desc,
Header::Status,
SortedOrder::Desc,
30..=41
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_cpu_asc,
Header::Cpu,
SortedOrder::Asc,
42..=50
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_cpu_desc,
Header::Cpu,
SortedOrder::Desc,
42..=50
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_memory_asc,
Header::Memory,
SortedOrder::Asc,
51..=70
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_memory_desc,
Header::Memory,
SortedOrder::Desc,
51..=70
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_id_asc,
Header::Id,
SortedOrder::Asc,
71..=81
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_id_desc,
Header::Id,
SortedOrder::Desc,
71..=81
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_image_asc,
Header::Image,
SortedOrder::Asc,
82..=91
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_image_desc,
Header::Image,
SortedOrder::Desc,
82..=91
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_rx_asc,
Header::Rx,
SortedOrder::Asc,
92..=101
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_rx_desc,
Header::Rx,
SortedOrder::Desc,
92..=101
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_tx_asc,
Header::Tx,
SortedOrder::Asc,
102..=111
);
test_draw_blocks_headers_sort!(
test_draw_blocks_headers_sort_containers_tx_desc,
Header::Tx,
SortedOrder::Desc,
102..=111
);
} }
+19 -322
View File
@@ -279,7 +279,7 @@ impl HelpInfo {
km.toggle_help, km.toggle_help,
"toggle this help information - or click heading", "toggle this help information - or click heading",
), ),
or_secondary(km.toggle_help, "save logs to file"), or_secondary(km.save_logs, "save logs to file"),
or_secondary( or_secondary(
km.toggle_mouse_capture, km.toggle_mouse_capture,
"toggle mouse capture - if disabled, text on screen can be selected & copied", "toggle mouse capture - if disabled, text on screen can be selected & copied",
@@ -415,21 +415,18 @@ pub fn draw(
#[cfg(test)] #[cfg(test)]
#[allow(clippy::unwrap_used, clippy::too_many_lines)] #[allow(clippy::unwrap_used, clippy::too_many_lines)]
mod tests { mod tests {
use crate::{ use crate::config::{AppColors, Keymap};
config::{AppColors, Keymap},
ui::draw_blocks::VERSION,
};
use crossterm::event::KeyCode; use crossterm::event::KeyCode;
use insta::assert_snapshot;
use jiff::tz::TimeZone; use jiff::tz::TimeZone;
use ratatui::style::{Color, Modifier}; use ratatui::style::{Color, Modifier};
use crate::ui::draw_blocks::tests::{expected_to_vec, get_result, test_setup}; use crate::ui::draw_blocks::tests::{get_result, test_setup};
#[test] #[test]
/// This will cause issues once the version has more than the current 5 chars (0.5.0) /// This will cause issues once the version has more than the current 5 chars (0.5.0)
fn test_draw_blocks_help() { fn test_draw_blocks_help() {
let (w, h) = (87, 33); let mut setup = test_setup(87, 33, true, true);
let mut setup = test_setup(w, h, true, true);
let tz = setup.app_data.lock().config.timezone.clone(); let tz = setup.app_data.lock().config.timezone.clone();
setup setup
@@ -445,50 +442,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let version_row = format!( assert_snapshot!(setup.terminal.backend());
" ╭ {VERSION} ────────────────────────────────────────────────────────────────────────────╮ "
);
let expected = [
" ",
version_row.as_str(),
" │ │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ ,adPPYba, 8b, ,d8 88 ,d8 ,adPPYba, 8b,dPPYba, │ ",
r#" │ a8" "8a `Y8, ,8P' 88 ,a8" a8P_____88 88P' "Y8 │ "#,
r#" │ 8b d8 )888( 8888[ 8PP""""""" 88 │ "#,
r#" │ "8a, ,a8" ,d8" "8b, 88`"Yba, "8b, ,aa 88 │ "#,
r#" │ `"YbbdP"' 8P' `Y8 88 `Y8a `"Ybbd8"' 88 │ "#,
" │ │ ",
" │ A simple tui to view & control docker containers │ ",
" │ │ ",
" │ ( tab ) or ( shift+tab ) change panels │ ",
" │ ( ↑ ↓ ) or ( j k ) or ( PgUp PgDown ) or ( Home End ) change selected line │ ",
" │ ( enter ) send docker container command │ ",
" │ ( e ) exec into a container │ ",
" │ ( h ) toggle this help information - or click heading │ ",
" │ ( s ) save logs to file │ ",
" │ ( m ) toggle mouse capture - if disabled, text on screen can be selected & copied │ ",
" │ ( F1 ) or ( / ) enter filter mode │ ",
" │ ( 0 ) stop sort │ ",
" │ ( 1 - 9 ) sort by header - or click header │ ",
" │ ( esc ) close dialog │ ",
" │ ( q ) quit at any time │ ",
" │ │ ",
" │ currently an early work in progress, all and any input appreciated │ ",
" │ https://github.com/mrjackwills/oxker │ ",
" │ │ ",
" │ │ ",
" ╰───────────────────────────────────────────────────────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
// first & last row, and first & last char on each row, is reset/reset, making sure that the help info is centered in the given area // first & last row, and first & last char on each row, is reset/reset, making sure that the help info is centered in the given area
(0 | 32, _) | (0..=33, 0 | 86) => { (0 | 32, _) | (0..=33, 0 | 86) => {
@@ -531,8 +488,7 @@ mod tests {
#[test] #[test]
/// Test that the help panel gets drawn with custom colors /// Test that the help panel gets drawn with custom colors
fn test_draw_blocks_help_custom_colors() { fn test_draw_blocks_help_custom_colors() {
let (w, h) = (87, 33); let mut setup = test_setup(87, 33, true, true);
let mut setup = test_setup(w, h, true, true);
let mut colors = AppColors::new(); let mut colors = AppColors::new();
let tz = setup.app_data.lock().config.timezone.clone(); let tz = setup.app_data.lock().config.timezone.clone();
@@ -553,50 +509,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let version_row = format!( assert_snapshot!(setup.terminal.backend());
" ╭ {VERSION} ────────────────────────────────────────────────────────────────────────────╮ "
);
let expected = [
" ",
version_row.as_str(),
" │ │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ ,adPPYba, 8b, ,d8 88 ,d8 ,adPPYba, 8b,dPPYba, │ ",
r#" │ a8" "8a `Y8, ,8P' 88 ,a8" a8P_____88 88P' "Y8 │ "#,
r#" │ 8b d8 )888( 8888[ 8PP""""""" 88 │ "#,
r#" │ "8a, ,a8" ,d8" "8b, 88`"Yba, "8b, ,aa 88 │ "#,
r#" │ `"YbbdP"' 8P' `Y8 88 `Y8a `"Ybbd8"' 88 │ "#,
" │ │ ",
" │ A simple tui to view & control docker containers │ ",
" │ │ ",
" │ ( tab ) or ( shift+tab ) change panels │ ",
" │ ( ↑ ↓ ) or ( j k ) or ( PgUp PgDown ) or ( Home End ) change selected line │ ",
" │ ( enter ) send docker container command │ ",
" │ ( e ) exec into a container │ ",
" │ ( h ) toggle this help information - or click heading │ ",
" │ ( s ) save logs to file │ ",
" │ ( m ) toggle mouse capture - if disabled, text on screen can be selected & copied │ ",
" │ ( F1 ) or ( / ) enter filter mode │ ",
" │ ( 0 ) stop sort │ ",
" │ ( 1 - 9 ) sort by header - or click header │ ",
" │ ( esc ) close dialog │ ",
" │ ( q ) quit at any time │ ",
" │ │ ",
" │ currently an early work in progress, all and any input appreciated │ ",
" │ https://github.com/mrjackwills/oxker │ ",
" │ │ ",
" │ │ ",
" ╰───────────────────────────────────────────────────────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
// first & last row, and first & last char on each row, is reset/reset, making sure that the help info is centered in the given area // first & last row, and first & last char on each row, is reset/reset, making sure that the help info is centered in the given area
(0 | 32, _) | (0..=33, 0 | 86) => { (0 | 32, _) | (0..=33, 0 | 86) => {
@@ -639,8 +555,7 @@ mod tests {
#[test] #[test]
/// Help panel will show custom keymap if in use, with one definition for each entry /// Help panel will show custom keymap if in use, with one definition for each entry
fn test_draw_blocks_help_custom_keymap_one_definition() { fn test_draw_blocks_help_custom_keymap_one_definition() {
let (w, h) = (98, 47); let mut setup = test_setup(98, 47, true, true);
let mut setup = test_setup(w, h, true, true);
let input = Keymap { let input = Keymap {
clear: (KeyCode::Char('a'), None), clear: (KeyCode::Char('a'), None),
@@ -679,72 +594,13 @@ mod tests {
}) })
.unwrap(); .unwrap();
let version_row = format!( assert_snapshot!(setup.terminal.backend());
" ╭ {VERSION} ─────────────────────────────────────────────────────────────────────────────────────╮ "
);
let expected = [
" ",
version_row.as_str(),
" │ │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ ,adPPYba, 8b, ,d8 88 ,d8 ,adPPYba, 8b,dPPYba, │ ",
r#" │ a8" "8a `Y8, ,8P' 88 ,a8" a8P_____88 88P' "Y8 │ "#,
r#" │ 8b d8 )888( 8888[ 8PP""""""" 88 │ "#,
r#" │ "8a, ,a8" ,d8" "8b, 88`"Yba, "8b, ,aa 88 │ "#,
r#" │ `"YbbdP"' 8P' `Y8 88 `Y8a `"Ybbd8"' 88 │ "#,
" │ │ ",
" │ A simple tui to view & control docker containers │ ",
" │ │ ",
" │ ( 0 ) select next panel │ ",
" │ ( 2 ) select previous panel │ ",
" │ ( q ) scroll list down by one │ ",
" │ ( y ) scroll list up by one │ ",
" │ ( o ) scroll list down by many │ ",
" │ ( w ) scroll list by up many │ ",
" │ ( s ) scroll list to end │ ",
" │ ( u ) scroll list to start │ ",
" │ ( enter ) send docker container command │ ",
" │ ( g ) exec into a container │ ",
" │ ( Home ) toggle this help information - or click heading │ ",
" │ ( Home ) save logs to file │ ",
" │ ( Page Down ) toggle mouse capture - if disabled, text on screen can be selected & copied │ ",
" │ ( i ) enter filter mode │ ",
" │ ( Up ) reset container sorting │ ",
" │ ( 4 ) sort containers by name │ ",
" │ ( 6 ) sort containers by state │ ",
" │ ( 8 ) sort containers by status │ ",
" │ ( F1 ) sort containers by cpu │ ",
" │ ( # ) sort containers by memory │ ",
" │ ( / ) sort containers by id │ ",
" │ ( , ) sort containers by image │ ",
" │ ( . ) sort containers by rx │ ",
" │ ( Backspace ) sort containers by tx │ ",
" │ ( a ) close dialog │ ",
" │ ( k ) quit at any time │ ",
" │ │ ",
" │ currently an early work in progress, all and any input appreciated │ ",
" │ https://github.com/mrjackwills/oxker │ ",
" │ │ ",
" │ │ ",
" ╰────────────────────────────────────────────────────────────────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
} }
#[test] #[test]
/// Help panel will show custom keymap if in use, with two definition for each entry /// Help panel will show custom keymap if in use, with two definition for each entry
fn test_draw_blocks_help_custom_keymap_two_definitions() { fn test_draw_blocks_help_custom_keymap_two_definitions() {
let (w, h) = (110, 47); let mut setup = test_setup(110, 47, true, true);
let mut setup = test_setup(w, h, true, true);
let keymap = Keymap { let keymap = Keymap {
clear: (KeyCode::Char('a'), Some(KeyCode::Char('b'))), clear: (KeyCode::Char('a'), Some(KeyCode::Char('b'))),
@@ -783,72 +639,13 @@ mod tests {
}) })
.unwrap(); .unwrap();
let version_row = format!( assert_snapshot!(setup.terminal.backend());
" ╭ {VERSION} ───────────────────────────────────────────────────────────────────────────────────────────────────╮ "
);
let expected = [
" ",
version_row.as_str(),
" │ │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ ,adPPYba, 8b, ,d8 88 ,d8 ,adPPYba, 8b,dPPYba, │ ",
r#" │ a8" "8a `Y8, ,8P' 88 ,a8" a8P_____88 88P' "Y8 │ "#,
r#" │ 8b d8 )888( 8888[ 8PP""""""" 88 │ "#,
r#" │ "8a, ,a8" ,d8" "8b, 88`"Yba, "8b, ,aa 88 │ "#,
r#" │ `"YbbdP"' 8P' `Y8 88 `Y8a `"Ybbd8"' 88 │ "#,
" │ │ ",
" │ A simple tui to view & control docker containers │ ",
" │ │ ",
" │ ( 0 ) or ( 1 ) select next panel │ ",
" │ ( 2 ) or ( 3 ) select previous panel │ ",
" │ ( q ) or ( r ) scroll list down by one │ ",
" │ ( y ) or ( z ) scroll list up by one │ ",
" │ ( o ) or ( p ) scroll list down by many │ ",
" │ ( w ) or ( x ) scroll list by up many │ ",
" │ ( s ) or ( t ) scroll list to end │ ",
" │ ( u ) or ( v ) scroll list to start │ ",
" │ ( enter ) send docker container command │ ",
" │ ( g ) or ( h ) exec into a container │ ",
" │ ( Home ) or ( Del ) toggle this help information - or click heading │ ",
" │ ( Home ) or ( Del ) save logs to file │ ",
" │ ( Page Down ) or ( Page Up ) toggle mouse capture - if disabled, text on screen can be selected & copied │ ",
" │ ( i ) or ( j ) enter filter mode │ ",
" │ ( Up ) or ( Down ) reset container sorting │ ",
" │ ( 4 ) or ( 5 ) sort containers by name │ ",
" │ ( 6 ) or ( 7 ) sort containers by state │ ",
" │ ( 8 ) or ( 9 ) sort containers by status │ ",
" │ ( F1 ) or ( F12 ) sort containers by cpu │ ",
" │ ( # ) or ( - ) sort containers by memory │ ",
" │ ( / ) or ( = ) sort containers by id │ ",
r" │ ( , ) or ( \ ) sort containers by image │ ",
" │ ( . ) or ( ] ) sort containers by rx │ ",
" │ ( Backspace ) or ( Back Tab ) sort containers by tx │ ",
" │ ( a ) or ( b ) close dialog │ ",
" │ ( k ) or ( l ) quit at any time │ ",
" │ │ ",
" │ currently an early work in progress, all and any input appreciated │ ",
" │ https://github.com/mrjackwills/oxker │ ",
" │ │ ",
" │ │ ",
" ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
} }
#[test] #[test]
/// Help panel will show custom keymap if in use, with either one or two definition for each entry /// Help panel will show custom keymap if in use, with either one or two definition for each entry
fn test_draw_blocks_help_one_and_two_definitions() { fn test_draw_blocks_help_one_and_two_definitions() {
let (w, h) = (110, 47); let mut setup = test_setup(110, 47, true, true);
let mut setup = test_setup(w, h, true, true);
let keymap = Keymap { let keymap = Keymap {
clear: (KeyCode::Char('a'), Some(KeyCode::Char('b'))), clear: (KeyCode::Char('a'), Some(KeyCode::Char('b'))),
@@ -889,71 +686,12 @@ mod tests {
}) })
.unwrap(); .unwrap();
let version_row = format!( assert_snapshot!(setup.terminal.backend());
" ╭ {VERSION} ───────────────────────────────────────────────────────────────────────────────────────────────────╮ "
);
let expected = [
" ",
version_row.as_str(),
" │ │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ ,adPPYba, 8b, ,d8 88 ,d8 ,adPPYba, 8b,dPPYba, │ ",
r#" │ a8" "8a `Y8, ,8P' 88 ,a8" a8P_____88 88P' "Y8 │ "#,
r#" │ 8b d8 )888( 8888[ 8PP""""""" 88 │ "#,
r#" │ "8a, ,a8" ,d8" "8b, 88`"Yba, "8b, ,aa 88 │ "#,
r#" │ `"YbbdP"' 8P' `Y8 88 `Y8a `"Ybbd8"' 88 │ "#,
" │ │ ",
" │ A simple tui to view & control docker containers │ ",
" │ │ ",
" │ ( 0 ) select next panel │ ",
" │ ( 2 ) or ( 3 ) select previous panel │ ",
" │ ( q ) or ( r ) scroll list down by one │ ",
" │ ( y ) or ( z ) scroll list up by one │ ",
" │ ( o ) scroll list down by many │ ",
" │ ( w ) scroll list by up many │ ",
" │ ( s ) scroll list to end │ ",
" │ ( u ) or ( v ) scroll list to start │ ",
" │ ( enter ) send docker container command │ ",
" │ ( g ) exec into a container │ ",
" │ ( Home ) toggle this help information - or click heading │ ",
" │ ( Home ) save logs to file │ ",
" │ ( Page Down ) or ( Page Up ) toggle mouse capture - if disabled, text on screen can be selected & copied │ ",
" │ ( i ) or ( j ) enter filter mode │ ",
" │ ( Up ) or ( Down ) reset container sorting │ ",
" │ ( 4 ) sort containers by name │ ",
" │ ( 6 ) or ( 7 ) sort containers by state │ ",
" │ ( 8 ) sort containers by status │ ",
" │ ( F1 ) or ( F12 ) sort containers by cpu │ ",
" │ ( # ) sort containers by memory │ ",
" │ ( / ) or ( = ) sort containers by id │ ",
" │ ( , ) sort containers by image │ ",
" │ ( . ) or ( ] ) sort containers by rx │ ",
" │ ( Backspace ) sort containers by tx │ ",
" │ ( a ) or ( b ) close dialog │ ",
" │ ( k ) quit at any time │ ",
" │ │ ",
" │ currently an early work in progress, all and any input appreciated │ ",
" │ https://github.com/mrjackwills/oxker │ ",
" │ │ ",
" │ │ ",
" ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
} }
#[test] #[test]
fn test_draw_blocks_help_show_timezone() { fn test_draw_blocks_help_show_timezone() {
let (w, h) = (87, 35); let mut setup = test_setup(87, 35, true, true);
let mut setup = test_setup(w, h, true, true);
setup setup
.terminal .terminal
@@ -968,49 +706,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
let version_row = format!( assert_snapshot!(setup.terminal.backend());
" ╭ {VERSION} ────────────────────────────────────────────────────────────────────────────╮ "
);
let expected = [
" ",
version_row.as_str(),
" │ │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ 88 │ ",
" │ ,adPPYba, 8b, ,d8 88 ,d8 ,adPPYba, 8b,dPPYba, │ ",
r#" │ a8" "8a `Y8, ,8P' 88 ,a8" a8P_____88 88P' "Y8 │ "#,
r#" │ 8b d8 )888( 8888[ 8PP""""""" 88 │ "#,
r#" │ "8a, ,a8" ,d8" "8b, 88`"Yba, "8b, ,aa 88 │ "#,
r#" │ `"YbbdP"' 8P' `Y8 88 `Y8a `"Ybbd8"' 88 │ "#,
" │ │ ",
" │ A simple tui to view & control docker containers │ ",
" │ │ ",
" │ logs timezone: Asia/Tokyo │ ",
" │ │ ",
" │ ( tab ) or ( shift+tab ) change panels │ ",
" │ ( ↑ ↓ ) or ( j k ) or ( PgUp PgDown ) or ( Home End ) change selected line │ ",
" │ ( enter ) send docker container command │ ",
" │ ( e ) exec into a container │ ",
" │ ( h ) toggle this help information - or click heading │ ",
" │ ( s ) save logs to file │ ",
" │ ( m ) toggle mouse capture - if disabled, text on screen can be selected & copied │ ",
" │ ( F1 ) or ( / ) enter filter mode │ ",
" │ ( 0 ) stop sort │ ",
" │ ( 1 - 9 ) sort by header - or click header │ ",
" │ ( esc ) close dialog │ ",
" │ ( q ) quit at any time │ ",
" │ │ ",
" │ currently an early work in progress, all and any input appreciated │ ",
" │ https://github.com/mrjackwills/oxker │ ",
" │ │ ",
" │ │ ",
" ╰───────────────────────────────────────────────────────────────────────────────────╯ ",
" ",
];
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(14, 31..=45) => { (14, 31..=45) => {
@@ -1021,7 +719,6 @@ mod tests {
} }
_ => (), _ => (),
} }
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
} }
} }
} }
+9 -35
View File
@@ -57,30 +57,19 @@ pub fn draw(
#[cfg(test)] #[cfg(test)]
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
mod tests { mod tests {
use insta::assert_snapshot;
use ratatui::style::Color; use ratatui::style::Color;
use crate::{ use crate::{
config::AppColors, config::AppColors,
ui::draw_blocks::tests::{expected_to_vec, get_result, test_setup}, ui::draw_blocks::tests::{get_result, test_setup},
}; };
#[test] #[test]
/// Info box drawn in bottom right /// Info box drawn in bottom right
fn test_draw_blocks_info() { fn test_draw_blocks_info() {
let (w, h) = (45, 9); let mut setup = test_setup(45, 9, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" test ",
" ",
];
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
setup setup
@@ -96,11 +85,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
let (bg, fg) = match (row_index, result_cell_index) { let (bg, fg) = match (row_index, result_cell_index) {
(6..=8, 32..=44) => (Color::Blue, Color::White), (6..=8, 32..=44) => (Color::Blue, Color::White),
_ => (Color::Reset, Color::Reset), _ => (Color::Reset, Color::Reset),
@@ -114,23 +102,11 @@ mod tests {
#[test] #[test]
/// Info box drawn in bottom right with custom colors applied /// Info box drawn in bottom right with custom colors applied
fn test_draw_blocks_info_custom_color() { fn test_draw_blocks_info_custom_color() {
let (w, h) = (45, 9); let mut setup = test_setup(45, 9, true, true);
let mut setup = test_setup(w, h, true, true);
let mut colors = AppColors::new(); let mut colors = AppColors::new();
colors.popup_info.background = Color::Red; colors.popup_info.background = Color::Red;
colors.popup_info.text = Color::Black; colors.popup_info.text = Color::Black;
let expected = [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" test ",
" ",
];
setup setup
.terminal .terminal
@@ -145,11 +121,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
let (bg, fg) = match (row_index, result_cell_index) { let (bg, fg) = match (row_index, result_cell_index) {
(6..=8, 32..=44) => (Color::Red, Color::Black), (6..=8, 32..=44) => (Color::Red, Color::Black),
_ => (Color::Reset, Color::Reset), _ => (Color::Reset, Color::Reset),
+70 -142
View File
@@ -74,6 +74,7 @@ pub fn draw(
#[cfg(test)] #[cfg(test)]
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
mod tests { mod tests {
use insta::assert_snapshot;
use ratatui::style::{Color, Modifier}; use ratatui::style::{Color, Modifier};
use uuid::Uuid; use uuid::Uuid;
@@ -82,26 +83,15 @@ mod tests {
config::AppColors, config::AppColors,
ui::{ ui::{
FrameData, Status, FrameData, Status,
draw_blocks::tests::{ draw_blocks::tests::{BORDER_CHARS, get_result, insert_logs, test_setup},
BORDER_CHARS, expected_to_vec, get_result, insert_logs, test_setup,
},
}, },
}; };
#[test] #[test]
/// No logs, panel unselected, then selected, border color changes correctly /// No logs, panel unselected, then selected, border color changes correctly
fn test_draw_blocks_logs_none() { fn test_draw_blocks_logs_none() {
let (w, h) = (35, 6); let mut setup = test_setup(35, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Logs - container_1 - image_1 ───╮",
"│ no logs found │",
"│ │",
"│ │",
"│ │",
"╰─────────────────────────────────╯",
];
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
setup setup
@@ -117,11 +107,10 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0 | 5, 0..=34) | (1..=4, 0) | (1..=5, 34) => { (0 | 5, 0..=34) | (1..=4, 0) | (1..=5, 34) => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
@@ -154,10 +143,8 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { for (_, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index); for result_cell in result_row {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
if BORDER_CHARS.contains(&result_cell.symbol()) { if BORDER_CHARS.contains(&result_cell.symbol()) {
assert_eq!(result_cell.fg, Color::LightCyan); assert_eq!(result_cell.fg, Color::LightCyan);
} }
@@ -166,22 +153,12 @@ mod tests {
} }
#[test] #[test]
/// Parsing logs, spinner visible, and then animates by one frame /// Parsing logs, first frame spinner visible
fn test_draw_blocks_logs_parsing() { fn test_draw_blocks_logs_parsing_frame_one() {
let (w, h) = (32, 6); let mut setup = test_setup(32, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let uuid = Uuid::new_v4(); let uuid = Uuid::new_v4();
setup.gui_state.lock().next_loading(uuid); setup.gui_state.lock().next_loading(uuid);
let expected = [
"╭ Logs - container_1 - image_1 ╮",
"│ parsing logs ⠙ │",
"│ │",
"│ │",
"│ │",
"╰──────────────────────────────╯",
];
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state)); let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
fd.status.insert(Status::Init); fd.status.insert(Status::Init);
@@ -199,11 +176,9 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0, 0..=31) | (1..=4, 0) | (1..=5, 31) | (5, 0..=30) => { (0, 0..=31) | (1..=4, 0) | (1..=5, 31) | (5, 0..=30) => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
@@ -216,19 +191,20 @@ mod tests {
} }
} }
} }
}
#[test]
/// Parsing logs, second frame spinner visible
fn test_draw_blocks_logs_parsing_frame_two() {
let mut setup = test_setup(32, 6, true, true);
let uuid = Uuid::new_v4();
setup.gui_state.lock().next_loading(uuid);
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
fd.status.insert(Status::Init);
// animation moved by one frame // animation moved by one frame
setup.gui_state.lock().next_loading(uuid); setup.gui_state.lock().next_loading(uuid);
let expected = [
"╭ Logs - container_1 - image_1 ╮",
"│ parsing logs ⠹ │",
"│ │",
"│ │",
"│ │",
"╰──────────────────────────────╯",
];
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state)); let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
fd.status.insert(Status::Init); fd.status.insert(Status::Init);
setup setup
@@ -245,10 +221,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0, 0..=31) | (1..=4, 0) | (1..=5, 31) | (5, 0..=30) => { (0, 0..=31) | (1..=4, 0) | (1..=5, 31) | (5, 0..=30) => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
@@ -265,9 +241,8 @@ mod tests {
#[test] #[test]
/// Logs correct displayed, changing log state also draws correctly /// Logs correct displayed, changing log state also draws correctly
fn test_draw_blocks_logs_some() { fn test_draw_blocks_logs_some_line_three() {
let (w, h) = (36, 6); let mut setup = test_setup(36, 6, true, true);
let mut setup = test_setup(w, h, true, true);
insert_logs(&setup); insert_logs(&setup);
@@ -285,19 +260,12 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
let expected = [
"╭ Logs 3/3 - container_1 - image_1 ╮",
"│ line 1 │",
"│ line 2 │",
"│▶ line 3 │",
"│ │",
"╰──────────────────────────────────╯",
];
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (row_index, result_row) in get_result(&setup) {
// let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]); // assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
if let (1..=4, 1..=34) = (row_index, result_cell_index) { if let (1..=4, 1..=34) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Reset); assert_eq!(result_cell.fg, Color::Reset);
@@ -311,7 +279,28 @@ mod tests {
} }
} }
} }
// Change selected log line }
#[test]
/// Logs correct displayed, changing log state also draws correctly
fn test_draw_blocks_logs_some_line_two() {
let mut setup = test_setup(36, 6, true, true);
insert_logs(&setup);
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
setup
.terminal
.draw(|f| {
super::draw(
&setup.app_data,
setup.area,
AppColors::new(),
f,
&fd,
&setup.gui_state,
);
})
.unwrap();
setup.app_data.lock().log_previous(); setup.app_data.lock().log_previous();
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -329,19 +318,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
"╭ Logs 2/3 - container_1 - image_1 ╮",
"│ line 1 │",
"│▶ line 2 │",
"│ line 3 │",
"│ │",
"╰──────────────────────────────────╯",
];
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
if let (1..=4, 1..=34) = (row_index, result_cell_index) { if let (1..=4, 1..=34) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Reset); assert_eq!(result_cell.fg, Color::Reset);
@@ -360,23 +340,13 @@ mod tests {
#[test] #[test]
/// Full (long) name displayed in logs border /// Full (long) name displayed in logs border
fn test_draw_blocks_logs_long_name() { fn test_draw_blocks_logs_long_name() {
let (w, h) = (80, 6); let mut setup = test_setup(80, 6, true, true);
let mut setup = test_setup(w, h, true, true);
setup.app_data.lock().containers.items[0].name = setup.app_data.lock().containers.items[0].name =
ContainerName::from("a_long_container_name_for_the_purposes_of_this_test"); ContainerName::from("a_long_container_name_for_the_purposes_of_this_test");
setup.app_data.lock().containers.items[0].image = setup.app_data.lock().containers.items[0].image =
ContainerImage::from("a_long_image_name_for_the_purposes_of_this_test"); ContainerImage::from("a_long_image_name_for_the_purposes_of_this_test");
insert_logs(&setup); insert_logs(&setup);
let expected = [
"╭ Logs 3/3 - a_long_container_name_for_the_purposes_of_this_test - a_long_image╮",
"│ line 1 │",
"│ line 2 │",
"│▶ line 3 │",
"│ │",
"╰──────────────────────────────────────────────────────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
setup setup
@@ -393,30 +363,15 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
} }
#[test] #[test]
fn test_draw_blocks_logs_custom_colors_parsing() { fn test_draw_blocks_logs_custom_colors_parsing() {
let (w, h) = (32, 6); let mut setup = test_setup(32, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let uuid = Uuid::new_v4(); let uuid = Uuid::new_v4();
setup.gui_state.lock().next_loading(uuid); setup.gui_state.lock().next_loading(uuid);
let expected = [
"╭ Logs - container_1 - image_1 ╮",
"│ parsing logs ⠙ │",
"│ │",
"│ │",
"│ │",
"╰──────────────────────────────╯",
];
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state)); let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
fd.status.insert(Status::Init); fd.status.insert(Status::Init);
@@ -438,11 +393,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Green); assert_eq!(result_cell.bg, Color::Green);
if let (1..=4, 1..=29) = (row_index, result_cell_index) { if let (1..=4, 1..=29) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Black); assert_eq!(result_cell.fg, Color::Black);
@@ -466,11 +420,8 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
if let (1..=4, 1..=29) = (row_index, result_cell_index) { if let (1..=4, 1..=29) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Reset); assert_eq!(result_cell.fg, Color::Reset);
@@ -482,17 +433,8 @@ mod tests {
#[test] #[test]
fn test_draw_blocks_logs_custom_colors_no_logs() { fn test_draw_blocks_logs_custom_colors_no_logs() {
let (w, h) = (35, 6); let mut setup = test_setup(35, 6, true, true);
let mut setup = test_setup(w, h, true, true);
let expected = [
"╭ Logs - container_1 - image_1 ───╮",
"│ no logs found │",
"│ │",
"│ │",
"│ │",
"╰─────────────────────────────────╯",
];
let mut colors = AppColors::new(); let mut colors = AppColors::new();
colors.logs.background = Color::Green; colors.logs.background = Color::Green;
colors.logs.text = Color::Black; colors.logs.text = Color::Black;
@@ -511,10 +453,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Green); assert_eq!(result_cell.bg, Color::Green);
if let (1..=4, 1..=29) = (row_index, result_cell_index) { if let (1..=4, 1..=29) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Black); assert_eq!(result_cell.fg, Color::Black);
@@ -537,10 +479,8 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
if let (1..=4, 1..=29) = (row_index, result_cell_index) { if let (1..=4, 1..=29) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Reset); assert_eq!(result_cell.fg, Color::Reset);
@@ -552,8 +492,7 @@ mod tests {
#[test] #[test]
/// Logs correct displayed with custom colors /// Logs correct displayed with custom colors
fn test_draw_blocks_logs_custom_colors_logs() { fn test_draw_blocks_logs_custom_colors_logs() {
let (w, h) = (36, 6); let mut setup = test_setup(36, 6, true, true);
let mut setup = test_setup(w, h, true, true);
insert_logs(&setup); insert_logs(&setup);
let mut colors = setup.app_data.lock().config.app_colors; let mut colors = setup.app_data.lock().config.app_colors;
@@ -576,19 +515,10 @@ mod tests {
); );
}) })
.unwrap(); .unwrap();
let expected = [
"╭ Logs 3/3 - container_1 - image_1 ╮",
"│ line 1 │",
"│ line 2 │",
"│▶ line 3 │",
"│ │",
"╰──────────────────────────────────╯",
];
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index); for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
if let (1..=4, 1..=34) = (row_index, result_cell_index) { if let (1..=4, 1..=34) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Reset); assert_eq!(result_cell.fg, Color::Reset);
@@ -617,10 +547,8 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Green); assert_eq!(result_cell.bg, Color::Green);
if let (1..=4, 1..=34) = (row_index, result_cell_index) { if let (1..=4, 1..=34) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Black); assert_eq!(result_cell.fg, Color::Black);
+10 -180
View File
@@ -117,6 +117,7 @@ pub mod tests {
sync::Arc, sync::Arc,
}; };
use insta::assert_snapshot;
use parking_lot::Mutex; use parking_lot::Mutex;
use ratatui::{Terminal, backend::TestBackend, layout::Rect, style::Color}; use ratatui::{Terminal, backend::TestBackend, layout::Rect, style::Color};
@@ -211,25 +212,17 @@ pub mod tests {
} }
} }
/// Get a single row of String's from the expected data
pub fn expected_to_vec(expected: &[&str], row_index: usize) -> Vec<String> {
expected[row_index]
.chars()
.map(|i| i.to_string())
.collect::<Vec<_>>()
}
/// Just a shorthand for when enumerating over result cells /// Just a shorthand for when enumerating over result cells
pub fn get_result( pub fn get_result(
setup: &TuiTestSetup, setup: &TuiTestSetup,
w: u16, // w: u16,
) -> std::iter::Enumerate<std::slice::Chunks<ratatui::buffer::Cell>> { ) -> std::iter::Enumerate<std::slice::Chunks<ratatui::buffer::Cell>> {
setup setup
.terminal .terminal
.backend() .backend()
.buffer() .buffer()
.content .content
.chunks(usize::from(w)) .chunks(usize::from(setup.area.width))
.enumerate() .enumerate()
} }
@@ -270,8 +263,7 @@ pub mod tests {
#[test] #[test]
/// Check that the whole layout is drawn correctly /// Check that the whole layout is drawn correctly
fn test_draw_blocks_whole_layout() { fn test_draw_blocks_whole_layout() {
let (w, h) = (160, 30); let mut setup = test_setup(160, 30, true, true);
let mut setup = test_setup(w, h, true, true);
insert_chart_data(&setup); insert_chart_data(&setup);
insert_logs(&setup); insert_logs(&setup);
@@ -282,39 +274,6 @@ pub mod tests {
private: 8003, private: 8003,
public: Some(8003), public: Some(8003),
}); });
let expected = [
" name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
"╭ Containers 1/3 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮╭──────────────╮",
"│⚪ container_1 ✓ running Up 1 hour 03.00% 30.00 kB / 30.00 kB 1 image_1 0.00 kB 0.00 kB ││▶ pause │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB ││ restart │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB ││ stop │",
"│ ││ delete │",
"│ ││ │",
"│ ││ │",
"╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯╰──────────────╯",
"╭ Logs 3/3 - container_1 - image_1 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│ line 1 │",
"│ line 2 │",
"│▶ line 3 │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
"╭───────────────────────── cpu 03.00% ──────────────────────────╮╭─────────────────────── memory 30.00 kB ───────────────────────╮╭────────── ports ───────────╮",
"│10.00%│ •••• ││100.00 kB│ ••• ││ ip private public│",
"│ │ ••• • ││ │ ••• • ││ 8001 │",
"│ │•• ••• ││ │•• ••• ││127.0.0.1 8003 8003│",
"│ │ ││ │ ││ │",
"╰───────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
];
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
let keymap = setup.app_data.lock().config.keymap.clone(); let keymap = setup.app_data.lock().config.keymap.clone();
@@ -326,20 +285,14 @@ pub mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
} }
#[test] #[test]
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
/// Check that the whole layout is drawn correctly /// Check that the whole layout is drawn correctly
fn test_draw_blocks_whole_layout_with_filter() { fn test_draw_blocks_whole_layout_with_filter_bar() {
let (w, h) = (160, 30); let mut setup = test_setup(160, 30, true, true);
let mut setup = test_setup(w, h, true, true);
insert_chart_data(&setup); insert_chart_data(&setup);
insert_logs(&setup); insert_logs(&setup);
@@ -351,55 +304,8 @@ pub mod tests {
public: Some(8003), public: Some(8003),
}); });
let expected = [
" name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
"╭ Containers 1/3 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮╭──────────────╮",
"│⚪ container_1 ✓ running Up 1 hour 03.00% 30.00 kB / 30.00 kB 1 image_1 0.00 kB 0.00 kB ││▶ pause │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB ││ restart │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB ││ stop │",
"│ ││ delete │",
"│ ││ │",
"│ ││ │",
"╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯╰──────────────╯",
"╭ Logs 3/3 - container_1 - image_1 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│ line 1 │",
"│ line 2 │",
"│▶ line 3 │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
"╭───────────────────────── cpu 03.00% ──────────────────────────╮╭─────────────────────── memory 30.00 kB ───────────────────────╮╭────────── ports ───────────╮",
"│10.00%│ •••• ││100.00 kB│ ••• ││ ip private public│",
"│ │ ••• • ││ │ ••• • ││ 8001 │",
"│ │•• ••• ││ │•• ••• ││ │",
"│ │ ││ │ ││ │",
"╰───────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
let keymap = setup.app_data.lock().config.keymap.clone(); let keymap = setup.app_data.lock().config.keymap.clone();
setup
.terminal
.draw(|f| {
draw_frame(&setup.app_data, colors, &keymap, f, &fd, &setup.gui_state);
})
.unwrap();
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
setup setup
.gui_state .gui_state
.lock() .lock()
@@ -407,39 +313,6 @@ pub mod tests {
setup.app_data.lock().filter_term_push('r'); setup.app_data.lock().filter_term_push('r');
setup.app_data.lock().filter_term_push('_'); setup.app_data.lock().filter_term_push('_');
setup.app_data.lock().filter_term_push('1'); setup.app_data.lock().filter_term_push('1');
let expected = [
" name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
"╭ Containers 1/1 - filtered ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮╭──────────────╮",
"│⚪ container_1 ✓ running Up 1 hour 03.00% 30.00 kB / 30.00 kB 1 image_1 0.00 kB 0.00 kB ││▶ pause │",
"│ ││ restart │",
"│ ││ stop │",
"│ ││ delete │",
"╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯╰──────────────╯",
"╭ Logs 3/3 - container_1 - image_1 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮",
"│ line 1 │",
"│ line 2 │",
"│▶ line 3 │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
"╭───────────────────────── cpu 03.00% ──────────────────────────╮╭─────────────────────── memory 30.00 kB ───────────────────────╮╭────────── ports ───────────╮",
"│10.00%│ ••• ││100.00 kB│ •• ││ ip private public│",
"│ │ •• • ││ │ •• • ││ 8001 │",
"│ │ ••• • • ││ │ ••• • • ││ │",
"│ │• •• ││ │• •• ││ │",
"│ │ ││ │ ││ │",
"╰───────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
" Esc clear ← by → Name Image Status All term: r_1 ",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
setup setup
.terminal .terminal
@@ -448,19 +321,13 @@ pub mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
} }
#[test] #[test]
/// Check that the whole layout is drawn correctly when have long container name and long image name /// Check that the whole layout is drawn correctly when have long container name and long image name
fn test_draw_blocks_whole_layout_long_name() { fn test_draw_blocks_whole_layout_long_name() {
let (w, h) = (190, 30); let mut setup = test_setup(190, 30, true, true);
let mut setup = test_setup(w, h, true, true);
insert_chart_data(&setup); insert_chart_data(&setup);
insert_logs(&setup); insert_logs(&setup);
@@ -477,38 +344,6 @@ pub mod tests {
setup.app_data.lock().containers.items[0].image = setup.app_data.lock().containers.items[0].image =
ContainerImage::from("a_long_image_name_for_the_purposes_of_this_test"); ContainerImage::from("a_long_image_name_for_the_purposes_of_this_test");
let expected = [
" name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help ",
"╭ Containers 1/3 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮╭─────────────────╮",
"│⚪ a_long_container_name_for_the… ✓ running Up 1 hour 03.00% 30.00 kB / 30.00 kB 1 a_long_image_name_for_the_pur… 0.00 kB 0.00 kB ││▶ pause │",
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB ││ restart │",
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB ││ stop │",
"│ ││ delete │",
"│ ││ │",
"│ ││ │",
"╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯╰─────────────────╯",
"╭ Logs 3/3 - a_long_container_name_for_the_purposes_of_this_test - a_long_image_name_for_the_purposes_of_this_test ──────────────────────────────────────────────────────────────────────────╮",
"│ line 1 │",
"│ line 2 │",
"│▶ line 3 │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯",
"╭───────────────────────────────── cpu 03.00% ─────────────────────────────────╮╭────────────────────────────── memory 30.00 kB ───────────────────────────────╮╭────────── ports ───────────╮",
"│10.00%│ •••• ││100.00 kB│ ••••• ││ ip private public│",
"│ │ •••• • ││ │ ••• • ││ 8001 │",
"│ │••• •••• ││ │••• ••• ││127.0.0.1 8003 8003│",
"│ │ ││ │ ││ │",
"╰──────────────────────────────────────────────────────────────────────────────╯╰──────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
let colors = setup.app_data.lock().config.app_colors; let colors = setup.app_data.lock().config.app_colors;
let keymap = setup.app_data.lock().config.keymap.clone(); let keymap = setup.app_data.lock().config.keymap.clone();
@@ -519,11 +354,6 @@ pub mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
}
}
} }
} }
+38 -101
View File
@@ -76,6 +76,7 @@ pub fn draw(area: Rect, colors: AppColors, f: &mut Frame, fd: &FrameData) {
mod tests { mod tests {
use std::net::{IpAddr, Ipv4Addr}; use std::net::{IpAddr, Ipv4Addr};
use insta::assert_snapshot;
use ratatui::style::{Color, Modifier}; use ratatui::style::{Color, Modifier};
use crate::{ use crate::{
@@ -83,17 +84,14 @@ mod tests {
config::AppColors, config::AppColors,
ui::{ ui::{
FrameData, FrameData,
draw_blocks::tests::{ draw_blocks::tests::{COLOR_ORANGE, COLOR_RX, COLOR_TX, get_result, test_setup},
COLOR_ORANGE, COLOR_RX, COLOR_TX, expected_to_vec, get_result, test_setup,
},
}, },
}; };
#[test] #[test]
/// Port section when container has no ports /// Port section when container has no ports
fn test_draw_blocks_ports_no_ports() { fn test_draw_blocks_ports_no_ports() {
let (w, h) = (30, 8); let mut setup = test_setup(30, 8, true, true);
let mut setup = test_setup(w, h, true, true);
setup.app_data.lock().containers.items[0].ports = vec![]; setup.app_data.lock().containers.items[0].ports = vec![];
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -103,22 +101,10 @@ mod tests {
super::draw(setup.area, setup.app_data.lock().config.app_colors, f, &fd); super::draw(setup.area, setup.app_data.lock().config.app_colors, f, &fd);
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
let expected = [ for (row_index, result_row) in get_result(&setup) {
"╭────────── ports ───────────╮",
"│ no ports │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"╰────────────────────────────╯",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
(0, 11..=17) => { (0, 11..=17) => {
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
@@ -138,8 +124,24 @@ mod tests {
} }
} }
} }
}
#[test]
/// Port section when container has no ports
// When state is "State::Running | State::Paused | State::Restarting, won't show "no ports" // When state is "State::Running | State::Paused | State::Restarting, won't show "no ports"
fn test_draw_blocks_ports_no_ports_dead() {
let mut setup = test_setup(30, 8, true, true);
setup.app_data.lock().containers.items[0].ports = vec![];
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
setup
.terminal
.draw(|f| {
super::draw(setup.area, setup.app_data.lock().config.app_colors, f, &fd);
})
.unwrap();
// split
setup.app_data.lock().containers.items[0].state = State::Dead; setup.app_data.lock().containers.items[0].state = State::Dead;
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
@@ -150,21 +152,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
"╭────────── ports ───────────╮",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"│ │",
"╰────────────────────────────╯",
];
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
if let (0, 11..=17) = (row_index, result_cell_index) { if let (0, 11..=17) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Red); assert_eq!(result_cell.fg, Color::Red);
@@ -180,8 +171,7 @@ mod tests {
#[test] #[test]
/// Port section when container has multiple ports /// Port section when container has multiple ports
fn test_draw_blocks_ports_multiple_ports() { fn test_draw_blocks_ports_multiple_ports() {
let (w, h) = (32, 8); let mut setup = test_setup(32, 8, true, true);
let mut setup = test_setup(w, h, true, true);
setup.app_data.lock().containers.items[0] setup.app_data.lock().containers.items[0]
.ports .ports
.push(ContainerPorts { .push(ContainerPorts {
@@ -204,22 +194,10 @@ mod tests {
super::draw(setup.area, setup.app_data.lock().config.app_colors, f, &fd); super::draw(setup.area, setup.app_data.lock().config.app_colors, f, &fd);
}) })
.unwrap(); .unwrap();
assert_snapshot!(setup.terminal.backend());
let expected = [ for (row_index, result_row) in get_result(&setup) {
"╭─────────── ports ────────────╮",
"│ ip private public │",
"│ 8001 │",
"│ 8002 │",
"│127.0.0.1 8003 8003 │",
"│ │",
"│ │",
"╰──────────────────────────────╯",
];
for (row_index, result_row) in get_result(&setup, w) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
@@ -247,8 +225,7 @@ mod tests {
#[test] #[test]
/// Port section title color correct dependant on state /// Port section title color correct dependant on state
fn test_draw_blocks_ports_container_state() { fn test_draw_blocks_ports_container_state() {
let (w, h) = (32, 8); let mut setup = test_setup(32, 8, true, true);
let mut setup = test_setup(w, h, true, true);
let fd = FrameData::from((&setup.app_data, &setup.gui_state)); let fd = FrameData::from((&setup.app_data, &setup.gui_state));
setup setup
@@ -258,21 +235,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
"╭─────────── ports ────────────╮",
"│ ip private public │",
"│ 8001 │",
"│ │",
"│ │",
"│ │",
"│ │",
"╰──────────────────────────────╯",
];
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
if let (0, 12..=18) = (row_index, result_cell_index) { if let (0, 12..=18) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Green); assert_eq!(result_cell.fg, Color::Green);
@@ -290,10 +256,8 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
if let (0, 12..=18) = (row_index, result_cell_index) { if let (0, 12..=18) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Yellow); assert_eq!(result_cell.fg, Color::Yellow);
@@ -311,10 +275,8 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Reset); assert_eq!(result_cell.bg, Color::Reset);
if let (0, 12..=18) = (row_index, result_cell_index) { if let (0, 12..=18) = (row_index, result_cell_index) {
assert_eq!(result_cell.fg, Color::Red); assert_eq!(result_cell.fg, Color::Red);
@@ -327,8 +289,7 @@ mod tests {
#[test] #[test]
/// Custom colors applied to ports panel /// Custom colors applied to ports panel
fn test_draw_blocks_ports_custom_colors() { fn test_draw_blocks_ports_custom_colors() {
let (w, h) = (32, 8); let mut setup = test_setup(32, 8, true, true);
let mut setup = test_setup(w, h, true, true);
let mut colors = AppColors::new(); let mut colors = AppColors::new();
colors.chart_ports.background = Color::Black; colors.chart_ports.background = Color::Black;
@@ -345,21 +306,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let expected = [ assert_snapshot!(setup.terminal.backend());
"╭─────────── ports ────────────╮",
"│ ip private public │",
"│ 8001 │",
"│ │",
"│ │",
"│ │",
"│ │",
"╰──────────────────────────────╯",
];
for (row_index, result_row) in get_result(&setup, w) { for (row_index, result_row) in get_result(&setup) {
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() { for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
assert_eq!(result_cell.bg, Color::Black); assert_eq!(result_cell.bg, Color::Black);
match (row_index, result_cell_index) { match (row_index, result_cell_index) {
@@ -387,8 +337,7 @@ mod tests {
#[test] #[test]
// Custom state color applied to ports panel title // Custom state color applied to ports panel title
fn test_draw_blocks_ports_custom_colors_state() { fn test_draw_blocks_ports_custom_colors_state() {
let (w, h) = (32, 8); let mut setup = test_setup(32, 8, true, true);
let mut setup = test_setup(w, h, true, true);
let mut colors = AppColors::new(); let mut colors = AppColors::new();
colors.container_state.dead = Color::Green; colors.container_state.dead = Color::Green;
@@ -402,17 +351,6 @@ mod tests {
colors.chart_ports.title = Color::DarkGray; colors.chart_ports.title = Color::DarkGray;
let expected = [
"╭─────────── ports ────────────╮",
"│ ip private public │",
"│ 8001 │",
"│ │",
"│ │",
"│ │",
"│ │",
"╰──────────────────────────────╯",
];
for i in [ for i in [
(State::Dead, Color::Green), (State::Dead, Color::Green),
(State::Exited, Color::Magenta), (State::Exited, Color::Magenta),
@@ -433,11 +371,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
for (row_index, result_row) in get_result(&setup, w) { // assert_snapshot!(setup.terminal.backend());
let expected_row = expected_to_vec(&expected, row_index);
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
assert_eq!(result_cell.symbol(), expected_row[result_cell_index]);
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
if row_index == 0 && (12..=18).contains(&result_cell_index) { if row_index == 0 && (12..=18).contains(&result_cell_index) {
assert_eq!(result_cell.fg, i.1); assert_eq!(result_cell.fg, i.1);
} }
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/charts.rs
expression: setup.terminal.backend()
---
"╭───────────── cpu 03.00% ─────────────╮╭────────── memory 30.00 kB ───────────╮"
"│10.00%│ • ││100.00 kB│ •• │"
"│ │ •• ││ │ •• │"
"│ │ ••• ││ │ • • │"
"│ │ • • ││ │ • • │"
"│ │ • •• ││ │•• •• │"
"│ │• • ││ │• • │"
"│ │• • ││ │• • │"
"│ │ ││ │ │"
"╰──────────────────────────────────────╯╰──────────────────────────────────────╯"
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/charts.rs
expression: setup.terminal.backend()
---
"╭───────────── cpu 03.00% ─────────────╮╭────────── memory 30.00 kB ───────────╮"
"│10.00%│ • ││100.00 kB│ •• │"
"│ │ •• ││ │ •• │"
"│ │ ••• ││ │ • • │"
"│ │ • • ││ │ • • │"
"│ │ • •• ││ │•• •• │"
"│ │• • ││ │• • │"
"│ │• • ││ │• • │"
"│ │ ││ │ │"
"╰──────────────────────────────────────╯╰──────────────────────────────────────╯"
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/charts.rs
expression: setup.terminal.backend()
---
"╭───────────── cpu 03.00% ─────────────╮╭────────── memory 30.00 kB ───────────╮"
"│10.00%│ • ││100.00 kB│ •• │"
"│ │ •• ││ │ •• │"
"│ │ ••• ││ │ • • │"
"│ │ • • ││ │ • • │"
"│ │ • •• ││ │•• •• │"
"│ │• • ││ │• • │"
"│ │• • ││ │• • │"
"│ │ ││ │ │"
"╰──────────────────────────────────────╯╰──────────────────────────────────────╯"
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/charts.rs
expression: setup.terminal.backend()
---
"╭───────────── cpu 00.00% ─────────────╮╭─────────── memory 0.00 kB ───────────╮"
"│00.00%│ ││0.00 kB│ │"
"│ │ ││ │ │"
"│ │ ││ │ │"
"│ │ ││ │ │"
"│ │ ││ │ │"
"│ │ ││ │ │"
"│ │ ││ │ │"
"│ │ ││ │ │"
"╰──────────────────────────────────────╯╰──────────────────────────────────────╯"
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/charts.rs
expression: setup.terminal.backend()
---
"╭───────────── cpu 03.00% ─────────────╮╭────────── memory 30.00 kB ───────────╮"
"│10.00%│ • ││100.00 kB│ •• │"
"│ │ •• ││ │ •• │"
"│ │ ••• ││ │ • • │"
"│ │ • • ││ │ • • │"
"│ │ • •• ││ │•• •• │"
"│ │• • ││ │• • │"
"│ │• • ││ │• • │"
"│ │ ││ │ │"
"╰──────────────────────────────────────╯╰──────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/commands.rs
expression: setup.terminal.backend()
---
"╭──────────╮"
"│ resume │"
"│▶ stop │"
"│ delete │"
"│ │"
"╰──────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/commands.rs
expression: setup.terminal.backend()
---
"╭──────────╮"
"│▶ pause │"
"│ restart │"
"│ stop │"
"│ delete │"
"╰──────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/commands.rs
expression: setup.terminal.backend()
---
"╭──────────╮"
"│ │"
"│ │"
"│ │"
"│ │"
"╰──────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/commands.rs
expression: setup.terminal.backend()
---
"╭──────────╮"
"│▶ pause │"
"│ restart │"
"│ stop │"
"│ delete │"
"╰──────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/commands.rs
expression: setup.terminal.backend()
---
"╭──────────╮"
"│▶ pause │"
"│ restart │"
"│ stop │"
"│ delete │"
"╰──────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/commands.rs
expression: setup.terminal.backend()
---
"╭──────────╮"
"│ resume │"
"│▶ stop │"
"│ delete │"
"│ │"
"╰──────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ✓ running Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ✓ running Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ✖ dead Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ✖ exited Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ✓ running Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ॥ paused Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 removing Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ↻ restarting Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ! running Up 1 hour (unhealthy) 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ? unknown Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ✖ dead Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ✖ exited Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ a_long_container_name_for_the… ॥ paused Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 a_long_image_name_for_the_pur… 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers ──────────────────────────╮"
"│ no containers running │"
"│ │"
"│ │"
"│ │"
"╰──────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ॥ paused Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 removing Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ↻ restarting Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ✓ running Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ! running Up 1 hour (unhealthy) 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,10 @@
---
source: src/ui/draw_blocks/containers.rs
expression: setup.terminal.backend()
---
"╭ Containers 1/3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮"
"│⚪ container_1 ? unknown Up 1 hour 00.00% 0.00 kB / 0.00 kB 1 image_1 0.00 kB 0.00 kB │" Hidden by multi-width symbols: [(2, " ")]
"│ container_2 ✓ running Up 2 hour 00.00% 0.00 kB / 0.00 kB 2 image_2 0.00 kB 0.00 kB │"
"│ container_3 ✓ running Up 3 hour 00.00% 0.00 kB / 0.00 kB 3 image_3 0.00 kB 0.00 kB │"
"│ │"
"╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/delete_confirm.rs
expression: setup.terminal.backend()
---
" "
" ╭──────────────────────── Confirm Delete ────────────────────────╮ "
" │ │ "
" │ Are you sure you want to delete container: container_1 │ "
" │ │ "
" │ ╭─────────────────────╮ ╭─────────────────────╮ │ "
" │ │ ( n ) no │ │ ( y ) yes │ │ "
" │ ╰─────────────────────╯ ╰─────────────────────╯ │ "
" ╰────────────────────────────────────────────────────────────────╯ "
" "
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/delete_confirm.rs
expression: setup.terminal.backend()
---
" "
" ╭──────────────────────── Confirm Delete ────────────────────────╮ "
" │ │ "
" │ Are you sure you want to delete container: container_1 │ "
" │ │ "
" │ ╭─────────────────────╮ ╭─────────────────────╮ │ "
" │ │ ( n ) no │ │ ( y ) yes │ │ "
" │ ╰─────────────────────╯ ╰─────────────────────╯ │ "
" ╰────────────────────────────────────────────────────────────────╯ "
" "
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/delete_confirm.rs
expression: setup.terminal.backend()
---
" "
" ╭──────────────────────── Confirm Delete ────────────────────────╮ "
" │ │ "
" │ Are you sure you want to delete container: container_1 │ "
" │ │ "
" │ ╭─────────────────────╮ ╭─────────────────────╮ │ "
" │ │ ( End ) no │ │ ( F10 ) yes │ │ "
" │ ╰─────────────────────╯ ╰─────────────────────╯ │ "
" ╰────────────────────────────────────────────────────────────────╯ "
" "
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/delete_confirm.rs
expression: setup.terminal.backend()
---
" "
" ╭──────────────────────── Confirm Delete ────────────────────────╮ "
" │ │ "
" │ Are you sure you want to delete container: container_1 │ "
" │ │ "
" │ ╭─────────────────────╮ ╭─────────────────────╮ │ "
" │ │ ( End | Up ) no │ │ ( F10 ) yes │ │ "
" │ ╰─────────────────────╯ ╰─────────────────────╯ │ "
" ╰────────────────────────────────────────────────────────────────╯ "
" "
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/delete_confirm.rs
expression: setup.terminal.backend()
---
" "
" ╭──────────────────────── Confirm Delete ────────────────────────╮ "
" │ │ "
" │ Are you sure you want to delete container: container_1 │ "
" │ │ "
" │ ╭─────────────────────╮ ╭─────────────────────╮ │ "
" │ │ ( End | Up ) no │ │ ( F10 | L ) yes │ │ "
" │ ╰─────────────────────╯ ╰─────────────────────╯ │ "
" ╰────────────────────────────────────────────────────────────────╯ "
" "
@@ -0,0 +1,14 @@
---
source: src/ui/draw_blocks/delete_confirm.rs
expression: setup.terminal.backend()
---
" "
" ╭──────────────────────────────────── Confirm Delete ────────────────────────────────────╮ "
" │ │ "
" │ Are you sure you want to delete container: container_1_container_1_container_1 │ "
" │ │ "
" │ ╭──────────────────────────────╮ ╭─────────────────────────────╮ │ "
" │ │ ( n ) no │ │ ( y ) yes │ │ "
" │ ╰──────────────────────────────╯ ╰─────────────────────────────╯ │ "
" ╰────────────────────────────────────────────────────────────────────────────────────────╯ "
" "
@@ -0,0 +1,15 @@
---
source: src/ui/draw_blocks/error.rs
expression: setup.terminal.backend()
---
" "
" ╭────────────── Error ──────────────╮ "
" │ │ "
" │ Unable to exec into container │ "
" │ │ "
" │ ( c ) clear error │ "
" │ │ "
" │ ( q ) quit oxker │ "
" │ │ "
" ╰───────────────────────────────────╯ "
" "
@@ -0,0 +1,15 @@
---
source: src/ui/draw_blocks/error.rs
expression: setup.terminal.backend()
---
" "
" ╭────────────── Error ──────────────╮ "
" │ │ "
" │ Unable to exec into container │ "
" │ │ "
" │ ( c ) clear error │ "
" │ │ "
" │ ( q ) quit oxker │ "
" │ │ "
" ╰───────────────────────────────────╯ "
" "
@@ -0,0 +1,15 @@
---
source: src/ui/draw_blocks/error.rs
expression: setup.terminal.backend()
---
" "
" ╭────────────── Error ──────────────╮ "
" │ │ "
" │ Unable to exec into container │ "
" │ │ "
" │ ( Back Tab ) clear error │ "
" │ │ "
" │ ( F4 ) quit oxker │ "
" │ │ "
" ╰───────────────────────────────────╯ "
" "
@@ -0,0 +1,15 @@
---
source: src/ui/draw_blocks/error.rs
expression: setup.terminal.backend()
---
" "
" ╭────────────── Error ──────────────╮ "
" │ │ "
" │ Unable to exec into container │ "
" │ │ "
" │ ( c ) clear error │ "
" │ │ "
" │ ( F4 | End ) quit oxker │ "
" │ │ "
" ╰───────────────────────────────────╯ "
" "
@@ -0,0 +1,15 @@
---
source: src/ui/draw_blocks/error.rs
expression: setup.terminal.backend()
---
" "
" ╭────────────── Error ──────────────╮ "
" │ │ "
" │ Unable to exec into container │ "
" │ │ "
" │ ( Back Tab | m ) clear error │ "
" │ │ "
" │ ( F4 | End ) quit oxker │ "
" │ │ "
" ╰───────────────────────────────────╯ "
" "
@@ -0,0 +1,13 @@
---
source: src/ui/draw_blocks/error.rs
expression: setup.terminal.backend()
---
" "
"╭────────────────── Error ───────────────────╮"
"│ │"
"│ Unable to access docker daemon │"
"│ │"
"│ oxker::v0.10.0 closing in 04 seconds │"
"│ │"
"╰────────────────────────────────────────────╯"
" "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/filter.rs
expression: setup.terminal.backend()
---
" Esc clear ← by → Name Image Status All term: "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/filter.rs
expression: setup.terminal.backend()
---
" Esc clear ← by → Name Image Status All term: cd "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/filter.rs
expression: setup.terminal.backend()
---
" Esc clear ← by → Name Image Status All term: "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/filter.rs
expression: setup.terminal.backend()
---
" Esc clear ← by → Name Image Status All term: "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/filter.rs
expression: setup.terminal.backend()
---
" Esc clear ← by → Name Image Status All term: cd "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" ⠙ name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" ⠙ name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit id image ↓ rx ↑ tx ( T ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit id image ↓ rx ↑ tx ( T | Tab ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit id image ↓ rx ↑ tx ( T | Tab ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" ( h ) exit help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" ( h ) exit help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu ▲ memory/limit id image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu ▼ memory/limit id image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit id ▲ image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit id ▼ image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit id image ▲ ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit id image ▼ ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit ▲ id image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit ▼ id image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name ▲ state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name ▼ state status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit id image ↓ rx ▲ ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state status cpu memory/limit id image ↓ rx ▼ ↑ tx ( h ) show help "
@@ -0,0 +1,5 @@
---
source: src/ui/draw_blocks/headers.rs
expression: setup.terminal.backend()
---
" name state ▲ status cpu memory/limit id image ↓ rx ↑ tx ( h ) show help "

Some files were not shown because too many files have changed in this diff Show More