experiment(core): implement typed source-default field policy
This commit is contained in:
@@ -0,0 +1,572 @@
|
||||
//! Independent field-map oracles for an isolated source-7 policy experiment.
|
||||
//! This does not wire the policy into the production formatter or source editor.
|
||||
#[path = "../../../harness/prototypes/source-defaults-20260913.rs"]
|
||||
mod policy;
|
||||
|
||||
use oa_core::{Kind, RelationKind};
|
||||
use policy::{Context, Mode};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
fn rendered(context: Context, input: &Value, mode: Mode) -> Value {
|
||||
Value::Object(policy::fields(context, input.as_object().unwrap(), mode))
|
||||
}
|
||||
|
||||
fn compact(context: Context, input: Value, expected: Value) {
|
||||
let original = input.clone();
|
||||
let result = rendered(context, &input, Mode::Compact);
|
||||
assert_eq!(result, expected, "context {context:?}");
|
||||
assert_eq!(input, original, "the input remains immutable");
|
||||
assert_eq!(
|
||||
rendered(context, &result, Mode::Compact),
|
||||
result,
|
||||
"compact policy is idempotent"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complete_comparison_restores_only_the_three_known_skips() {
|
||||
let exchange = json!({"body":{"Exchange":{"exchange":null,"sender":null,"receiver":null,"message_kind":"Asynchronous","reply_to":null,"values":[]}}});
|
||||
let mut complete = exchange.clone();
|
||||
complete["body"]["Exchange"]["operation"] = Value::Null;
|
||||
assert_eq!(
|
||||
rendered(
|
||||
Context::Element(Kind::Occurrence),
|
||||
&exchange,
|
||||
Mode::CompleteForEdit
|
||||
),
|
||||
complete
|
||||
);
|
||||
assert_eq!(
|
||||
rendered(
|
||||
Context::Node,
|
||||
&json!({"element":"e","diagram":"d"}),
|
||||
Mode::CompleteForEdit
|
||||
),
|
||||
json!({"element":"e","diagram":"d","port_anchors":[]})
|
||||
);
|
||||
assert_eq!(
|
||||
rendered(
|
||||
Context::Trace,
|
||||
&json!({"baseline":{"oa":{"name":"","description":""},"sa":{"name":"","description":""}}}),
|
||||
Mode::CompleteForEdit
|
||||
),
|
||||
json!({"baseline":{"oa":{"name":"","description":""},"sa":{"name":"","description":""},"semantic":null}})
|
||||
);
|
||||
for input in [
|
||||
json!({"body":{"Action":{"action":null,"lifeline":null}}}),
|
||||
json!({"body":{"State":{"state":null,"lifeline":null}}}),
|
||||
] {
|
||||
assert_eq!(
|
||||
rendered(
|
||||
Context::Element(Kind::Occurrence),
|
||||
&input,
|
||||
Mode::CompleteForEdit
|
||||
),
|
||||
input
|
||||
);
|
||||
}
|
||||
for input in [
|
||||
json!({"baseline":null}),
|
||||
json!({"baseline":{"semantic":{"historical":[null,[],false,0,""]},"oa":{"name":"n","description":""},"sa":{"name":"s","description":""}}}),
|
||||
] {
|
||||
assert_eq!(
|
||||
rendered(Context::Trace, &input, Mode::CompleteForEdit),
|
||||
input
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_element_omits_only_empty_common_defaults() {
|
||||
for kind in Kind::ALL {
|
||||
// Future/unknown payloads are preservation sentinels, not admitted source.
|
||||
compact(
|
||||
Context::Element(kind),
|
||||
json!({"description":"","parent":null,"future":{"empty":[],"absent":null,"zero":0,"flag":false}}),
|
||||
json!({"future":{"empty":[],"absent":null,"zero":0,"flag":false}}),
|
||||
);
|
||||
compact(
|
||||
Context::Element(kind),
|
||||
json!({"description":" \n","parent":"owner"}),
|
||||
json!({"description":" \n","parent":"owner"}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ordinary_element_defaults_are_context_specific() {
|
||||
for kind in [Kind::Process, Kind::FunctionalChain] {
|
||||
compact(Context::Element(kind), json!({"steps":[]}), json!({}));
|
||||
compact(
|
||||
Context::Element(kind),
|
||||
json!({"steps":["second","first"]}),
|
||||
json!({"steps":["second","first"]}),
|
||||
);
|
||||
}
|
||||
compact(
|
||||
Context::Element(Kind::ExchangeItem),
|
||||
json!({"kind":"Information","mechanism":"Unspecified","supertype":null}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Element(Kind::ExchangeItem),
|
||||
json!({"kind":"Energy","mechanism":"Flow","supertype":"base"}),
|
||||
json!({"kind":"Energy","mechanism":"Flow","supertype":"base"}),
|
||||
);
|
||||
compact(
|
||||
Context::Element(Kind::ExchangeCategory),
|
||||
json!({"family":"Work","exchanges":[]}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Element(Kind::ExchangeCategory),
|
||||
json!({"family":"Participant","exchanges":["x"]}),
|
||||
json!({"family":"Participant","exchanges":["x"]}),
|
||||
);
|
||||
compact(
|
||||
Context::Element(Kind::Interface),
|
||||
json!({"supertype":null}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Element(Kind::Lifeline),
|
||||
json!({"represented":null}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Element(Kind::Constraint),
|
||||
json!({"expression":"","constrained":[]}),
|
||||
json!({}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scenario_source_default_never_uses_the_graphical_viewpoint_default() {
|
||||
compact(
|
||||
Context::Element(Kind::Scenario),
|
||||
json!({"viewpoint":"MixedLegacy","context":null,"precondition":"","postcondition":"","steps":[]}),
|
||||
json!({}),
|
||||
);
|
||||
for viewpoint in [
|
||||
"OperationalActivity",
|
||||
"Functional",
|
||||
"ParticipantInteraction",
|
||||
"BoundaryInterface",
|
||||
] {
|
||||
compact(
|
||||
Context::Element(Kind::Scenario),
|
||||
json!({"viewpoint":viewpoint,"context":"scope","precondition":"ready","postcondition":"","steps":["two","one"]}),
|
||||
json!({"viewpoint":viewpoint,"context":"scope","precondition":"ready","steps":["two","one"]}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn each_state_header_supplies_its_own_kind() {
|
||||
for (kind, name) in [
|
||||
(Kind::State, "State"),
|
||||
(Kind::Mode, "Mode"),
|
||||
(Kind::Initial, "Initial"),
|
||||
(Kind::Final, "Final"),
|
||||
(Kind::Choice, "Choice"),
|
||||
(Kind::Junction, "Junction"),
|
||||
(Kind::Fork, "Fork"),
|
||||
(Kind::Join, "Join"),
|
||||
(Kind::ShallowHistory, "ShallowHistory"),
|
||||
(Kind::DeepHistory, "DeepHistory"),
|
||||
(Kind::EntryPoint, "EntryPoint"),
|
||||
(Kind::ExitPoint, "ExitPoint"),
|
||||
(Kind::Terminate, "Terminate"),
|
||||
] {
|
||||
compact(
|
||||
Context::Element(kind),
|
||||
json!({"kind":name,"entry":"","exit":"","do_activity":""}),
|
||||
json!({}),
|
||||
);
|
||||
}
|
||||
// Invalid mismatches must not be silently normalized by the writer policy.
|
||||
compact(
|
||||
Context::Element(Kind::Mode),
|
||||
json!({"kind":"State","entry":"work"}),
|
||||
json!({"kind":"State","entry":"work"}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_field_unbounded_and_present_empty_values_are_not_defaults() {
|
||||
compact(
|
||||
Context::Element(Kind::DataField),
|
||||
json!({"type_ref":"String","minimum":1,"maximum":1,"unit":"","direction":"Unspecified","storage":"Value","default":null}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Element(Kind::DataField),
|
||||
json!({"type_ref":{"Named":"record"},"minimum":0,"maximum":null,"unit":"m","direction":"Out","storage":"Reference","default":[]}),
|
||||
json!({"type_ref":{"Named":"record"},"minimum":0,"maximum":null,"unit":"m","direction":"Out","storage":"Reference","default":[]}),
|
||||
);
|
||||
for value in [
|
||||
json!({"Boolean":false}),
|
||||
json!({"Integer":0}),
|
||||
json!({"Real":0.0}),
|
||||
json!({"String":""}),
|
||||
] {
|
||||
compact(
|
||||
Context::Element(Kind::DataField),
|
||||
json!({"default":[value.clone()]}),
|
||||
json!({"default":[value]}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn data_definition_whole_default_and_selected_required_fields_differ() {
|
||||
compact(
|
||||
Context::Element(Kind::DataType),
|
||||
json!({"definition":{"String":{"minimum_length":0,"maximum_length":null}},"default":null,"unit":""}),
|
||||
json!({}),
|
||||
);
|
||||
for (input, expected) in [
|
||||
(
|
||||
json!({"Integer":{"minimum":null,"maximum":null}}),
|
||||
json!({"Integer":{}}),
|
||||
),
|
||||
(
|
||||
json!({"Real":{"minimum":null,"maximum":2.5}}),
|
||||
json!({"Real":{"maximum":2.5}}),
|
||||
),
|
||||
(
|
||||
json!({"String":{"minimum_length":4,"maximum_length":null}}),
|
||||
json!({"String":{"minimum_length":4}}),
|
||||
),
|
||||
(json!({"Record":{"supertype":null}}), json!({"Record":{}})),
|
||||
(
|
||||
json!({"Enumeration":{"literals":[]}}),
|
||||
json!({"Enumeration":{"literals":[]}}),
|
||||
),
|
||||
] {
|
||||
compact(
|
||||
Context::Element(Kind::DataType),
|
||||
json!({"definition":input}),
|
||||
json!({"definition":expected}),
|
||||
);
|
||||
}
|
||||
compact(
|
||||
Context::Element(Kind::DataType),
|
||||
json!({"definition":"Boolean","default":{"Boolean":false}}),
|
||||
json!({"definition":"Boolean","default":{"Boolean":false}}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn port_contract_and_its_required_payload_stay_explicit() {
|
||||
compact(
|
||||
Context::Element(Kind::Port),
|
||||
json!({"contract":"Legacy","legacy":{"direction":"Out","interface":null}}),
|
||||
json!({"contract":"Legacy","legacy":{"direction":"Out"}}),
|
||||
);
|
||||
for contract in [
|
||||
json!({"FunctionInput":{"incoming_items":[]}}),
|
||||
json!({"FunctionOutput":{"outgoing_items":[]}}),
|
||||
json!({"Component":{"kind":"Standard","orientation":"Unset"}}),
|
||||
] {
|
||||
compact(
|
||||
Context::Element(Kind::Port),
|
||||
json!({"contract":contract.clone(),"legacy":null}),
|
||||
json!({"contract":contract}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn occurrence_whole_default_is_distinct_from_selected_constructor_payload() {
|
||||
compact(
|
||||
Context::Element(Kind::Occurrence),
|
||||
json!({"body":{"Exchange":{"exchange":null,"sender":null,"receiver":null,"message_kind":"Asynchronous","reply_to":null,"values":[]}},"precondition":"","postcondition":""}),
|
||||
json!({}),
|
||||
);
|
||||
for (input, expected) in [
|
||||
(
|
||||
json!({"Action":{"action":null,"lifeline":null}}),
|
||||
json!({"Action":{}}),
|
||||
),
|
||||
(
|
||||
json!({"State":{"state":null,"lifeline":null}}),
|
||||
json!({"State":{}}),
|
||||
),
|
||||
(
|
||||
json!({"SequenceReference":{"sequence":null}}),
|
||||
json!({"SequenceReference":{}}),
|
||||
),
|
||||
(
|
||||
json!({"ScenarioUse":{"scenario":null,"bindings":[]}}),
|
||||
json!({"ScenarioUse":{"bindings":[]}}),
|
||||
),
|
||||
(
|
||||
json!({"Branch":{"guard":"","occurrences":[]}}),
|
||||
json!({"Branch":{"guard":"","occurrences":[]}}),
|
||||
),
|
||||
(
|
||||
json!({"Fragment":{"operator":"Parallel","branches":[]}}),
|
||||
json!({"Fragment":{"operator":"Parallel","branches":[]}}),
|
||||
),
|
||||
(
|
||||
json!({"Control":{"kind":"Choice"}}),
|
||||
json!({"Control":{"kind":"Choice"}}),
|
||||
),
|
||||
] {
|
||||
compact(
|
||||
Context::Element(Kind::Occurrence),
|
||||
json!({"body":input}),
|
||||
json!({"body":expected}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unresolved_operation_and_required_message_value_are_preserved() {
|
||||
compact(
|
||||
Context::Element(Kind::Occurrence),
|
||||
json!({"body":{"Exchange":{"exchange":null,"sender":null,"receiver":null,"message_kind":"Asynchronous","reply_to":null,"values":[{"field":"f","path":[],"expression":""}],"operation":{"allocation":null}}}}),
|
||||
json!({"body":{"Exchange":{"values":[{"field":"f","expression":""}],"operation":{}}}}),
|
||||
);
|
||||
compact(
|
||||
Context::Element(Kind::Occurrence),
|
||||
json!({"body":{"Exchange":{"exchange":"flow","sender":"a","receiver":"b","message_kind":{"Timer":{"expression":""}},"reply_to":"request","values":[],"operation":null}}}),
|
||||
json!({"body":{"Exchange":{"exchange":"flow","sender":"a","receiver":"b","message_kind":{"Timer":{"expression":""}},"reply_to":"request"}}}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn event_body_whole_default_does_not_prune_selected_required_fields() {
|
||||
compact(
|
||||
Context::Element(Kind::Event),
|
||||
json!({"body":{"Signal":{"items":[]}}}),
|
||||
json!({}),
|
||||
);
|
||||
for body in [
|
||||
json!({"Signal":{"items":["i"]}}),
|
||||
json!({"Time":{"kind":"After","expression":""}}),
|
||||
json!({"Change":{"expression":""}}),
|
||||
] {
|
||||
compact(
|
||||
Context::Element(Kind::Event),
|
||||
json!({"body":body.clone()}),
|
||||
json!({"body":body}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relation_required_endpoints_and_contextual_payloads_remain() {
|
||||
for kind in RelationKind::ALL {
|
||||
compact(
|
||||
Context::Relation(kind),
|
||||
json!({"description":"","source":"s","target":"t","future":[]}),
|
||||
json!({"source":"s","target":"t","future":[]}),
|
||||
);
|
||||
}
|
||||
compact(
|
||||
Context::Relation(RelationKind::FunctionalExchange),
|
||||
json!({"source":"s","target":"t","source_port":"sp","target_port":"tp","items":[]}),
|
||||
json!({"source":"s","target":"t","source_port":"sp","target_port":"tp"}),
|
||||
);
|
||||
let contextual = json!({"owner":"o","source":{"references":[],"occurrence":"s"},"target":{"references":[],"occurrence":"t"},"purpose":{"Precedence":{"guard":""}}});
|
||||
compact(
|
||||
Context::Relation(RelationKind::ContextualLink),
|
||||
contextual.clone(),
|
||||
contextual,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relation_defaults_preserve_contextual_orientation_and_multiplicity() {
|
||||
for (kind, orientation) in [
|
||||
(RelationKind::BoundaryExchange, true),
|
||||
(RelationKind::CommunicationMean, false),
|
||||
] {
|
||||
compact(
|
||||
Context::Relation(kind),
|
||||
json!({"oriented":orientation,"items":[]}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Relation(kind),
|
||||
json!({"oriented":!orientation}),
|
||||
json!({"oriented":!orientation}),
|
||||
);
|
||||
}
|
||||
compact(
|
||||
Context::Relation(RelationKind::DataAssociation),
|
||||
json!({"source_role":"","target_role":"","source_minimum":0,"target_minimum":0,"source_maximum":null,"target_maximum":null,"source_navigable":false,"target_navigable":false}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Relation(RelationKind::DataAssociation),
|
||||
json!({"source_maximum":0,"target_maximum":1,"source_navigable":true}),
|
||||
json!({"source_maximum":0,"target_maximum":1,"source_navigable":true}),
|
||||
);
|
||||
compact(
|
||||
Context::Relation(RelationKind::InterfaceItemAllocation),
|
||||
json!({"order":0,"transmission":"Unspecified","acquisition":"Unspecified"}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Relation(RelationKind::CapabilityExtend),
|
||||
json!({"condition":""}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Relation(RelationKind::SequenceLink),
|
||||
json!({"guard":""}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Relation(RelationKind::StateAction),
|
||||
json!({"phase":"Do"}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Relation(RelationKind::StateTransition),
|
||||
json!({"transition_kind":"External","trigger":"","guard":"","effect":"","triggers":[],"effects":[]}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Relation(RelationKind::StateTransition),
|
||||
json!({"transition_kind":"Internal","triggers":["t"],"effects":["e"]}),
|
||||
json!({"transition_kind":"Internal","triggers":["t"],"effects":["e"]}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diagram_options_remove_only_unrestricted_defaults() {
|
||||
let defaults = json!({"hidden_edges":[],"relation_kinds":"All","work_categories":"All","participant_categories":"All","coverage":"All","work_contexts":"All","exchange_labels":"Name"});
|
||||
compact(
|
||||
Context::Diagram,
|
||||
json!({"description":"","layer":"Oa","projection":"Overview","routes":[],"view_options":defaults}),
|
||||
json!({}),
|
||||
);
|
||||
compact(
|
||||
Context::Diagram,
|
||||
json!({"layer":"Sa","projection":{"StateMachine":{"machine":"m"}},"view_options":{"hidden_edges":[],"relation_kinds":{"Only":[]},"work_categories":{"Any":[]},"participant_categories":"All","coverage":"All","work_contexts":{"Any":[]},"exchange_labels":"Name"}}),
|
||||
json!({"layer":"Sa","projection":{"StateMachine":{"machine":"m"}},"view_options":{"relation_kinds":{"Only":[]},"work_categories":{"Any":[]},"work_contexts":{"Any":[]}}}),
|
||||
);
|
||||
compact(
|
||||
Context::Diagram,
|
||||
json!({"routes":[{"edge":"e","waypoints":[],"label":null}]}),
|
||||
json!({"routes":[{"edge":"e"}]}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn node_whole_defaults_preserve_negative_zero_and_required_coordinates() {
|
||||
compact(
|
||||
Context::Node,
|
||||
json!({"diagram":"d","element":"e","position":{"x":0.0,"y":0.0},"size":{"width":224.0,"height":94.0},"collapsed":false}),
|
||||
json!({"diagram":"d","element":"e"}),
|
||||
);
|
||||
for position in [
|
||||
json!({"x":-0.0,"y":0.0}),
|
||||
json!({"x":0.0,"y":-0.0}),
|
||||
json!({"x":1.0,"y":0.0}),
|
||||
] {
|
||||
let result = rendered(
|
||||
Context::Node,
|
||||
&json!({"position":position.clone()}),
|
||||
Mode::Compact,
|
||||
);
|
||||
assert_eq!(result, json!({"position":position.clone()}));
|
||||
for coordinate in ["x", "y"] {
|
||||
assert_eq!(
|
||||
result["position"][coordinate].as_f64().unwrap().to_bits(),
|
||||
position[coordinate].as_f64().unwrap().to_bits(),
|
||||
"coordinate sign is part of fidelity"
|
||||
);
|
||||
}
|
||||
}
|
||||
compact(
|
||||
Context::Node,
|
||||
json!({"size":{"width":300.0,"height":94.0},"port_anchors":[{"port":"p","side":"Left","offset":0.0}]}),
|
||||
json!({"size":{"width":300.0,"height":94.0},"port_anchors":[{"port":"p","side":"Left","offset":0.0}]}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn artifact_present_empty_strings_and_trace_history_stay_distinct() {
|
||||
compact(
|
||||
Context::Artifact,
|
||||
json!({"owner":"o","description":"","relation":"References","uri":"","revision":null,"fragment":null}),
|
||||
json!({"owner":"o"}),
|
||||
);
|
||||
compact(
|
||||
Context::Artifact,
|
||||
json!({"owner":"o","relation":"Implements","revision":"","fragment":""}),
|
||||
json!({"owner":"o","relation":"Implements","revision":"","fragment":""}),
|
||||
);
|
||||
compact(
|
||||
Context::Trace,
|
||||
json!({"oa":"o","sa":"s","description":"","kind":"Refinement","baseline":null}),
|
||||
json!({"oa":"o","sa":"s"}),
|
||||
);
|
||||
compact(
|
||||
Context::Trace,
|
||||
json!({"baseline":{"oa":{"name":"","description":""},"sa":{"name":"s","description":""}}}),
|
||||
json!({"baseline":{"oa":{"name":"","description":""},"sa":{"name":"s","description":""}}}),
|
||||
);
|
||||
let baseline = json!({"oa":{"name":"o","description":""},"sa":{"name":"s","description":""},"semantic":{"facets":[{"Value":null},{"Value":[]},{"Value":false},{"Value":0},{"Value":""}]}});
|
||||
compact(
|
||||
Context::Trace,
|
||||
json!({"kind":"Manual","baseline":baseline.clone()}),
|
||||
json!({"kind":"Manual","baseline":baseline}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_future_fields_prevent_whole_default_removal() {
|
||||
// These sentinels exercise preservation, not current parser admission of
|
||||
// unknown fields. Only known slots may lose their redundant defaults.
|
||||
compact(
|
||||
Context::Element(Kind::DataType),
|
||||
json!({"definition":{"String":{"minimum_length":0,"maximum_length":null,"future":[]}}}),
|
||||
json!({"definition":{"String":{"minimum_length":0,"future":[]}}}),
|
||||
);
|
||||
compact(
|
||||
Context::Element(Kind::Occurrence),
|
||||
json!({"body":{"Exchange":{"exchange":null,"sender":null,"receiver":null,"message_kind":"Asynchronous","reply_to":null,"values":[],"operation":null,"future":false}}}),
|
||||
json!({"body":{"Exchange":{"future":false}}}),
|
||||
);
|
||||
compact(
|
||||
Context::Diagram,
|
||||
json!({"view_options":{"hidden_edges":[],"relation_kinds":"All","work_categories":"All","participant_categories":"All","coverage":"All","work_contexts":"All","exchange_labels":"Name","future":null}}),
|
||||
json!({"view_options":{"future":null}}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_and_multikey_constructor_wrappers_are_not_reinterpreted() {
|
||||
for definition in [
|
||||
json!({"Future":{"minimum":null,"maximum":null}}),
|
||||
json!({"String":{"minimum_length":0,"maximum_length":null},"Future":{}}),
|
||||
] {
|
||||
compact(
|
||||
Context::Element(Kind::DataType),
|
||||
json!({"definition":definition.clone()}),
|
||||
json!({"definition":definition}),
|
||||
);
|
||||
}
|
||||
for body in [
|
||||
json!({"Future":{"operation":null,"values":[]}}),
|
||||
json!({"Exchange":{"exchange":null,"values":[]},"Future":{}}),
|
||||
] {
|
||||
let fields = json!({"body":body});
|
||||
assert_eq!(
|
||||
rendered(
|
||||
Context::Element(Kind::Occurrence),
|
||||
&fields,
|
||||
Mode::CompleteForEdit
|
||||
),
|
||||
fields,
|
||||
"do not invent a selected Exchange constructor in an unknown wrapper",
|
||||
);
|
||||
compact(Context::Element(Kind::Occurrence), fields.clone(), fields);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user