Skip to main content
Glama
rebaser.rs11.4 kB
use base64::{ Engine, engine::general_purpose, }; use dal::{ AttributeValue, Component, DalContext, Func, FuncBackendKind, FuncBackendResponseType, func::argument::{ FuncArgument, FuncArgumentKind, }, }; use dal_test::{ helpers::{ ChangeSetTestHelpers, create_component_for_default_schema_name_in_default_view, }, test, }; use pretty_assertions_sorted::assert_eq; #[test] async fn modify_func_node(ctx: &mut DalContext) { let code_base64 = general_purpose::STANDARD_NO_PAD.encode("this is code"); let func = Func::new( ctx, "test", None::<String>, None::<String>, None::<String>, false, false, FuncBackendKind::JsAttribute, FuncBackendResponseType::Boolean, None::<String>, Some(code_base64.clone()), false, ) .await .expect("able to make a func"); ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx) .await .expect("could not commit and update snapshot to visibility"); Func::get_by_id(ctx, func.id) .await .expect("able to get func by id"); assert_eq!(Some(code_base64), func.code_base64); let new_code_base64 = general_purpose::STANDARD_NO_PAD.encode("this is new code"); let func = func .modify(ctx, |f| { f.name = "i changed this".into(); Ok(()) }) .await .expect("able to modify func"); ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx) .await .expect("could not commit"); let refetched_func = Func::get_by_id(ctx, func.id) .await .expect("able to fetch func"); assert_eq!("i changed this", refetched_func.name.as_str()); let func = func .modify(ctx, |f| { f.code_base64 = Some(new_code_base64.clone()); Ok(()) }) .await .expect("able to modify func"); ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx) .await .expect("could not commit and update snapshot to visibility"); let modified_func = Func::get_by_id(ctx, func.id) .await .expect("able to get func by id again"); assert_eq!( Some(new_code_base64.as_str()), modified_func.code_base64.as_deref() ); let funcs = Func::list_for_default_and_editing(ctx) .await .expect("able to list funcs"); let modified_func_again = funcs .iter() .find(|f| f.id == modified_func.id) .expect("func should be in list"); assert_eq!(Some(new_code_base64), modified_func_again.code_base64); } #[test] async fn func_node_with_arguments(ctx: &mut DalContext) { let code_base64 = general_purpose::STANDARD_NO_PAD.encode("this is code"); let func = Func::new( ctx, "test", None::<String>, None::<String>, None::<String>, false, false, FuncBackendKind::JsAttribute, FuncBackendResponseType::Boolean, None::<String>, Some(code_base64), false, ) .await .expect("able to make a func"); Func::get_by_id(ctx, func.id) .await .expect("able to get func by id before commit"); ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx) .await .expect("could not commit and update snapshot to visibility"); Func::get_by_id(ctx, func.id) .await .expect("able to get func by id after rebase"); let new_code_base64 = general_purpose::STANDARD_NO_PAD.encode("this is new code"); // modify func let func = func .modify(ctx, |f| { f.name = "test:modified".into(); f.code_base64 = Some(new_code_base64.clone()); Ok(()) }) .await .expect("able to modify func"); // create func arguments let arg_1 = FuncArgument::new(ctx, "argle bargle", FuncArgumentKind::Object, None, func.id) .await .expect("able to create func argument"); FuncArgument::new(ctx, "argy bargy", FuncArgumentKind::Object, None, func.id) .await .expect("able to create func argument 2"); ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx) .await .expect("could not commit and update snapshot to visibility"); let modified_func = Func::get_by_id(ctx, func.id) .await .expect("able to get func by id again"); assert_eq!( Some(new_code_base64).as_deref(), modified_func.code_base64.as_deref() ); assert_eq!("test:modified", modified_func.name.as_str()); let args = FuncArgument::list_for_func(ctx, modified_func.id) .await .expect("able to list args"); assert_eq!(2, args.len()); // Modify func argument FuncArgument::modify_by_id(ctx, arg_1.id, |arg| { arg.name = "bargle argle".into(); Ok(()) }) .await .expect("able to modify func"); let func_arg_refetch = FuncArgument::get_by_id(ctx, arg_1.id) .await .expect("get func arg"); assert_eq!( "bargle argle", func_arg_refetch.name.as_str(), "refetch should have updated func arg name" ); ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx) .await .expect("could not commit and update snapshot to visibility"); let args = FuncArgument::list_for_func(ctx, func.id) .await .expect("able to list args again"); assert_eq!(2, args.len()); let modified_arg = args .iter() .find(|a| a.id == arg_1.id) .expect("able to get modified func arg"); assert_eq!( "bargle argle", modified_arg.name.as_str(), "modified func arg should have new name after rebase" ); } #[test] async fn delete_func_node(ctx: &mut DalContext) { let code_base64 = general_purpose::STANDARD_NO_PAD.encode("this is code"); let func = Func::new( ctx, "test", None::<String>, None::<String>, None::<String>, false, false, FuncBackendKind::JsAttribute, FuncBackendResponseType::Boolean, None::<String>, Some(code_base64), false, ) .await .expect("able to make a func"); ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx) .await .expect("could not commit and update snapshot to visibility"); let snapshot_id_before_deletion = ctx.workspace_snapshot().expect("get snap").id().await; Func::get_by_id(ctx, func.id) .await .expect("able to get func by id"); Func::delete_by_id(ctx, func.id) .await .expect("able to remove func"); assert!(Func::get_by_id(ctx, func.id).await.is_err()); ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx) .await .expect("could not commit and update snapshot to visibility"); let snapshot_id_after_deletion = ctx.workspace_snapshot().expect("get snap").id().await; // A sanity check assert_ne!(snapshot_id_before_deletion, snapshot_id_after_deletion); let result = Func::get_by_id(ctx, func.id).await; assert!(result.is_err()); } #[test] async fn correctly_detect_unrelated_unmodified_data(ctx: &mut DalContext) -> dal_test::Result<()> { let shared_component_id = create_component_for_default_schema_name_in_default_view(ctx, "swifty", "Shared component") .await? .id(); ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx).await?; // Swifty is in HEAD ChangeSetTestHelpers::apply_change_set_to_base(ctx).await?; // Both change sets have Swifty in HEAD let change_set_a = ChangeSetTestHelpers::fork_from_head_change_set_with_name(ctx, "Change set A").await?; let change_set_b = ChangeSetTestHelpers::fork_from_head_change_set_with_name(ctx, "Change set B").await?; // Modify the shared component in change set A. ctx.update_visibility_and_snapshot_to_visibility(change_set_a.id) .await?; let cs_a_name_av_id = { let component = Component::get_by_id(ctx, shared_component_id).await?; component .attribute_values_for_prop(ctx, &["root", "si", "name"]) .await? .first() .copied() .expect("si.name attribute value not found") }; // Swifty in Change Set A has a name of 'Modified in change set A' AttributeValue::update( ctx, cs_a_name_av_id, Some(serde_json::json!("Modified in change set A")), ) .await?; // Change set A is committed to the rebaser ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx).await?; // Create a new component in change set B. ctx.update_visibility_and_snapshot_to_visibility(change_set_b.id) .await?; let _change_set_b_component_id = create_component_for_default_schema_name_in_default_view( ctx, "swifty", "Change Set B Component", ) .await? .id(); ChangeSetTestHelpers::commit_and_update_snapshot_to_visibility(ctx).await?; // Merge change set A to head. ctx.update_visibility_and_snapshot_to_visibility(change_set_a.id) .await?; ChangeSetTestHelpers::apply_change_set_to_base(ctx).await?; // Make sure the shared component looks as we'd expect. let expected_qualification_item_count = 1; let shared_component = Component::get_by_id(ctx, shared_component_id).await?; let av_ids = shared_component .attribute_values_for_prop(ctx, &["root", "si", "name"]) .await?; assert_eq!(av_ids.len(), 1, "Found more than one AV for si.name"); let av_ids = shared_component .attribute_values_for_prop(ctx, &["root", "domain", "name"]) .await?; assert_eq!(av_ids.len(), 1, "Found more than one AV for domain.name"); let av_ids = shared_component .attribute_values_for_prop(ctx, &["root", "qualification", "qualificationItem"]) .await?; assert_eq!( av_ids.len(), expected_qualification_item_count, "Found more than one AV for qualification.qualificationItem" ); // Merge change set B to head. ctx.update_visibility_and_snapshot_to_visibility(change_set_b.id) .await?; ChangeSetTestHelpers::apply_change_set_to_base(ctx).await?; // Make sure merging change set B didn't affect anything it didn't touch. let shared_component = Component::get_by_id(ctx, shared_component_id).await?; let av_ids = shared_component .attribute_values_for_prop(ctx, &["root", "si", "name"]) .await?; assert_eq!(av_ids.len(), 1, "Found more than one AV for si.name"); let av_ids = shared_component .attribute_values_for_prop(ctx, &["root", "domain", "name"]) .await?; assert_eq!(av_ids.len(), 1, "Found more than one AV for domain.name"); let av_ids = shared_component .attribute_values_for_prop(ctx, &["root", "qualification", "qualificationItem"]) .await?; assert_eq!( av_ids.len(), expected_qualification_item_count, "Found more than one AV for qualification.qualificationItem" ); 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