use std::{cell::RefCell, path::Path, rc::Rc}; use ely_platform::AppId; use gpui::{Entity, TestAppContext, VisualTestContext}; use super::{Desk, open_in}; use crate::view::Mode; /// ElyMark over a fresh data folder, as `main` opens it. fn start(cx: &mut TestAppContext, data: &Path) -> (Entity, &'static mut VisualTestContext) { // The file watcher runs on a real thread. cx.executor().allow_parking(); cx.update(ely_gpui_component::init_for_tests); cx.update(|cx| { ely_ui::settings::install_defaults(cx); ely_ui::i18n::install(cx); ely_ui::install_no_launch_files(cx); }); let held = Rc::new(RefCell::new(None)); let kept = held.clone(); let data = data.to_path_buf(); let window = cx.update(|cx| { cx.open_window(Default::default(), |window, cx| { let (root, desk) = open_in(AppId::Mark, data, window, cx); kept.replace(Some(desk)); root }) .expect("a window") }); let cx = VisualTestContext::from_window(window.into(), cx).into_mut(); cx.run_until_parked(); let desk = held.take().expect("the desk"); (desk, cx) } fn open(desk: &Entity, path: &Path, cx: &mut VisualTestContext) { desk.update(cx, |desk, cx| desk.open_path(path.to_path_buf(), cx)); cx.run_until_parked(); } fn outline(desk: &Entity, cx: &mut VisualTestContext) -> Vec<(usize, String, usize)> { desk.read_with(cx, |desk, cx| { let view = desk.active_view().expect("a tab"); let outline = view.read(cx).outline(cx); outline .into_iter() .map(|heading| (heading.level, heading.title, heading.line)) .collect() }) } #[gpui::test] fn a_file_opens_with_its_outline_and_joins_the_recent_list(cx: &mut TestAppContext) { let (data, files) = ( tempfile::tempdir().expect("data"), tempfile::tempdir().expect("files"), ); let path = files.path().join("a.md"); std::fs::write(&path, "# One\n\nText.\n\n## Two\n\nMore.\n").expect("a file"); let (desk, cx) = start(cx, data.path()); open(&desk, &path, cx); assert_eq!( outline(&desk, cx), [(1, "One".into(), 0), (2, "Two".into(), 4)] ); let view = desk.read_with(cx, |desk, _| desk.active_view().expect("a tab")); view.update_in(cx, |view, window, cx| view.reveal(4, window, cx)); cx.run_until_parked(); assert_eq!( view.read_with(cx, |view, cx| view.place(cx).line), 4, "the jump lands" ); let real = std::fs::canonicalize(&path).expect("real"); assert!(desk.read_with(cx, |desk, _| desk.recent.contains(&real))); let kept = std::fs::read_to_string(data.path().join("recent.json")).expect("the list"); assert!(kept.contains("a.md"), "{kept}"); } #[gpui::test] fn the_outline_follows_typing(cx: &mut TestAppContext) { let (data, files) = ( tempfile::tempdir().expect("data"), tempfile::tempdir().expect("files"), ); let path = files.path().join("a.md"); std::fs::write(&path, "Text.\n").expect("a file"); let (desk, cx) = start(cx, data.path()); open(&desk, &path, cx); let view = desk.read_with(cx, |desk, _| desk.active_view().expect("a tab")); view.update_in(cx, |view, window, cx| view.switch(Mode::Source, window, cx)); view.update(cx, |view, cx| view.adopt("# New\n\nText.\n".into(), cx)); cx.executor() .advance_clock(std::time::Duration::from_secs(1)); cx.run_until_parked(); assert_eq!(outline(&desk, cx), [(1, "New".into(), 0)]); } #[gpui::test] fn two_files_are_two_tabs_each_with_its_outline(cx: &mut TestAppContext) { let (data, files) = ( tempfile::tempdir().expect("data"), tempfile::tempdir().expect("files"), ); let (a, b) = (files.path().join("a.md"), files.path().join("b.md")); std::fs::write(&a, "# A\n").expect("a"); std::fs::write(&b, "# B\n").expect("b"); let (desk, cx) = start(cx, data.path()); open(&desk, &a, cx); open(&desk, &b, cx); assert_eq!(desk.read_with(cx, |desk, _| desk.core.tabs.len()), 2); assert_eq!(outline(&desk, cx), [(1, "B".into(), 0)]); let first = desk.read_with(cx, |desk, _| desk.core.tabs[0].id); desk.update(cx, |desk, cx| { desk.core.active = Some(first); cx.notify(); }); assert_eq!(outline(&desk, cx), [(1, "A".into(), 0)]); } #[gpui::test] fn a_folder_lists_its_markdown_files(cx: &mut TestAppContext) { let (data, files) = ( tempfile::tempdir().expect("data"), tempfile::tempdir().expect("files"), ); std::fs::create_dir(files.path().join("sub")).expect("sub"); std::fs::write(files.path().join("a.md"), "a").expect("a"); std::fs::write(files.path().join("sub/b.markdown"), "b").expect("b"); std::fs::write(files.path().join("c.txt"), "c").expect("c"); let (desk, cx) = start(cx, data.path()); open(&desk, files.path(), cx); let mut listed = desk.read_with(cx, |desk, _| { let folder = desk.folder.as_ref().expect("a folder"); folder .files .iter() .map(|file| file.replace('\\', "/")) .collect::>() }); listed.sort(); assert_eq!(listed, ["a.md", "sub/b.markdown"]); }