Files
kebab/crates/kb-store-sqlite/tests/ingest_report_snapshot.rs
altair823 111f40ddf0 p1-6: kb-store-sqlite test suite (8 categories)
All 8 test categories from the task plan, plus a JobRepo subset:

  migration   — tests/migration.rs: fresh DB after run_migrations
                exposes every required §5 table + index.
  unit (copy) — tests/asset_writer.rs: copy mode writes file with
                mode 0o644 + correct bytes.
  unit (ref)  — tests/asset_writer.rs: reference mode does not write
                file; row records source path.
  unit (cs)   — tests/asset_writer.rs: tampered checksum returns a
                Conflict-flavoured anyhow error.
  unit (idem) — tests/idempotency.rs: same put_document twice → 1 row,
                doc_version 1→2; tags re-derived.
  unit (rb)   — tests/idempotency.rs: put_blocks with FK violation
                rolls back; pre-existing rows unchanged.
  contract    — tests/contract_roundtrip.rs: drives kb-parse-md +
                kb-normalize + kb-chunk on
                fixtures/markdown/code-and-table.md, persists, then
                reloads via DocumentStore::get_document /
                get_chunk and asserts byte-equal round-trip.
  snapshot    — tests/ingest_report_snapshot.rs +
                snapshots/ingest_report.snapshot.json: pin the wire
                JSON form of kb_core::IngestReport for an inline
                fixture run.
  jobs        — tests/jobs.rs: create → progress → finish flow;
                error message round-trip; list filters on status/kind.

Drops the unused `serde` direct dep from Cargo.toml; serde_json brings
its own. Dev-deps confirmed via `cargo tree -p kb-store-sqlite --depth 1`
to live only in the dev tree.
2026-04-30 17:13:03 +00:00

100 lines
3.6 KiB
Rust

//! Snapshot test pinning the JSON wire form of `kb_core::IngestReport`
//! for an inline fixture run. The store crate doesn't (yet) write
//! IngestReports — that's `kb-app`'s job — but the wire schema lives in
//! `kb-core`, and we want a determinism pin that fails loudly if the
//! shape drifts.
//!
//! Set `UPDATE_SNAPSHOTS=1` to re-bake the baseline.
use std::path::PathBuf;
use kb_core::{
AssetId, ChunkerVersion, DocumentId, IngestItem, IngestItemKind, IngestReport,
ParserVersion, SourceScope, WorkspacePath,
};
use serde_json::Value;
fn baseline_path() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("snapshots")
.join("ingest_report.snapshot.json")
}
fn fixture_report() -> IngestReport {
IngestReport {
scope: SourceScope {
root: PathBuf::from("/home/u/KB"),
include: vec!["**/*.md".into()],
exclude: vec![".git/**".into()],
},
scanned: 3,
new: 2,
updated: 1,
skipped: 0,
errors: 0,
duration_ms: 187,
items: Some(vec![
IngestItem {
kind: IngestItemKind::New,
doc_id: Some(DocumentId("a".repeat(32))),
doc_path: WorkspacePath::new("notes/alpha.md".into()).unwrap(),
asset_id: Some(AssetId("a".repeat(32))),
byte_len: Some(1234),
block_count: Some(7),
chunk_count: Some(3),
parser_version: Some(ParserVersion("pulldown-cmark-0.x".into())),
chunker_version: Some(ChunkerVersion("md-heading-v1".into())),
warnings: vec![],
error: None,
},
IngestItem {
kind: IngestItemKind::Updated,
doc_id: Some(DocumentId("b".repeat(32))),
doc_path: WorkspacePath::new("notes/beta.md".into()).unwrap(),
asset_id: Some(AssetId("b".repeat(32))),
byte_len: Some(2048),
block_count: Some(12),
chunk_count: Some(5),
parser_version: Some(ParserVersion("pulldown-cmark-0.x".into())),
chunker_version: Some(ChunkerVersion("md-heading-v1".into())),
warnings: vec!["malformed frontmatter".into()],
error: None,
},
]),
}
}
#[test]
fn ingest_report_wire_form_is_stable() {
let report = fixture_report();
let actual = serde_json::to_value(&report).unwrap();
let baseline = match std::fs::read_to_string(baseline_path()) {
Ok(s) => s,
Err(_) if std::env::var("UPDATE_SNAPSHOTS").is_ok() => {
std::fs::create_dir_all(baseline_path().parent().unwrap()).unwrap();
let pretty = serde_json::to_string_pretty(&actual).unwrap();
std::fs::write(baseline_path(), format!("{pretty}\n")).unwrap();
return;
}
Err(e) => panic!(
"missing baseline {}; run with UPDATE_SNAPSHOTS=1: {e}",
baseline_path().display()
),
};
let expected: Value = serde_json::from_str(&baseline).unwrap();
if actual != expected {
if std::env::var("UPDATE_SNAPSHOTS").is_ok() {
let pretty = serde_json::to_string_pretty(&actual).unwrap();
std::fs::write(baseline_path(), format!("{pretty}\n")).unwrap();
return;
}
let pretty = serde_json::to_string_pretty(&actual).unwrap();
panic!(
"ingest_report snapshot drift\n\
--- expected ({}) ---\n{baseline}\n\
--- actual ---\n{pretty}",
baseline_path().display()
);
}
}