use crate::file_browser::fs_tree::{sanitize_path, TreeItemPath};
use crate::file_browser::{FileType, PathFilter};
use crate::{
core::{algebra::Vector2, parking_lot::Mutex, pool::Handle},
file_browser::{
fs_tree::{self, read_dir_entries, DisksProvider},
FileBrowserBuilder, FileBrowserMessage,
},
test::{test_widget_deletion, UserInterfaceTestingExtension},
tree::{Tree, TreeRoot, TreeRootBuilder},
widget::WidgetBuilder,
RcUiNodeHandle, UiNode, UserInterface,
};
use fyrox_graph::SceneGraph;
use std::{
fs::File,
path::{Path, PathBuf},
sync::Arc,
};
fn create_dir(path: impl AsRef<Path>) {
std::fs::create_dir_all(path).unwrap()
}
fn write_empty_file(path: impl AsRef<Path>) {
if let Some(parent) = path.as_ref().parent() {
if !parent.exists() {
create_dir(parent)
}
}
File::create(path).unwrap();
}
fn create_dirs(paths: &[PathBuf]) {
for path in paths {
create_dir(path)
}
}
fn write_empty_files(paths: &[PathBuf]) {
for path in paths {
write_empty_file(path)
}
}
fn clean_or_create(path: impl AsRef<Path>) {
if path.as_ref().exists() {
std::fs::remove_dir_all(&path).unwrap();
}
create_dir(path);
}
fn find_by_path(path: impl AsRef<Path>, ui: &UserInterface) -> Handle<UiNode> {
ui.find_from_root(&mut |n| {
n.user_data_cloned::<TreeItemPath>()
.is_some_and(|p| p.path() == path.as_ref())
})
.map(|(h, _)| h)
.unwrap_or_default()
}
fn write_test_tree(root: &Path) -> Vec<PathBuf> {
clean_or_create(root);
let root = sanitize_path(root).unwrap();
let paths = [
root.join("file1"),
root.join("file2"),
root.join("file3"),
root.join("subdir").join("file1"),
root.join("subdir").join("file2"),
root.join("subdir").join("file3"),
];
write_empty_files(&paths);
paths.to_vec()
}
fn count_tree_items(ui: &UserInterface) -> usize {
let mut count = 0;
for node in ui.nodes() {
if node.has_component::<Tree>() {
count += 1;
}
}
count
}
fn count_tree_roots(ui: &UserInterface) -> usize {
let mut count = 0;
for node in ui.nodes() {
if node.has_component::<TreeRoot>() {
count += 1;
}
}
count
}
#[test]
fn test_deletion() {
test_widget_deletion(|ctx| FileBrowserBuilder::new(WidgetBuilder::new()).build(ctx));
}
#[test]
fn test_find_tree() {
let mut ui = UserInterface::new(Vector2::new(100.0, 100.0));
let root = TreeRootBuilder::new(
WidgetBuilder::new().with_user_data(Arc::new(Mutex::new(PathBuf::from("test")))),
)
.build(&mut ui.build_ctx())
.to_base();
let path = fs_tree::build_tree(
root,
"./test/path1",
"./test",
RcUiNodeHandle::new(Handle::<Tree>::new(0, 1), ui.sender()),
&Default::default(),
&mut ui,
);
while ui.poll_message().is_some() {}
assert_eq!(
fs_tree::find_tree_item(root, Path::new("./test/path1"), &ui),
path
);
assert_eq!(
fs_tree::find_tree_item(root, Path::new("test/path1"), &ui),
Handle::<UiNode>::NONE
);
}
#[test]
fn test_dir_fetching() {
let path = Path::new("./test_dir_fetching");
clean_or_create(path);
let folders = [path.join("dir1"), path.join("dir2"), path.join("dir3")];
let files = [
path.join("file1.foobar"),
path.join("file2"),
path.join("file3"),
];
create_dirs(&folders);
write_empty_files(&files);
let entries = read_dir_entries(path, &PathFilter::new()).unwrap();
assert_eq!(entries[0..3], folders);
assert_eq!(entries[3..6], files);
let entries = read_dir_entries(
path,
&PathFilter {
folders_only: false,
types: vec![FileType {
description: "Foobar".to_string(),
extension: "foobar".to_string(),
}],
},
)
.unwrap();
assert_eq!(entries[0..3], folders[0..3]);
assert_eq!(entries[3..4], files[0..1]);
}
#[test]
fn test_fs_tree_with_root() {
let root = PathBuf::from("./test_fs_tree_with_root");
let paths = write_test_tree(&root);
let screen_size = Vector2::repeat(1000.0);
let mut ui = UserInterface::new(screen_size);
let ctx = &mut ui.build_ctx();
FileBrowserBuilder::new(WidgetBuilder::new())
.with_root(root)
.with_path(paths.last().unwrap())
.build(ctx);
ui.poll_all_messages();
for path in paths {
let path = fs_tree::sanitize_path(&path).unwrap();
assert!(find_by_path(path, &ui).is_some());
}
for (mount_point, _) in DisksProvider::new().iter() {
assert!(find_by_path(mount_point.to_string(), &ui).is_none());
}
}
#[test]
fn test_fs_tree_with_root_and_empty_tree() {
let root = PathBuf::from("./test_fs_tree_with_root_empty");
clean_or_create(&root);
let screen_size = Vector2::repeat(1000.0);
let mut ui = UserInterface::new(screen_size);
let ctx = &mut ui.build_ctx();
FileBrowserBuilder::new(WidgetBuilder::new())
.with_root(root)
.build(ctx);
ui.poll_all_messages();
assert_eq!(count_tree_items(&ui), 0);
assert_eq!(count_tree_roots(&ui), 1);
for (mount_point, _) in DisksProvider::new().iter() {
assert!(find_by_path(mount_point.to_string(), &ui).is_none());
}
}
#[test]
fn test_fs_tree_without_root() {
let root = PathBuf::from("./test_fs_tree_without_root");
let paths = write_test_tree(&root);
let screen_size = Vector2::repeat(1000.0);
let mut ui = UserInterface::new(screen_size);
let ctx = &mut ui.build_ctx();
let browser = FileBrowserBuilder::new(WidgetBuilder::new())
.with_path(paths.last().unwrap())
.build(ctx);
ui.poll_all_messages();
for path in &paths {
let path = fs_tree::sanitize_path(path).unwrap();
assert!(find_by_path(path, &ui).is_some());
}
for (mount_point, _) in DisksProvider::new().iter() {
assert!(find_by_path(mount_point.to_string(), &ui).is_some());
}
for path in &paths {
ui.send(browser, FileBrowserMessage::Path(path.clone()));
let mut response_count = 0;
while let Some(message) = ui.poll_message() {
if let Some(FileBrowserMessage::Path(response_path)) = message.data_from(browser) {
response_count += 1;
assert_eq!(path, response_path);
}
}
assert_eq!(response_count, 1);
for path in &paths {
let path = fs_tree::sanitize_path(path).unwrap();
assert!(find_by_path(path, &ui).is_some());
}
}
}
#[test]
fn test_fs_tree_invalid_path() {
let screen_size = Vector2::repeat(1000.0);
let mut ui = UserInterface::new(screen_size);
let ctx = &mut ui.build_ctx();
FileBrowserBuilder::new(WidgetBuilder::new())
.with_path("foo/bar/baz")
.build(ctx);
ui.poll_all_messages();
assert_eq!(count_tree_items(&ui), 0);
assert_eq!(count_tree_roots(&ui), 1);
}