todo_file/
testutil.rs

1//! Utilities for writing tests that interact with todo file
2use std::{
3	cell::RefCell,
4	fmt::{Debug, Formatter},
5	path::Path,
6};
7
8use tempfile::{Builder, NamedTempFile};
9
10use crate::{Line, TodoFile};
11
12/// Context for `with_todo_file`
13pub struct TodoFileTestContext {
14	todo_file: TodoFile,
15	git_todo_file: RefCell<NamedTempFile>,
16}
17
18impl Debug for TodoFileTestContext {
19	#[inline]
20	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
21		f.debug_struct("TodoFileTestContext")
22			.field("todo_file", &self.todo_file)
23			.field("filepath", &self.todo_file.filepath)
24			.finish_non_exhaustive()
25	}
26}
27
28impl TodoFileTestContext {
29	/// Return the path of the todo file
30	#[inline]
31	pub fn path(&self) -> String {
32		String::from(self.git_todo_file.borrow().path().to_str().unwrap_or_default())
33	}
34
35	/// Get the todo file instance
36	#[inline]
37	pub const fn todo_file(&self) -> &TodoFile {
38		&self.todo_file
39	}
40
41	/// Get the todo file instance as mutable
42	#[inline]
43	pub fn todo_file_mut(&mut self) -> &mut TodoFile {
44		&mut self.todo_file
45	}
46
47	/// Get the todo file instance
48	#[inline]
49	pub fn to_owned(self) -> (NamedTempFile, TodoFile) {
50		(self.git_todo_file.into_inner(), self.todo_file)
51	}
52
53	/// Delete the path behind the todo file
54	///
55	/// # Panics
56	/// Will panic if the file cannot be deleted for any reason
57	#[inline]
58	pub fn delete_file(&self) {
59		self.git_todo_file
60			.replace(Builder::new().tempfile().unwrap())
61			.close()
62			.unwrap();
63	}
64
65	/// Set the path behind ot todo file as readonly
66	///
67	/// # Panics
68	/// Will panic if the file permissions cannot be changed for any reason
69	#[inline]
70	pub fn set_file_readonly(&self) {
71		let git_todo_file = self.git_todo_file.borrow_mut();
72		let todo_file = git_todo_file.as_file();
73		let mut permissions = todo_file.metadata().unwrap().permissions();
74		permissions.set_readonly(true);
75		todo_file.set_permissions(permissions).unwrap();
76	}
77}
78
79/// Provide a `TodoFileTestContext` instance containing a `Todo` for use in tests.
80///
81/// # Panics
82/// Will panic if a temporary file cannot be created
83#[inline]
84pub fn with_todo_file<C>(lines: &[&str], callback: C)
85where C: FnOnce(TodoFileTestContext) {
86	let git_repo_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
87		.join("..")
88		.join("..")
89		.join("test")
90		.join("fixtures")
91		.join("simple");
92	let git_todo_file = Builder::new()
93		.prefix("git-rebase-todo-scratch")
94		.suffix("")
95		.tempfile_in(git_repo_dir.as_path())
96		.unwrap();
97
98	let mut todo_file = TodoFile::new(git_todo_file.path().to_str().unwrap(), 1, "#");
99	todo_file.set_lines(lines.iter().map(|l| Line::new(l).unwrap()).collect());
100	callback(TodoFileTestContext {
101		git_todo_file: RefCell::new(git_todo_file),
102		todo_file,
103	});
104}