Skip to content

Commit 32286b5

Browse files
authored
Task 2: Add 5 integration tests (#180)
* docs: add 5 integration tests for R2CN task 2 * refactor: split integration tests into 5 separate files per reviewer request * style: fix formatting using cargo fmt nightly * refactor: follow established test patterns using internal API
1 parent d5d21cc commit 32286b5

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed

Cargo.lock

Lines changed: 64 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,4 @@ testcontainers = { version = "0.25.2", features = [
8181
"reusable-containers",
8282
] }
8383
reqwest = { version = "0.12.24", features = ["blocking"] }
84+
assert_cmd = "2.1.2"

tests/command/add_test.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,3 +617,78 @@ async fn test_add_duplicate_file_should_not_duplicate_index() {
617617
);
618618
}
619619
}
620+
621+
#[tokio::test]
622+
#[serial]
623+
/// Tests adding an empty file to the repository
624+
///
625+
/// Ensures that Libra can handle adding empty files without errors
626+
async fn test_add_empty_file() {
627+
let test_dir = tempdir().unwrap();
628+
test::setup_with_new_libra_in(test_dir.path()).await;
629+
let _guard = test::ChangeDirGuard::new(test_dir.path());
630+
631+
// Create an empty file
632+
let file_path = "empty.txt";
633+
fs::File::create(file_path).unwrap();
634+
635+
// Execute add command
636+
add::execute(AddArgs {
637+
pathspec: vec![String::from(file_path)],
638+
all: false,
639+
update: false,
640+
refresh: false,
641+
force: false,
642+
verbose: false,
643+
dry_run: false,
644+
ignore_errors: false,
645+
})
646+
.await;
647+
648+
// Verify the empty file was added to index
649+
let changes = changes_to_be_committed().await;
650+
assert!(
651+
changes.new.iter().any(|x| x.to_str().unwrap() == file_path),
652+
"Empty file should be added to index"
653+
);
654+
}
655+
656+
#[tokio::test]
657+
#[serial]
658+
/// Tests adding a file in a nested subdirectory
659+
///
660+
/// Ensures that Libra correctly handles files in deep directory structures
661+
async fn test_add_sub_directory_file() {
662+
let test_dir = tempdir().unwrap();
663+
test::setup_with_new_libra_in(test_dir.path()).await;
664+
let _guard = test::ChangeDirGuard::new(test_dir.path());
665+
666+
// Create nested subdirectory structure
667+
let sub_dir = "a/b/c";
668+
fs::create_dir_all(sub_dir).unwrap();
669+
let file_path = "a/b/c/deep.txt";
670+
fs::write(file_path, "hello deep").unwrap();
671+
672+
// Execute add command
673+
add::execute(AddArgs {
674+
pathspec: vec![String::from(file_path)],
675+
all: false,
676+
update: false,
677+
refresh: false,
678+
force: false,
679+
verbose: false,
680+
dry_run: false,
681+
ignore_errors: false,
682+
})
683+
.await;
684+
685+
// Verify the file in nested directory was added to index
686+
let changes = changes_to_be_committed().await;
687+
assert!(
688+
changes
689+
.new
690+
.iter()
691+
.any(|x| x.to_str().unwrap().replace("\\", "/") == file_path),
692+
"File in nested subdirectory should be added to index"
693+
);
694+
}

tests/command/status_test.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,3 +1792,78 @@ async fn test_status_porcelain_v2_deleted_file() {
17921792
deleted_line
17931793
);
17941794
}
1795+
1796+
#[tokio::test]
1797+
#[serial]
1798+
/// Tests status command after adding a file
1799+
///
1800+
/// Verifies that the status command correctly reports added files with proper formatting
1801+
async fn test_status_after_add() {
1802+
let test_dir = tempdir().unwrap();
1803+
test::setup_with_new_libra_in(test_dir.path()).await;
1804+
let _guard = test::ChangeDirGuard::new(test_dir.path());
1805+
1806+
// Create a new file
1807+
let file_path = "test.txt";
1808+
fs::write(file_path, "content").unwrap();
1809+
1810+
// Add the file
1811+
add::execute(AddArgs {
1812+
pathspec: vec![String::from(file_path)],
1813+
all: false,
1814+
update: false,
1815+
refresh: false,
1816+
force: false,
1817+
verbose: false,
1818+
dry_run: false,
1819+
ignore_errors: false,
1820+
})
1821+
.await;
1822+
1823+
// Test porcelain output
1824+
let mut output = Vec::new();
1825+
status_execute(
1826+
StatusArgs {
1827+
porcelain: Some(PorcelainVersion::V1),
1828+
..Default::default()
1829+
},
1830+
&mut output,
1831+
)
1832+
.await;
1833+
1834+
let output_str = String::from_utf8(output).unwrap();
1835+
assert!(
1836+
output_str
1837+
.lines()
1838+
.any(|l| l.starts_with("A ") && l.contains(file_path)),
1839+
"Porcelain status should show 'A ' prefix for added file: {}",
1840+
output_str
1841+
);
1842+
1843+
// Test short output
1844+
let mut output = Vec::new();
1845+
status_execute(
1846+
StatusArgs {
1847+
short: true,
1848+
..Default::default()
1849+
},
1850+
&mut output,
1851+
)
1852+
.await;
1853+
1854+
let output_str = String::from_utf8(output).unwrap();
1855+
assert!(
1856+
output_str
1857+
.lines()
1858+
.any(|l| l.starts_with("A ") && l.contains(file_path)),
1859+
"Short status should show 'A ' prefix for added file: {}",
1860+
output_str
1861+
);
1862+
1863+
// Verify via changes_to_be_committed
1864+
let changes = changes_to_be_committed().await;
1865+
assert!(
1866+
changes.new.iter().any(|x| x.to_str().unwrap() == file_path),
1867+
"Added file should appear in changes_to_be_committed"
1868+
);
1869+
}

0 commit comments

Comments
 (0)