Skip to content

Commit d7ad5a5

Browse files
committed
improve test coverage
1 parent f642d60 commit d7ad5a5

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

src/commands/create/mod.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,38 @@ mod tests {
254254

255255
Ok(())
256256
}
257+
258+
fn split_metadata_name(name: &str) -> (&str, &str) {
259+
let without_prefix = name
260+
.strip_prefix("rsworktree-")
261+
.expect("name should include rsworktree prefix");
262+
without_prefix
263+
.rsplit_once('-')
264+
.expect("name should include trailing hash")
265+
}
266+
267+
#[test]
268+
fn metadata_name_replaces_disallowed_characters() {
269+
let name = worktree_metadata_name("feat/branch with spaces");
270+
let (sanitized, hash) = split_metadata_name(&name);
271+
assert_eq!(sanitized, "feat-branch-with-spaces");
272+
assert_eq!(hash.len(), 16);
273+
assert!(hash.chars().all(|c| c.is_ascii_hexdigit()));
274+
}
275+
276+
#[test]
277+
fn metadata_name_uses_default_when_sanitized_empty() {
278+
let name = worktree_metadata_name("///");
279+
let (sanitized, _) = split_metadata_name(&name);
280+
assert_eq!(sanitized, "worktree");
281+
}
282+
283+
#[test]
284+
fn metadata_name_truncates_long_inputs() {
285+
let long_name = "a".repeat(80);
286+
let name = worktree_metadata_name(&long_name);
287+
let (sanitized, _) = split_metadata_name(&name);
288+
assert_eq!(sanitized.len(), 48);
289+
assert!(sanitized.chars().all(|c| c == 'a'));
290+
}
257291
}

src/repo/mod.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,72 @@ fn gitignore_has_entry(contents: &str) -> bool {
117117
.map(|line| line.trim())
118118
.any(|line| line == WORKTREE_IGNORE_ENTRY || line == WORKTREE_IGNORE_ALT_ENTRY)
119119
}
120+
121+
#[cfg(test)]
122+
mod tests {
123+
use super::*;
124+
use std::fs;
125+
126+
use tempfile::TempDir;
127+
128+
fn init_repo(dir: &TempDir) -> color_eyre::Result<Repo> {
129+
git2::Repository::init(dir.path())?;
130+
Repo::discover_from(dir.path())
131+
}
132+
133+
#[test]
134+
fn ensure_worktrees_dir_creates_gitignore_when_missing() -> color_eyre::Result<()> {
135+
let dir = TempDir::new()?;
136+
let repo = init_repo(&dir)?;
137+
let gitignore = dir.path().join(".gitignore");
138+
139+
assert!(!gitignore.exists(), "gitignore should start absent");
140+
141+
repo.ensure_worktrees_dir()?;
142+
143+
let contents = fs::read_to_string(&gitignore)?;
144+
assert_eq!(contents, format!("{WORKTREE_IGNORE_ENTRY}\n"));
145+
146+
Ok(())
147+
}
148+
149+
#[test]
150+
fn ensure_worktrees_dir_appends_entry_once() -> color_eyre::Result<()> {
151+
let dir = TempDir::new()?;
152+
let repo = init_repo(&dir)?;
153+
let gitignore = dir.path().join(".gitignore");
154+
fs::write(&gitignore, "target")?;
155+
156+
repo.ensure_worktrees_dir()?;
157+
let contents = fs::read_to_string(&gitignore)?;
158+
assert_eq!(contents, format!("target\n{WORKTREE_IGNORE_ENTRY}\n"));
159+
160+
repo.ensure_worktrees_dir()?;
161+
let contents_again = fs::read_to_string(&gitignore)?;
162+
assert_eq!(contents_again, contents);
163+
164+
Ok(())
165+
}
166+
167+
#[test]
168+
fn gitignore_has_entry_detects_alternate_form() {
169+
assert!(gitignore_has_entry(".rsworktree\n"));
170+
assert!(gitignore_has_entry(" .rsworktree/ \n"));
171+
assert!(!gitignore_has_entry(".other"));
172+
}
173+
174+
#[test]
175+
fn ensure_worktrees_dir_respects_existing_entry() -> color_eyre::Result<()> {
176+
let dir = TempDir::new()?;
177+
let repo = init_repo(&dir)?;
178+
let gitignore = dir.path().join(".gitignore");
179+
fs::write(&gitignore, format!("{WORKTREE_IGNORE_ALT_ENTRY}\n"))?;
180+
181+
repo.ensure_worktrees_dir()?;
182+
183+
let contents = fs::read_to_string(&gitignore)?;
184+
assert_eq!(contents, format!("{WORKTREE_IGNORE_ALT_ENTRY}\n"));
185+
186+
Ok(())
187+
}
188+
}

0 commit comments

Comments
 (0)