mirror of
https://github.com/PR0M3TH3AN/Marlin.git
synced 2025-09-09 15:48:43 +00:00
update
This commit is contained in:
103
tests/e2e.rs
Normal file
103
tests/e2e.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
//! End-to-end smoke-tests for the marlin binary.
|
||||
//!
|
||||
//! Run with `cargo test --test e2e` or let CI invoke `cargo test`.
|
||||
|
||||
use assert_cmd::prelude::*;
|
||||
use predicates::prelude::*;
|
||||
use std::{fs, path::PathBuf, process::Command};
|
||||
use tempfile::tempdir;
|
||||
|
||||
/// Absolute path to the `marlin` binary Cargo just built for this test run.
|
||||
fn marlin_bin() -> PathBuf {
|
||||
PathBuf::from(env!("CARGO_BIN_EXE_marlin"))
|
||||
}
|
||||
|
||||
fn spawn_demo_tree(root: &PathBuf) {
|
||||
fs::create_dir_all(root.join("Projects/Alpha")).unwrap();
|
||||
fs::create_dir_all(root.join("Projects/Beta")).unwrap();
|
||||
fs::create_dir_all(root.join("Projects/Gamma")).unwrap();
|
||||
fs::create_dir_all(root.join("Logs")).unwrap();
|
||||
fs::create_dir_all(root.join("Reports")).unwrap();
|
||||
|
||||
fs::write(root.join("Projects/Alpha/draft1.md"), "- [ ] TODO foo\n").unwrap();
|
||||
fs::write(root.join("Projects/Alpha/draft2.md"), "- [x] TODO foo\n").unwrap();
|
||||
fs::write(root.join("Projects/Beta/final.md"), "done\n").unwrap();
|
||||
fs::write(root.join("Projects/Gamma/TODO.txt"), "TODO bar\n").unwrap();
|
||||
fs::write(root.join("Logs/app.log"), "ERROR omg\n").unwrap();
|
||||
fs::write(root.join("Reports/Q1.pdf"), "PDF\n").unwrap();
|
||||
}
|
||||
|
||||
fn run(cmd: &mut Command) -> assert_cmd::assert::Assert {
|
||||
cmd.assert().success()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn full_cli_flow() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// 1. sandbox
|
||||
let tmp = tempdir()?;
|
||||
let demo_dir = tmp.path().join("marlin_demo");
|
||||
spawn_demo_tree(&demo_dir);
|
||||
|
||||
// 2. init (auto-scan cwd)
|
||||
run(Command::new(marlin_bin())
|
||||
.current_dir(&demo_dir)
|
||||
.arg("init"));
|
||||
|
||||
// 3. tag & attr
|
||||
run(Command::new(marlin_bin())
|
||||
.arg("tag")
|
||||
.arg(format!("{}/Projects/**/*.md", demo_dir.display()))
|
||||
.arg("project/md"));
|
||||
|
||||
run(Command::new(marlin_bin())
|
||||
.arg("attr")
|
||||
.arg("set")
|
||||
.arg(format!("{}/Reports/*.pdf", demo_dir.display()))
|
||||
.arg("reviewed")
|
||||
.arg("yes"));
|
||||
|
||||
// 4. search expectations
|
||||
Command::new(marlin_bin())
|
||||
.arg("search")
|
||||
.arg("TODO")
|
||||
.assert()
|
||||
.stdout(predicate::str::contains("TODO.txt"));
|
||||
|
||||
Command::new(marlin_bin())
|
||||
.arg("search")
|
||||
.arg("attr:reviewed=yes")
|
||||
.assert()
|
||||
.stdout(predicate::str::contains("Q1.pdf"));
|
||||
|
||||
// 5. link & backlinks
|
||||
let foo = demo_dir.join("foo.txt");
|
||||
let bar = demo_dir.join("bar.txt");
|
||||
fs::write(&foo, "")?;
|
||||
fs::write(&bar, "")?;
|
||||
run(Command::new(marlin_bin()).arg("scan").arg(&demo_dir));
|
||||
run(Command::new(marlin_bin())
|
||||
.arg("link").arg("add")
|
||||
.arg(&foo).arg(&bar));
|
||||
Command::new(marlin_bin())
|
||||
.arg("link").arg("backlinks").arg(&bar)
|
||||
.assert()
|
||||
.stdout(predicate::str::contains("foo.txt"));
|
||||
|
||||
// 6. backup / restore round-trip
|
||||
let backup_path = String::from_utf8(
|
||||
Command::new(marlin_bin()).arg("backup").output()?.stdout
|
||||
)?;
|
||||
let backup_file = backup_path.split_whitespace().last().unwrap();
|
||||
|
||||
// wipe DB file
|
||||
std::fs::remove_file(dirs::data_dir().unwrap().join("marlin/index.db"))?;
|
||||
run(Command::new(marlin_bin()).arg("restore").arg(backup_file));
|
||||
|
||||
// sanity: search still works
|
||||
Command::new(marlin_bin())
|
||||
.arg("search").arg("TODO")
|
||||
.assert()
|
||||
.stdout(predicate::str::contains("TODO.txt"));
|
||||
|
||||
Ok(())
|
||||
}
|
68
tests/test.md
Normal file
68
tests/test.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Testing
|
||||
|
||||
Below is a **repeat-able 3-step flow** you can use **every time you pull fresh code**.
|
||||
|
||||
---
|
||||
|
||||
## 0 Prepare once
|
||||
|
||||
```bash
|
||||
# Run once (or add to ~/.bashrc) so debug + release artefacts land
|
||||
# in the same predictable place. Speeds-up future builds.
|
||||
export CARGO_TARGET_DIR=target
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1 Build the new binary
|
||||
|
||||
```bash
|
||||
git pull # grab the latest commit
|
||||
cargo build --release
|
||||
sudo install -Dm755 target/release/marlin /usr/local/bin/marlin
|
||||
```
|
||||
|
||||
* `cargo build --release` – builds the optimised binary.
|
||||
* `install …` – copies it into your `$PATH` so `marlin` on the CLI is the fresh one.
|
||||
|
||||
---
|
||||
|
||||
## 2 Run the smoke-test suite
|
||||
|
||||
```bash
|
||||
# Runs the end-to-end test we added in tests/e2e.rs
|
||||
cargo test --test e2e -- --nocapture
|
||||
```
|
||||
|
||||
* `--test e2e` – compiles and runs **only** `tests/e2e.rs`; other unit-tests are skipped (add them later if you like).
|
||||
* `--nocapture` – streams stdout/stderr so you can watch each CLI step in real time.
|
||||
* Exit-code **0** ➜ everything passed.
|
||||
Any non-zero exit or a red ✗ line means a step failed; the assert’s diff will show the command and its output.
|
||||
|
||||
---
|
||||
|
||||
## 3 (Optionally) run all tests
|
||||
|
||||
```bash
|
||||
cargo test --all -- --nocapture
|
||||
```
|
||||
|
||||
This will execute:
|
||||
|
||||
* unit tests in `src/**`
|
||||
* every file in `tests/`
|
||||
* doc-tests
|
||||
|
||||
If you wire **“cargo test --all”** into CI (GitHub Actions, GitLab, etc.), pushes that break a workflow will be rejected automatically.
|
||||
|
||||
---
|
||||
|
||||
### One-liner helper (copy/paste)
|
||||
|
||||
```bash
|
||||
git pull && cargo build --release &&
|
||||
sudo install -Dm755 target/release/marlin /usr/local/bin/marlin &&
|
||||
cargo test --test e2e -- --nocapture
|
||||
```
|
||||
|
||||
Stick that in a shell alias (`alias marlin-ci='…'`) and you’ve got a 5-second upgrade-and-verify loop.
|
Reference in New Issue
Block a user