Skip to main content
Glama
attribute_value.rs7.42 kB
use dal::{ AttributeValue, ChangeSet, Component, DalContext, }; use dal_test::{ Result, expected::ExpectComponent, helpers::{ ChangeSetTestHelpers, attribute::value, change_set, component, schema::variant, }, test, }; use pretty_assertions_sorted::assert_eq; use serde_json::json; mod subscription; #[test] async fn arguments_for_prototype_function_execution(ctx: &mut DalContext) -> Result<()> { // Create a component and commit. For context, the test exclusive schema has the identity // function set on "/root/domain/name" with an input from "/root/si/name". We need to ensure // that the value of "/root/si/name" comes in, as expected. The name is set when creating a // component, so we do not need to do additional setup. let expected = "you should see this name in the arguments"; let component = ExpectComponent::create_named(ctx, "swifty", expected).await; let name_prop = component.prop(ctx, ["root", "domain", "name"]).await; ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx).await?; // Ensure that the arguments look as we expect. let name_av_id = name_prop.attribute_value(ctx).await.id(); let (_, arguments, _) = AttributeValue::prepare_arguments_for_prototype_function_execution(ctx, name_av_id).await?; assert_eq!( json![{ "identity": expected }], arguments ); Ok(()) } #[test] async fn attribute_value_path(ctx: &mut DalContext) -> Result<()> { // Create a component and commit. For context, the test exclusive schema has the identity // function set on "/root/domain/name" with an input from "/root/si/name". We need to ensure // that the value of "/root/si/name" comes in, as expected. The name is set when creating a // component, so we do not need to do additional setup. variant::create( ctx, "test", r#" function main() { return { props: [ { name: "Value", kind: "string" }, { name: "Values", kind: "array", entry: { name: "ValuesItem", kind: "string" }, }, { name: "ValueMap", kind: "map", entry: { name: "ValueMapItem", kind: "string" }, }, ] }; } "#, ) .await?; let component_id = component::create(ctx, "test", "test").await?; // Check object paths { let value = Component::attribute_value_for_prop(ctx, component_id, &["root", "domain", "Value"]) .await?; AttributeValue::update(ctx, value, Some(json!("test"))).await?; assert_eq!( AttributeValue::path_from_root(ctx, value).await?.1, "/domain/Value" ); } // Check array paths { let values = Component::attribute_value_for_prop(ctx, component_id, &["root", "domain", "Values"]) .await?; AttributeValue::update(ctx, values, Some(json!(["1", "2", "3"]))).await?; let values_elements = AttributeValue::get_child_av_ids_in_order(ctx, values).await?; assert_eq!( AttributeValue::path_from_root(ctx, values).await?.1, "/domain/Values" ); assert_eq!( AttributeValue::path_from_root(ctx, values_elements[0]) .await? .1, "/domain/Values/0" ); } // Check map paths { let value_map = Component::attribute_value_for_prop(ctx, component_id, &["root", "domain", "ValueMap"]) .await?; AttributeValue::update(ctx, value_map, Some(json!({ "a": "1", "b": "2", "c": "3"}))) .await?; let value_map_elements = AttributeValue::map_children(ctx, value_map).await?; assert_eq!( AttributeValue::path_from_root(ctx, value_map).await?.1, "/domain/ValueMap" ); assert_eq!( AttributeValue::path_from_root(ctx, *value_map_elements.get("a").unwrap()) .await? .1, "/domain/ValueMap/a" ); } Ok(()) } #[test] async fn update_object_multiplayer(ctx: &mut DalContext) -> Result<()> { // Create a variant that will be in all three change sets variant::create( ctx, "test", r#" function main() { return { props: [ { name: "ObjectValue", kind: "object", children: [ { name: "a", kind: "string" }, { name: "b", kind: "string" }, { name: "both", kind: "string" }, { name: "neither", kind: "string" }, ] }, { name: "ArrayOfObjectValues", kind: "array", entry: { name: "ArrayOfObjectValuesItem", kind: "object", children: [ { name: "a", kind: "string" }, { name: "b", kind: "string" }, { name: "both", kind: "string" }, { name: "neither", kind: "string" }, ] }, }, { name: "MapOfObjectValues", kind: "map", entry: { name: "MapOfObjectValuesItem", kind: "object", children: [ { name: "a", kind: "string" }, { name: "b", kind: "string" }, { name: "both", kind: "string" }, { name: "neither", kind: "string" }, ] }, }, ] }; } "#, ) .await?; component::create(ctx, "test", "test").await?; // Give them all initial values (testing the case where the value is already set, and changesets update) let attrs = [ ("test", "/domain/ObjectValue"), ("test", "/domain/ArrayOfObjectValues/0"), ("test", "/domain/MapOfObjectValues/val"), ]; for &attr in &attrs { value::set(ctx, attr, json!({})).await?; } change_set::commit(ctx).await?; // Two players update the object in parallel. let (player1, player2) = (ctx.clone(), ctx.clone()); { for &attr in &attrs { value::set(&player1, attr, json!({ "a": "a", "both": "a"})).await?; } player1.commit().await?; } { for &attr in &attrs { value::set(&player2, attr, json!({ "b": "b", "both": "b"})).await?; } player2.commit().await?; } // Check its effect on the merged changeset ChangeSet::wait_for_dvu(ctx, false).await?; for &attr in &attrs { // The object must have exactly 4 child AVs and the value should be the merged value let av_id = value::id(ctx, attr).await?; assert_eq!(4, AttributeValue::child_av_ids(ctx, av_id).await?.len(),); assert_eq!( json!({ "b": "b", "both": "b", "a": "a" }), value::get(ctx, attr).await?, ); } Ok(()) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server