use std::collections::BTreeMap;
use datacraft_core::command::Command;
use datacraft_core::core::Core;
use datacraft_core::event::Event;
use datacraft_core::port::{DriverCapabilities, MockPort, Support};
use datacraft_core::schema::{FieldDef, FieldKind, NumericKind, TableDef};
fn one_field_table() -> TableDef {
TableDef::new(
"Customers",
vec![FieldDef::new(
"id",
FieldKind::Number(NumericKind::LongInteger),
)],
)
}
fn core_with(caps: DriverCapabilities) -> Core {
let mut port = MockPort::with_tables(vec![one_field_table()]);
port.with_capabilities(caps);
let mut core = Core::new(Box::new(port));
let events = core.dispatch(Command::OpenDatabase {
path: std::path::PathBuf::from("shop.mdb"),
password: None,
source: None,
});
assert!(
matches!(events.first(), Some(Event::DatabaseOpened { .. })),
"{events:?}"
);
core
}
#[test]
fn restricted_capabilities_disable_the_matching_affordances() {
let mut caps = DriverCapabilities::full();
caps.create_table = false;
caps.drop_table = false;
caps.rename_table = false;
caps.write_rows = false;
caps.relationships = Support::No;
caps.passwords = false;
let core = core_with(caps);
let db = core.inspect().database.expect("database open");
assert_eq!(
db.availability,
BTreeMap::from([
(
"table".to_owned(),
datacraft_core::availability::DisabledReason::CreateTables,
),
(
"import_file".to_owned(),
datacraft_core::availability::DisabledReason::CreateTables,
),
(
"nav.delete".to_owned(),
datacraft_core::availability::DisabledReason::DropTables,
),
(
"nav.rename".to_owned(),
datacraft_core::availability::DisabledReason::RenameTables,
),
(
"datasheet.new_record".to_owned(),
datacraft_core::availability::DisabledReason::WriteRows,
),
(
"datasheet.delete_record".to_owned(),
datacraft_core::availability::DisabledReason::WriteRows,
),
(
"datasheet.edit_record".to_owned(),
datacraft_core::availability::DisabledReason::WriteRows,
),
(
"relationships".to_owned(),
datacraft_core::availability::DisabledReason::NoRelationships,
),
(
"relationships.create".to_owned(),
datacraft_core::availability::DisabledReason::NoRelationships,
),
(
"relationships.delete".to_owned(),
datacraft_core::availability::DisabledReason::NoRelationships,
),
(
"backstage.save_as".to_owned(),
datacraft_core::availability::DisabledReason::NoPasswords,
),
(
"backstage.change_password".to_owned(),
datacraft_core::availability::DisabledReason::NoPasswords,
),
])
);
}
#[test]
fn full_capabilities_leave_the_availability_map_empty() {
let core = core_with(DriverCapabilities::full());
let db = core.inspect().database.expect("database open");
assert!(db.availability.is_empty());
}
#[test]
fn relationship_write_affordances_gate_on_support_yes() {
let mut caps = DriverCapabilities::full();
caps.relationships = Support::ReadOnly;
let db = core_with(caps).inspect().database.expect("database open");
for id in ["relationships.create", "relationships.delete"] {
assert_eq!(
db.availability.get(id),
Some(&datacraft_core::availability::DisabledReason::NoRelationships),
"affordance {id:?} must be disabled for a read-only surface"
);
}
assert!(
!db.availability.contains_key("relationships"),
"the viewer affordance stays enabled for a read-only surface"
);
let mut caps = DriverCapabilities::full();
caps.relationships = Support::No;
let db = core_with(caps).inspect().database.expect("database open");
for id in [
"relationships",
"relationships.create",
"relationships.delete",
] {
assert_eq!(
db.availability.get(id),
Some(&datacraft_core::availability::DisabledReason::NoRelationships),
"affordance {id:?} must be disabled for a No surface"
);
}
let mut caps = DriverCapabilities::full();
caps.relationships = Support::Yes;
let db = core_with(caps).inspect().database.expect("database open");
assert!(db.availability.is_empty(), "{:?}", db.availability);
}
#[test]
fn disabled_reasons_serialize_stable_on_the_wire() {
use datacraft_core::availability::DisabledReason;
assert_eq!(
serde_json::to_value(DisabledReason::CreateTables).expect("serialize"),
serde_json::json!("create_tables")
);
assert_eq!(
serde_json::to_value(DisabledReason::WriteRows).expect("serialize"),
serde_json::json!("write_rows")
);
assert_eq!(
serde_json::to_value(DisabledReason::DropTables).expect("serialize"),
serde_json::json!("drop_tables")
);
assert_eq!(
serde_json::to_value(DisabledReason::NoRelationships).expect("serialize"),
serde_json::json!("no_relationships")
);
assert_eq!(
serde_json::to_value(DisabledReason::NoPasswords).expect("serialize"),
serde_json::json!("no_passwords")
);
assert_eq!(
serde_json::to_value(DisabledReason::AlterTables).expect("serialize"),
serde_json::json!("alter_tables")
);
assert_eq!(
serde_json::to_value(DisabledReason::CreateDatabase).expect("serialize"),
serde_json::json!("create_database")
);
assert_eq!(
serde_json::to_value(DisabledReason::RenameTables).expect("serialize"),
serde_json::json!("rename_tables")
);
}
#[test]
fn schema_edit_and_create_affordances_gate_on_their_capabilities() {
let mut caps = DriverCapabilities::full();
caps.alter_table = false;
caps.create_database = false;
let db = core_with(caps).inspect().database.expect("database open");
for id in [
"design.add_field",
"design.rename_field",
"design.drop_field",
"design.set_field_properties",
] {
assert_eq!(
db.availability.get(id),
Some(&datacraft_core::availability::DisabledReason::AlterTables),
"affordance {id:?} must be disabled for a source without alter_table"
);
}
assert_eq!(
db.availability.get("backstage.create_database"),
Some(&datacraft_core::availability::DisabledReason::CreateDatabase),
"the create-database affordance must be disabled without create_database"
);
let db = core_with(DriverCapabilities::full())
.inspect()
.database
.expect("database open");
for id in [
"design.add_field",
"design.rename_field",
"design.drop_field",
"design.set_field_properties",
"backstage.create_database",
] {
assert!(
!db.availability.contains_key(id),
"a capable source keeps {id:?} enabled"
);
}
}