use super::utils::get_resource_path;
use crate::{cmderr, commands::CommandOut};
use anyhow::Context;
use std::io::Write;
use tauri::{command, AppHandle, Runtime};
#[command]
pub(crate) fn exists<R: Runtime>(
app_handle: AppHandle<R>,
widget_id: String,
path: String,
) -> CommandOut<bool> {
let file_path = get_resource_path(&app_handle, &widget_id, &path)?;
Ok(file_path.exists())
}
#[command]
pub(crate) fn is_file<R: Runtime>(
app_handle: AppHandle<R>,
widget_id: String,
path: String,
) -> CommandOut<bool> {
let file_path = get_resource_path(&app_handle, &widget_id, &path)?;
Ok(file_path.is_file())
}
#[command]
pub(crate) fn is_dir<R: Runtime>(
app_handle: AppHandle<R>,
widget_id: String,
path: String,
) -> CommandOut<bool> {
let file_path = get_resource_path(&app_handle, &widget_id, &path)?;
Ok(file_path.is_dir())
}
#[command]
pub(crate) fn read_file<R: Runtime>(
app_handle: AppHandle<R>,
widget_id: String,
path: String,
) -> CommandOut<String> {
let file_path = get_resource_path(&app_handle, &widget_id, &path)?;
std::fs::read_to_string(&file_path)
.context(format!("Failed to read file '{}'", file_path.display()))
.map_err(|e| cmderr!(e))
}
#[command]
pub(crate) fn write_file<R: Runtime>(
app_handle: AppHandle<R>,
widget_id: String,
path: String,
content: String,
) -> CommandOut<()> {
let file_path = get_resource_path(&app_handle, &widget_id, &path)?;
std::fs::write(&file_path, content)
.context(format!("Failed to write file '{}'", file_path.display()))
.map_err(|e| cmderr!(e))
}
#[command]
pub(crate) fn append_file<R: Runtime>(
app_handle: AppHandle<R>,
widget_id: String,
path: String,
content: String,
) -> CommandOut<()> {
let file_path = get_resource_path(&app_handle, &widget_id, &path)?;
std::fs::OpenOptions::new()
.append(true)
.create(true)
.open(&file_path)
.and_then(|mut file| file.write_all(content.as_bytes()))
.context(format!("Failed to append file '{}'", file_path.display()))
.map_err(|e| cmderr!(e))
}
#[command]
pub(crate) fn remove_file<R: Runtime>(
app_handle: AppHandle<R>,
widget_id: String,
path: String,
) -> CommandOut<()> {
let file_path = get_resource_path(&app_handle, &widget_id, &path)?;
std::fs::remove_file(&file_path)
.context(format!("Failed to delete file '{}'", file_path.display()))
.map_err(|e| cmderr!(e))
}
#[command]
pub(crate) fn create_dir<R: Runtime>(
app_handle: AppHandle<R>,
widget_id: String,
path: String,
) -> CommandOut<()> {
let folder_path = get_resource_path(&app_handle, &widget_id, &path)?;
std::fs::create_dir_all(&folder_path)
.context(format!("Failed to create directory '{}'", folder_path.display()))
.map_err(|e| cmderr!(e))
}
#[command]
pub(crate) fn remove_dir<R: Runtime>(
app_handle: AppHandle<R>,
widget_id: String,
path: String,
) -> CommandOut<()> {
let folder_path = get_resource_path(&app_handle, &widget_id, &path)?;
std::fs::remove_dir_all(&folder_path)
.context(format!("Failed to delete directory '{}'", folder_path.display()))
.map_err(|e| cmderr!(e))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::testing::setup_mock_env;
use pretty_assertions::assert_eq;
use rstest::rstest;
use std::path::{Path, PathBuf};
fn setup_widget_directory(base_dir: &Path, widget_id: &str) -> PathBuf {
let widget_dir = base_dir.join("widgets").join(widget_id);
std::fs::create_dir_all(&widget_dir)
.expect("Failed to create widget directory");
widget_dir
}
#[rstest]
fn test_exists() {
let (base_dir, app_handle) = setup_mock_env();
let widget_dir = setup_widget_directory(base_dir.path(), "dummy");
let file_path = widget_dir.join("dummy_file.txt");
let result = exists(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
);
assert!(result.is_ok());
assert!(!result.unwrap());
std::fs::File::create(file_path).unwrap();
let result = exists(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
);
assert!(result.is_ok());
assert!(result.unwrap());
}
#[rstest]
fn test_is_file_or_dir() {
let (base_dir, app_handle) = setup_mock_env();
let widget_dir = setup_widget_directory(base_dir.path(), "dummy");
let file_path = widget_dir.join("dummy_file.txt");
let dir_path = widget_dir.join("dummy_dir");
std::fs::File::create(file_path).unwrap();
std::fs::create_dir(dir_path).unwrap();
let result = is_file(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
);
assert!(result.is_ok());
assert!(result.unwrap());
let result = is_dir(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
);
assert!(result.is_ok());
assert!(!result.unwrap());
let result =
is_file(app_handle.clone(), "dummy".to_string(), "dummy_dir".to_string());
assert!(result.is_ok());
assert!(!result.unwrap());
let result =
is_dir(app_handle.clone(), "dummy".to_string(), "dummy_dir".to_string());
assert!(result.is_ok());
assert!(result.unwrap());
}
#[rstest]
fn test_read_file() {
let (base_dir, app_handle) = setup_mock_env();
let widget_dir = setup_widget_directory(base_dir.path(), "dummy");
let file_path = widget_dir.join("dummy_file.txt");
let result = read_file(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
);
assert!(result.is_err());
assert!(result.unwrap_err().contains(
format!("Failed to read file '{}'", file_path.display()).as_str()
));
let content = "Hello, world!";
std::fs::File::create(&file_path)
.unwrap()
.write_all(content.as_bytes())
.unwrap();
let result = read_file(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
);
assert!(result.is_ok());
assert_eq!(result.unwrap(), content);
}
#[rstest]
fn test_write_file() {
let (base_dir, app_handle) = setup_mock_env();
let widget_dir = setup_widget_directory(base_dir.path(), "dummy");
let file_path = widget_dir.join("dummy_file.txt");
let content = "Hello, world!";
let result = write_file(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
content.to_string(),
);
assert!(result.is_ok());
assert_eq!(std::fs::read_to_string(&file_path).unwrap(), content);
let new_content = "Hello, new world!";
let result = write_file(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
new_content.to_string(),
);
assert!(result.is_ok());
assert_eq!(std::fs::read_to_string(&file_path).unwrap(), new_content);
}
#[rstest]
fn test_append_file() {
let (base_dir, app_handle) = setup_mock_env();
let widget_dir = setup_widget_directory(base_dir.path(), "dummy");
let file_path = widget_dir.join("dummy_file.txt");
let content = "Hello, world!\n";
let result = append_file(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
content.to_string(),
);
assert!(result.is_ok());
assert_eq!(std::fs::read_to_string(&file_path).unwrap(), content);
let new_content = "Hello, new world!\n";
let result = append_file(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
new_content.to_string(),
);
assert!(result.is_ok());
assert_eq!(
std::fs::read_to_string(&file_path).unwrap(),
format!("{content}{new_content}")
);
}
#[rstest]
fn test_create_dir() {
let (base_dir, app_handle) = setup_mock_env();
let widget_dir = setup_widget_directory(base_dir.path(), "dummy");
let result = create_dir(
app_handle.clone(),
"dummy".to_string(),
"dummy_dir".to_string(),
);
assert!(result.is_ok());
assert!(widget_dir.join("dummy_dir").is_dir());
}
#[rstest]
fn test_remove_file_or_dir() {
let (base_dir, app_handle) = setup_mock_env();
let widget_dir = setup_widget_directory(base_dir.path(), "dummy");
let result = remove_file(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
);
assert!(result.is_err());
assert!(result.unwrap_err().contains(
format!(
"Failed to delete file '{}'",
widget_dir.join("dummy_file.txt").display()
)
.as_str()
));
let result = remove_dir(
app_handle.clone(),
"dummy".to_string(),
"dummy_dir".to_string(),
);
assert!(result.is_err());
assert!(result.unwrap_err().contains(
format!(
"Failed to delete directory '{}'",
widget_dir.join("dummy_dir").display()
)
.as_str()
));
let file_path = widget_dir.join("dummy_file.txt");
let dir_path = widget_dir.join("dummy_dir");
std::fs::File::create(&file_path).unwrap();
std::fs::create_dir(&dir_path).unwrap();
let result = remove_file(
app_handle.clone(),
"dummy".to_string(),
"dummy_dir".to_string(),
);
assert!(result.is_err());
assert!(result.unwrap_err().contains(
format!(
"Failed to delete file '{}'",
widget_dir.join("dummy_dir").display()
)
.as_str()
));
let result = remove_dir(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
);
assert!(result.is_err());
assert!(result.unwrap_err().contains(
format!(
"Failed to delete directory '{}'",
widget_dir.join("dummy_file.txt").display()
)
.as_str()
));
let result = remove_file(
app_handle.clone(),
"dummy".to_string(),
"dummy_file.txt".to_string(),
);
assert!(result.is_ok());
assert!(!file_path.exists());
let result = remove_dir(
app_handle.clone(),
"dummy".to_string(),
"dummy_dir".to_string(),
);
assert!(result.is_ok());
assert!(!dir_path.exists());
}
}