Files
modeling-app/rust/kcl-lib/e2e/modify/main.rs
Jess Frazelle 3f02bb2065 deterministic id generator per module (#5811)
* deterministic id generator per module

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* non

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* do not remake the planes if they are alreaady made;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* do not remake the planes if they are alreaady made;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* clippy

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-03-15 17:08:39 +00:00

233 lines
7.0 KiB
Rust

use anyhow::Result;
use kcl_lib::{
exec::{KclValue, PlaneType},
modify_ast_for_sketch, ExecState, ExecutorContext, ModuleId, Program, SourceRange,
};
use kittycad_modeling_cmds::{each_cmd as mcmd, length_unit::LengthUnit, shared::Point3d, ModelingCmd};
use pretty_assertions::assert_eq;
/// Setup the engine and parse code for an ast.
async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, ModuleId, uuid::Uuid)> {
let program = Program::parse_no_errs(code)?;
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()).await?;
let mut exec_state = ExecState::new(&ctx);
let result = ctx.run(&program, &mut exec_state).await?;
let outcome = exec_state.to_wasm_outcome(result.0).await;
// We need to get the sketch ID.
let KclValue::Sketch { value: sketch } = outcome.variables.get(name).unwrap() else {
anyhow::bail!("part001 not found in: {:?}", outcome.variables);
};
let sketch_id = sketch.id;
let plane_id = uuid::Uuid::new_v4();
ctx.engine
.send_modeling_cmd(
plane_id,
SourceRange::default(),
&ModelingCmd::from(mcmd::MakePlane {
clobber: false,
origin: Point3d::default(),
size: LengthUnit(60.0),
x_axis: Point3d { x: 1.0, y: 0.0, z: 0.0 },
y_axis: Point3d { x: 0.0, y: 1.0, z: 0.0 },
hide: Some(true),
}),
)
.await?;
// Enter sketch mode.
// We can't get control points without being in sketch mode.
// You can however get path info without sketch mode.
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
SourceRange::default(),
&ModelingCmd::from(mcmd::EnableSketchMode {
animated: false,
ortho: true,
entity_id: plane_id,
planar_normal: Some(Point3d { x: 0.0, y: 0.0, z: 1.0 }),
adjust_camera: false,
}),
)
.await?;
Ok((ctx, program, ModuleId::default(), sketch_id))
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_modify_sketch_part001() {
let name = "part001";
let code = format!(
r#"{} = startSketchOn("XY")
|> startProfileAt([8.41, 5.78], %)
|> line(end = [7.37, -11])
|> line(end = [-8.69, -3.75])
|> line(end = [-5, 4.25])
"#,
name
);
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
.await
.unwrap();
// Make sure the code is the same.
assert_eq!(code, new_code);
// Make sure the program is the same.
assert_eq!(new_program, program);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_modify_sketch_part002() {
let name = "part002";
let code = format!(
r#"{} = startSketchOn("XY")
|> startProfileAt([8.41, 5.78], %)
|> line(end = [7.42, -8.62])
|> line(end = [-6.38, -3.51])
|> line(end = [-3.77, 3.56])
"#,
name
);
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
.await
.unwrap();
// Make sure the code is the same.
assert_eq!(code, new_code);
// Make sure the program is the same.
assert_eq!(new_program, program);
}
#[tokio::test(flavor = "multi_thread")]
#[ignore] // until KittyCAD/engine#1434 is fixed.
async fn kcl_test_modify_close_sketch() {
let name = "part002";
let code = format!(
r#"{} = startSketchOn("XY")
|> startProfileAt([7.91, 3.89], %)
|> line(end = [7.42, -8.62])
|> line(end = [-6.38, -3.51])
|> line(end = [-3.77, 3.56])
|> close()
"#,
name
);
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
.await
.unwrap();
// Make sure the code is the same.
assert_eq!(code, new_code);
// Make sure the program is the same.
assert_eq!(new_program, program);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_modify_line_to_close_sketch() {
let name = "part002";
let code = format!(
r#"const {} = startSketchOn("XY")
|> startProfileAt([7.91, 3.89], %)
|> line(end = [7.42, -8.62])
|> line(end = [-6.38, -3.51])
|> line(end = [-3.77, 3.56])
|> line(endAbsolute = [7.91, 3.89])
"#,
name
);
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
.await
.unwrap();
// Make sure the code is the same.
assert_eq!(
new_code,
format!(
r#"{} = startSketchOn("XY")
|> startProfileAt([7.91, 3.89], %)
|> line(end = [7.42, -8.62])
|> line(end = [-6.38, -3.51])
|> line(end = [-3.77, 3.56])
|> close()
"#,
name
)
);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_modify_with_constraint() {
let name = "part002";
let code = format!(
r#"const thing = 12
const {} = startSketchOn("XY")
|> startProfileAt([7.91, 3.89], %)
|> line(end = [7.42, -8.62])
|> line(end = [-6.38, -3.51])
|> line(end = [-3.77, 3.56])
|> line(endAbsolute = [thing, 3.89])
"#,
name
);
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let result = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id).await;
assert!(result.is_err());
assert_eq!(
result.unwrap_err().message(),
"Sketch part002 is constrained `partial` and cannot be modified",
);
}
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_modify_line_should_close_sketch() {
let name = "part003";
let code = format!(
r#"const {} = startSketchOn("XY")
|> startProfileAt([13.69, 3.8], %)
|> line(end = [4.23, -11.79])
|> line(end = [-10.7, -1.16])
|> line(end = [-3.72, 8.69])
|> line(end = [10.19, 4.26])
"#,
name
);
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
let mut new_program = program.clone();
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
.await
.unwrap();
// Make sure the code is the same.
assert_eq!(
new_code,
format!(
r#"{} = startSketchOn("XY")
|> startProfileAt([13.69, 3.8], %)
|> line(end = [4.23, -11.79])
|> line(end = [-10.7, -1.16])
|> line(end = [-3.72, 8.69])
|> close()
"#,
name
)
);
}