1 use std::env;
2 use std::fs::{self, File};
3 use std::io::Read;
4 use std::path::{Path, PathBuf};
5 use std::process::Command;
6 
7 use tempfile::TempDir;
8 
9 use git2::build::CheckoutBuilder;
10 use git2::Repository;
11 use git2::Signature;
12 
13 pub struct BatTester {
14     /// Temporary working directory
15     temp_dir: TempDir,
16 
17     /// Path to the *bat* executable
18     exe: PathBuf,
19 }
20 
21 impl BatTester {
test_snapshot(&self, name: &str, style: &str)22     pub fn test_snapshot(&self, name: &str, style: &str) {
23         let output = Command::new(&self.exe)
24             .current_dir(self.temp_dir.path())
25             .args(&[
26                 "sample.rs",
27                 "--no-config",
28                 "--paging=never",
29                 "--color=never",
30                 "--decorations=always",
31                 "--terminal-width=80",
32                 &format!("--style={}", style),
33             ])
34             .output()
35             .expect("bat failed");
36 
37         // have to do the replace because the filename in the header changes based on the current working directory
38         let actual = String::from_utf8_lossy(&output.stdout)
39             .as_ref()
40             .replace("tests/snapshots/", "");
41 
42         let mut expected = String::new();
43         let mut file = File::open(format!("tests/snapshots/output/{}.snapshot.txt", name))
44             .expect("snapshot file missing");
45         file.read_to_string(&mut expected)
46             .expect("could not read snapshot file");
47 
48         assert_eq!(expected, actual);
49     }
50 }
51 
52 impl Default for BatTester {
default() -> Self53     fn default() -> Self {
54         let temp_dir = create_sample_directory().expect("sample directory");
55 
56         let root = env::current_exe()
57             .expect("tests executable")
58             .parent()
59             .expect("tests executable directory")
60             .parent()
61             .expect("bat executable directory")
62             .to_path_buf();
63 
64         let exe_name = if cfg!(windows) { "bat.exe" } else { "bat" };
65         let exe = root.join(exe_name);
66 
67         BatTester { temp_dir, exe }
68     }
69 }
70 
create_sample_directory() -> Result<TempDir, git2::Error>71 fn create_sample_directory() -> Result<TempDir, git2::Error> {
72     // Create temp directory and initialize repository
73     let temp_dir = TempDir::new().expect("Temp directory");
74     let repo = Repository::init(&temp_dir)?;
75 
76     // Copy over `sample.rs`
77     let sample_path = temp_dir.path().join("sample.rs");
78     println!("{:?}", &sample_path);
79     fs::copy("tests/snapshots/sample.rs", &sample_path).expect("successful copy");
80 
81     // Commit
82     let mut index = repo.index()?;
83     index.add_path(Path::new("sample.rs"))?;
84 
85     let oid = index.write_tree()?;
86     let signature = Signature::now("bat test runner", "bat@test.runner")?;
87     let tree = repo.find_tree(oid)?;
88     let _ = repo.commit(
89         Some("HEAD"), //  point HEAD to our new commit
90         &signature,   // author
91         &signature,   // committer
92         "initial commit",
93         &tree,
94         &[],
95     );
96     let mut opts = CheckoutBuilder::new();
97     repo.checkout_head(Some(opts.force()))?;
98 
99     fs::copy("tests/snapshots/sample.modified.rs", &sample_path).expect("successful copy");
100 
101     Ok(temp_dir)
102 }
103