KeiSeiKit-1.0/_primitives/_rust/kei-entity-store/tests/archive_smoke.rs
Parfii-bot a4e667de10 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

99 lines
3.3 KiB
Rust

//! Archive-verb smoke tests.
//!
//! Covers kei-chat-store migration: schemas opt-in to soft-delete via
//! `archived_field: Some("archived")`. The verb flips the column + an
//! optional `<field>_at` sibling timestamp.
use kei_entity_store::schema::{EdgeKeyKind, EntitySchema, FieldDef};
use kei_entity_store::verbs::{archive, create, get};
use kei_entity_store::Store;
use serde_json::json;
static ARCHIVABLE_FIELDS: &[FieldDef] = &[
FieldDef::pk("id"),
FieldDef::text_nn("title"),
FieldDef::integer("archived"),
FieldDef::integer("archived_at"),
FieldDef::created_at(),
];
static ARCHIVABLE: EntitySchema = EntitySchema {
name: "msg",
table: "msgs",
fields: ARCHIVABLE_FIELDS,
enabled_verbs: &["create", "get", "archive"],
fts_columns: None,
edge_table: None,
edge_key_kind: EdgeKeyKind::IntegerPair,
archived_field: Some("archived"),
custom_migrations: &[],
};
static NO_ARCHIVE_FIELDS: &[FieldDef] = &[
FieldDef::pk("id"),
FieldDef::text_nn("title"),
FieldDef::created_at(),
];
static WITHOUT_FIELD: EntitySchema = EntitySchema {
name: "msg",
table: "msgs_plain",
fields: NO_ARCHIVE_FIELDS,
enabled_verbs: &["create", "archive"],
fts_columns: None,
edge_table: None,
edge_key_kind: EdgeKeyKind::IntegerPair,
archived_field: None,
custom_migrations: &[],
};
#[test]
fn archive_sets_flag_and_stamps_timestamp() {
let s = Store::open_memory(&[&ARCHIVABLE]).unwrap();
let v = create::run(s.conn(), &ARCHIVABLE, json!({ "title": "hi" })).unwrap();
let id = v["id"].as_i64().unwrap();
let before: i64 = chrono::Utc::now().timestamp();
let out = archive::run(s.conn(), &ARCHIVABLE, json!({ "id": id })).unwrap();
assert_eq!(out["id"].as_i64().unwrap(), id);
let stamped = out["archived_at"].as_i64().unwrap();
assert!(stamped >= before);
let row = get::run(s.conn(), &ARCHIVABLE, json!({ "id": id })).unwrap();
assert_eq!(row["archived"].as_i64().unwrap(), 1);
assert_eq!(row["archived_at"].as_i64().unwrap(), stamped);
}
#[test]
fn archive_preserves_id_and_other_fields() {
let s = Store::open_memory(&[&ARCHIVABLE]).unwrap();
let v = create::run(s.conn(), &ARCHIVABLE, json!({ "title": "keep" })).unwrap();
let id = v["id"].as_i64().unwrap();
archive::run(s.conn(), &ARCHIVABLE, json!({ "id": id })).unwrap();
let row = get::run(s.conn(), &ARCHIVABLE, json!({ "id": id })).unwrap();
assert_eq!(row["title"], "keep");
assert_eq!(row["id"].as_i64().unwrap(), id);
}
#[test]
fn archive_errors_when_archived_field_missing() {
let s = Store::open_memory(&[&WITHOUT_FIELD]).unwrap();
let v = create::run(s.conn(), &WITHOUT_FIELD, json!({ "title": "x" })).unwrap();
let id = v["id"].as_i64().unwrap();
let err = archive::run(s.conn(), &WITHOUT_FIELD, json!({ "id": id })).unwrap_err();
assert_eq!(err.exit_code(), 2);
}
#[test]
fn archive_not_found_errors() {
let s = Store::open_memory(&[&ARCHIVABLE]).unwrap();
let err = archive::run(s.conn(), &ARCHIVABLE, json!({ "id": 9999 })).unwrap_err();
assert_eq!(err.exit_code(), 2);
}
#[test]
fn archive_rejects_missing_id() {
let s = Store::open_memory(&[&ARCHIVABLE]).unwrap();
let err = archive::run(s.conn(), &ARCHIVABLE, json!({})).unwrap_err();
assert_eq!(err.exit_code(), 2);
}