Skip to content

Commit 06b5313

Browse files
committed
Add tests for state detection
1 parent 886e27c commit 06b5313

File tree

2 files changed

+166
-8
lines changed

2 files changed

+166
-8
lines changed

src/todo_file/src/state.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ mod tests {
5252
use rstest::rstest;
5353

5454
use super::*;
55+
use crate::testutil::{with_todo_revise_file, TodoFileTestDirContext, with_todo_rebase_edit_file, with_todo_rebase_edit_file_stopped};
5556

5657
#[rstest]
5758
#[case::edit(State::Initial, "initial")]
@@ -60,4 +61,22 @@ mod tests {
6061
fn to_string(#[case] action: State, #[case] expected: &str) {
6162
assert_eq!(format!("{action}"), expected);
6263
}
64+
65+
#[rstest]
66+
#[case::edit(State::Initial)]
67+
#[case::edit(State::Edit)]
68+
#[case::edit(State::Revise)]
69+
fn detect(#[case] expected: State) {
70+
let check = |context: TodoFileTestDirContext| {
71+
assert_eq!(
72+
detect_state(context.todo_file().filepath.as_path()).unwrap(),
73+
expected
74+
)
75+
};
76+
match expected {
77+
State::Initial => with_todo_rebase_edit_file(&[], check),
78+
State::Edit => with_todo_rebase_edit_file_stopped(&[], check),
79+
State::Revise => with_todo_revise_file(&[], check),
80+
}
81+
}
6382
}

src/todo_file/src/testutil.rs

Lines changed: 147 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
//! Utilities for writing tests that interact with todo file
22
use std::{
33
cell::RefCell,
4+
io::Write,
45
fmt::{Debug, Formatter},
5-
path::Path,
6+
fs::File,
7+
path::{Path, PathBuf},
68
};
79

8-
use tempfile::{Builder, NamedTempFile};
10+
use tempfile::{Builder, NamedTempFile, TempDir};
911

1012
use crate::{Line, TodoFile};
1113

14+
fn get_repo_dir() -> PathBuf {
15+
Path::new(env!("CARGO_MANIFEST_DIR"))
16+
.join("..")
17+
.join("..")
18+
.join("test")
19+
.join("fixtures")
20+
.join("simple")
21+
}
22+
1223
/// Context for `with_todo_file`
1324
pub struct TodoFileTestContext {
1425
todo_file: TodoFile,
@@ -83,12 +94,7 @@ impl TodoFileTestContext {
8394
#[inline]
8495
pub fn with_todo_file<C>(lines: &[&str], callback: C)
8596
where 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");
97+
let git_repo_dir = get_repo_dir();
9298
let git_todo_file = Builder::new()
9399
.prefix("git-rebase-todo-scratch")
94100
.suffix("")
@@ -102,3 +108,136 @@ where C: FnOnce(TodoFileTestContext) {
102108
todo_file,
103109
});
104110
}
111+
112+
113+
/// Context for `with_todo_file`
114+
pub struct TodoFileTestDirContext {
115+
todo_file: TodoFile,
116+
git_todo_dir: RefCell<TempDir>,
117+
git_todo_file: RefCell<File>,
118+
}
119+
120+
impl Debug for TodoFileTestDirContext {
121+
#[inline]
122+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
123+
f.debug_struct("TodoFileTestDirContext")
124+
.field("todo_file", &self.todo_file)
125+
.field("filepath", &self.todo_file.filepath)
126+
.finish()
127+
}
128+
}
129+
130+
impl TodoFileTestDirContext {
131+
/// Return the path of the todo file
132+
#[inline]
133+
pub fn path(&self) -> String {
134+
String::from(self.todo_file.filepath.to_str().unwrap_or_default())
135+
}
136+
137+
/// Return the path of the todo dir
138+
#[inline]
139+
pub fn dir_path(&self) -> String {
140+
String::from(self.git_todo_dir.borrow().path().to_str().unwrap_or_default())
141+
}
142+
143+
/// Get the todo file instance
144+
#[inline]
145+
pub const fn todo_file(&self) -> &TodoFile {
146+
&self.todo_file
147+
}
148+
149+
/// Get the todo file instance as mutable
150+
#[inline]
151+
pub fn todo_file_mut(&mut self) -> &mut TodoFile {
152+
&mut self.todo_file
153+
}
154+
155+
/// Get the todo file instance
156+
#[inline]
157+
pub fn to_owned(self) -> (TempDir, TodoFile) {
158+
(self.git_todo_dir.into_inner(), self.todo_file)
159+
}
160+
161+
/// Delete the path behind the todo dir
162+
///
163+
/// # Panics
164+
/// Will panic if the dir cannot be deleted for any reason
165+
#[inline]
166+
pub fn delete_dir(&self) {
167+
self.git_todo_dir
168+
.replace(Builder::new().tempdir().unwrap())
169+
.close()
170+
.unwrap();
171+
}
172+
173+
/// Set the path behind ot todo file as readonly
174+
///
175+
/// # Panics
176+
/// Will panic if the file permissions cannot be changed for any reason
177+
#[inline]
178+
pub fn set_file_readonly(&self) {
179+
let git_todo_file = self.git_todo_file.borrow_mut();
180+
let mut permissions = git_todo_file.metadata().unwrap().permissions();
181+
permissions.set_readonly(true);
182+
git_todo_file.set_permissions(permissions).unwrap();
183+
}
184+
}
185+
186+
/// Provide a `TodoFileTestDirContext` instance containing a `Todo` for use in tests.
187+
///
188+
/// # Panics
189+
/// Will panic if a temporary file cannot be created
190+
#[inline]
191+
fn with_todo_file_dir<C>(prefix: &str, filename: &str, lines: &[&str], callback: C)
192+
where C: FnOnce(TodoFileTestDirContext) {
193+
let git_repo_dir = get_repo_dir();
194+
let git_todo_dir = Builder::new()
195+
.prefix(prefix)
196+
.suffix("")
197+
.tempdir_in(git_repo_dir.as_path())
198+
.unwrap();
199+
let git_todo_file_path = git_todo_dir.path().join(filename);
200+
let git_todo_file = File::create(git_todo_file_path.clone()).unwrap();
201+
202+
let mut todo_file = TodoFile::new(git_todo_file_path, 1, "#");
203+
todo_file.set_lines(lines.iter().map(|l| Line::new(l).unwrap()).collect());
204+
callback(TodoFileTestDirContext {
205+
git_todo_dir: RefCell::new(git_todo_dir),
206+
todo_file,
207+
git_todo_file: RefCell::new(git_todo_file),
208+
});
209+
}
210+
211+
/// Provide a `TodoFileTestDirContext` instance containing a `Todo` for use in tests.
212+
///
213+
/// # Panics
214+
/// Will panic if a temporary file cannot be created
215+
#[inline]
216+
pub fn with_todo_revise_file<C>(lines: &[&str], callback: C)
217+
where C: FnOnce(TodoFileTestDirContext) {
218+
with_todo_file_dir("revise.", "git-revise-todo", lines, callback)
219+
}
220+
221+
/// Provide a `TodoFileTestDirContext` instance containing a `Todo` for use in tests.
222+
///
223+
/// # Panics
224+
/// Will panic if a temporary file cannot be created
225+
#[inline]
226+
pub fn with_todo_rebase_edit_file<C>(lines: &[&str], callback: C)
227+
where C: FnOnce(TodoFileTestDirContext) {
228+
with_todo_file_dir("rebase-merge-scratch", "git-rebase-todo", lines, callback)
229+
}
230+
231+
/// Provide a `TodoFileTestDirContext` instance containing a `Todo`, with a stopped-sha
232+
///
233+
/// # Panics
234+
/// Will panic if a temporary file cannot be created
235+
#[inline]
236+
pub fn with_todo_rebase_edit_file_stopped<C>(lines: &[&str], callback: C)
237+
where C: FnOnce(TodoFileTestDirContext) {
238+
with_todo_rebase_edit_file(lines, |context| {
239+
let mut stopped_sha = File::create(Path::new(context.dir_path().as_str()).join("stopped-sha")).unwrap();
240+
writeln!(&mut stopped_sha, "this is a test file").unwrap();
241+
callback(context);
242+
});
243+
}

0 commit comments

Comments
 (0)