Compare commits
7 Commits
pierremtb/
...
achalmers-
Author | SHA1 | Date | |
---|---|---|---|
9b29b08f62 | |||
46c613288c | |||
541dcd9a41 | |||
b5bf85d420 | |||
4eee73f471 | |||
7462eee89c | |||
17945cac6d |
@ -112,7 +112,8 @@ test.describe('when using the file tree to', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
panesOpen,
|
openKclCodePanel,
|
||||||
|
openFilePanel,
|
||||||
createAndSelectProject,
|
createAndSelectProject,
|
||||||
pasteCodeInEditor,
|
pasteCodeInEditor,
|
||||||
createNewFileAndSelect,
|
createNewFileAndSelect,
|
||||||
@ -124,9 +125,9 @@ test.describe('when using the file tree to', () => {
|
|||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
page.on('console', console.log)
|
page.on('console', console.log)
|
||||||
|
|
||||||
await panesOpen(['files', 'code'])
|
|
||||||
|
|
||||||
await createAndSelectProject('project-000')
|
await createAndSelectProject('project-000')
|
||||||
|
await openKclCodePanel()
|
||||||
|
await openFilePanel()
|
||||||
// File the main.kcl with contents
|
// File the main.kcl with contents
|
||||||
const kclCube = await fsp.readFile(
|
const kclCube = await fsp.readFile(
|
||||||
'src/wasm-lib/tests/executor/inputs/cube.kcl',
|
'src/wasm-lib/tests/executor/inputs/cube.kcl',
|
||||||
|
@ -585,6 +585,15 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Sorry I don't have time to fix this right now, but runs like
|
||||||
|
* the one linked below show me that setting the open panes in this manner is not reliable.
|
||||||
|
* You can either set `openPanes` as a part of the same initScript we run in setupElectron/setup,
|
||||||
|
* or you can imperatively open the panes with functions like {openKclCodePanel}
|
||||||
|
* (or we can make a general openPane function that takes a paneId).,
|
||||||
|
* but having a separate initScript does not seem to work reliably.
|
||||||
|
* @link https://github.com/KittyCAD/modeling-app/actions/runs/10731890169/job/29762700806?pr=3807#step:20:19553
|
||||||
|
*/
|
||||||
panesOpen: async (paneIds: PaneId[]) => {
|
panesOpen: async (paneIds: PaneId[]) => {
|
||||||
return test?.step(`Setting ${paneIds} panes to be open`, async () => {
|
return test?.step(`Setting ${paneIds} panes to be open`, async () => {
|
||||||
await page.addInitScript(
|
await page.addInitScript(
|
||||||
|
@ -368,10 +368,10 @@ test.describe('Testing settings', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
panesOpen,
|
openKclCodePanel,
|
||||||
|
openFilePanel,
|
||||||
createAndSelectProject,
|
createAndSelectProject,
|
||||||
pasteCodeInEditor,
|
pasteCodeInEditor,
|
||||||
clickPane,
|
|
||||||
createNewFileAndSelect,
|
createNewFileAndSelect,
|
||||||
editorTextMatches,
|
editorTextMatches,
|
||||||
} = await getUtils(page, test)
|
} = await getUtils(page, test)
|
||||||
@ -379,8 +379,6 @@ test.describe('Testing settings', () => {
|
|||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
page.on('console', console.log)
|
page.on('console', console.log)
|
||||||
|
|
||||||
await panesOpen([])
|
|
||||||
|
|
||||||
await test.step('Precondition: No projects exist', async () => {
|
await test.step('Precondition: No projects exist', async () => {
|
||||||
await expect(page.getByTestId('home-section')).toBeVisible()
|
await expect(page.getByTestId('home-section')).toBeVisible()
|
||||||
const projectLinksPre = page.getByTestId('project-link')
|
const projectLinksPre = page.getByTestId('project-link')
|
||||||
@ -389,14 +387,14 @@ test.describe('Testing settings', () => {
|
|||||||
|
|
||||||
await createAndSelectProject('project-000')
|
await createAndSelectProject('project-000')
|
||||||
|
|
||||||
await clickPane('code')
|
await openKclCodePanel()
|
||||||
const kclCube = await fsp.readFile(
|
const kclCube = await fsp.readFile(
|
||||||
'src/wasm-lib/tests/executor/inputs/cube.kcl',
|
'src/wasm-lib/tests/executor/inputs/cube.kcl',
|
||||||
'utf-8'
|
'utf-8'
|
||||||
)
|
)
|
||||||
await pasteCodeInEditor(kclCube)
|
await pasteCodeInEditor(kclCube)
|
||||||
|
|
||||||
await clickPane('files')
|
await openFilePanel()
|
||||||
await createNewFileAndSelect('2.kcl')
|
await createNewFileAndSelect('2.kcl')
|
||||||
|
|
||||||
const kclCylinder = await fsp.readFile(
|
const kclCylinder = await fsp.readFile(
|
||||||
|
@ -690,40 +690,53 @@ test(
|
|||||||
'Text-to-CAD functionality',
|
'Text-to-CAD functionality',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ browserName }, testInfo) => {
|
async ({ browserName }, testInfo) => {
|
||||||
|
const projectName = 'project-000'
|
||||||
|
const prompt = 'lego 2x4'
|
||||||
|
const textToCadFileName = 'lego-2x4.kcl'
|
||||||
|
|
||||||
const { electronApp, page, dir } = await setupElectron({ testInfo })
|
const { electronApp, page, dir } = await setupElectron({ testInfo })
|
||||||
const fileExists = () =>
|
const fileExists = () =>
|
||||||
fs.existsSync(join(dir, 'project-000', 'lego-2x4.kcl'))
|
fs.existsSync(join(dir, projectName, textToCadFileName))
|
||||||
|
|
||||||
const { createAndSelectProject, panesOpen } = await getUtils(page, test)
|
const {
|
||||||
|
createAndSelectProject,
|
||||||
|
openFilePanel,
|
||||||
|
openKclCodePanel,
|
||||||
|
waitForPageLoad,
|
||||||
|
} = await getUtils(page, test)
|
||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await panesOpen(['code', 'files'])
|
// Locators
|
||||||
|
const projectMenuButton = page.getByRole('button', { name: projectName })
|
||||||
|
const textToCadFileButton = page.getByRole('listitem').filter({
|
||||||
|
has: page.getByRole('button', { name: textToCadFileName }),
|
||||||
|
})
|
||||||
|
const textToCadComment = page.getByText(
|
||||||
|
`// Generated by Text-to-CAD: ${prompt}`
|
||||||
|
)
|
||||||
|
|
||||||
// Create and navigate to the project
|
// Create and navigate to the project
|
||||||
await createAndSelectProject('project-000')
|
await createAndSelectProject('project-000')
|
||||||
|
|
||||||
// Wait for Start Sketch otherwise you will not have access Text-to-CAD command
|
// Wait for Start Sketch otherwise you will not have access Text-to-CAD command
|
||||||
await expect(
|
await waitForPageLoad()
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
await openFilePanel()
|
||||||
).toBeEnabled({
|
await openKclCodePanel()
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step(`Test file creation`, async () => {
|
await test.step(`Test file creation`, async () => {
|
||||||
await sendPromptFromCommandBar(page, 'lego 2x4')
|
await sendPromptFromCommandBar(page, prompt)
|
||||||
// File is considered created if it shows up in the Project Files pane
|
// File is considered created if it shows up in the Project Files pane
|
||||||
const file = page.getByRole('button', { name: 'lego-2x4.kcl' })
|
await expect(textToCadFileButton).toBeVisible({ timeout: 20_000 })
|
||||||
await expect(file).toBeVisible({ timeout: 20_000 })
|
|
||||||
expect(fileExists()).toBeTruthy()
|
expect(fileExists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Test file navigation`, async () => {
|
await test.step(`Test file navigation`, async () => {
|
||||||
const file = page.getByRole('button', { name: 'lego-2x4.kcl' })
|
await expect(projectMenuButton).toContainText('main.kcl')
|
||||||
await file.click()
|
await textToCadFileButton.click()
|
||||||
const kclComment = page.getByText('Lego 2x4 Brick')
|
|
||||||
// File can be navigated and loaded assuming a specific KCL comment is loaded into the KCL code pane
|
// File can be navigated and loaded assuming a specific KCL comment is loaded into the KCL code pane
|
||||||
await expect(kclComment).toBeVisible({ timeout: 20_000 })
|
await expect(textToCadComment).toBeVisible({ timeout: 20_000 })
|
||||||
|
await expect(projectMenuButton).toContainText(textToCadFileName)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Test file deletion on rejection`, async () => {
|
await test.step(`Test file deletion on rejection`, async () => {
|
||||||
@ -737,6 +750,8 @@ test(
|
|||||||
)
|
)
|
||||||
await expect(submittingToastMessage).toBeVisible()
|
await expect(submittingToastMessage).toBeVisible()
|
||||||
expect(fileExists()).toBeFalsy()
|
expect(fileExists()).toBeFalsy()
|
||||||
|
// Confirm we've navigated back to the main.kcl file after deletion
|
||||||
|
await expect(projectMenuButton).toContainText('main.kcl')
|
||||||
})
|
})
|
||||||
|
|
||||||
await electronApp.close()
|
await electronApp.close()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||||
use kcl_lib::test_server;
|
use kcl_lib::{settings::types::UnitLength::Mm, test_server};
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
pub fn bench_execute(c: &mut Criterion) {
|
pub fn bench_execute(c: &mut Criterion) {
|
||||||
@ -13,26 +13,42 @@ pub fn bench_execute(c: &mut Criterion) {
|
|||||||
// Configure Criterion.rs to detect smaller differences and increase sample size to improve
|
// Configure Criterion.rs to detect smaller differences and increase sample size to improve
|
||||||
// precision and counteract the resulting noise.
|
// precision and counteract the resulting noise.
|
||||||
group.sample_size(10);
|
group.sample_size(10);
|
||||||
group.bench_with_input(BenchmarkId::new("execute_", name), &code, |b, &s| {
|
group.bench_with_input(BenchmarkId::new("execute", name), &code, |b, &s| {
|
||||||
let rt = Runtime::new().unwrap();
|
let rt = Runtime::new().unwrap();
|
||||||
|
|
||||||
// Spawn a future onto the runtime
|
// Spawn a future onto the runtime
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
rt.block_on(test_server::execute_and_snapshot(
|
rt.block_on(test_server::execute_and_snapshot(s, Mm)).unwrap();
|
||||||
s,
|
|
||||||
kcl_lib::settings::types::UnitLength::Mm,
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
group.finish();
|
group.finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
criterion_group!(benches, bench_execute);
|
pub fn bench_lego(c: &mut Criterion) {
|
||||||
|
let mut group = c.benchmark_group("executor_lego_pattern");
|
||||||
|
// Configure Criterion.rs to detect smaller differences and increase sample size to improve
|
||||||
|
// precision and counteract the resulting noise.
|
||||||
|
group.sample_size(10);
|
||||||
|
// Create lego bricks with N x 10 bumps, where N is each element of `sizes`.
|
||||||
|
let sizes = vec![1, 2, 4];
|
||||||
|
for size in sizes {
|
||||||
|
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
|
||||||
|
let rt = Runtime::new().unwrap();
|
||||||
|
let code = LEGO_PROGRAM.replace("{{N}}", &size.to_string());
|
||||||
|
// Spawn a future onto the runtime
|
||||||
|
b.iter(|| {
|
||||||
|
rt.block_on(test_server::execute_and_snapshot(&code, Mm)).unwrap();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
group.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(benches, bench_lego, bench_execute);
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
|
|
||||||
const KITT_PROGRAM: &str = include_str!("../../tests/executor/inputs/kittycad_svg.kcl");
|
const KITT_PROGRAM: &str = include_str!("../../tests/executor/inputs/kittycad_svg.kcl");
|
||||||
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
||||||
const SERVER_RACK_HEAVY_PROGRAM: &str = include_str!("../../tests/executor/inputs/server-rack-heavy.kcl");
|
const SERVER_RACK_HEAVY_PROGRAM: &str = include_str!("../../tests/executor/inputs/server-rack-heavy.kcl");
|
||||||
const SERVER_RACK_LITE_PROGRAM: &str = include_str!("../../tests/executor/inputs/server-rack-lite.kcl");
|
const SERVER_RACK_LITE_PROGRAM: &str = include_str!("../../tests/executor/inputs/server-rack-lite.kcl");
|
||||||
|
const LEGO_PROGRAM: &str = include_str!("../../tests/executor/inputs/slow_lego.kcl.tmpl");
|
||||||
|
@ -99,7 +99,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
args.send_modeling_cmd(
|
args.batch_modeling_cmd(
|
||||||
id,
|
id,
|
||||||
kittycad::types::ModelingCmd::Extrude {
|
kittycad::types::ModelingCmd::Extrude {
|
||||||
target: sketch_group.id,
|
target: sketch_group.id,
|
||||||
@ -112,7 +112,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
|
|||||||
// Disable the sketch mode.
|
// Disable the sketch mode.
|
||||||
args.batch_modeling_cmd(uuid::Uuid::new_v4(), kittycad::types::ModelingCmd::SketchModeDisable {})
|
args.batch_modeling_cmd(uuid::Uuid::new_v4(), kittycad::types::ModelingCmd::SketchModeDisable {})
|
||||||
.await?;
|
.await?;
|
||||||
extrude_groups.push(do_post_extrude(sketch_group.clone(), length, id, args.clone()).await?);
|
extrude_groups.push(do_post_extrude(sketch_group.clone(), length, args.clone()).await?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(extrude_groups.into())
|
Ok(extrude_groups.into())
|
||||||
@ -121,7 +121,6 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
|
|||||||
pub(crate) async fn do_post_extrude(
|
pub(crate) async fn do_post_extrude(
|
||||||
sketch_group: SketchGroup,
|
sketch_group: SketchGroup,
|
||||||
length: f64,
|
length: f64,
|
||||||
id: Uuid,
|
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||||
// Bring the object to the front of the scene.
|
// Bring the object to the front of the scene.
|
||||||
@ -165,7 +164,7 @@ pub(crate) async fn do_post_extrude(
|
|||||||
|
|
||||||
let solid3d_info = args
|
let solid3d_info = args
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
id,
|
uuid::Uuid::new_v4(),
|
||||||
kittycad::types::ModelingCmd::Solid3DGetExtrusionFaceInfo {
|
kittycad::types::ModelingCmd::Solid3DGetExtrusionFaceInfo {
|
||||||
edge_id,
|
edge_id,
|
||||||
object_id: sketch_group.id,
|
object_id: sketch_group.id,
|
||||||
|
@ -170,5 +170,5 @@ async fn inner_loft(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Using the first sketch as the base curve, idk we might want to change this later.
|
// Using the first sketch as the base curve, idk we might want to change this later.
|
||||||
do_post_extrude(sketch_groups[0].clone(), 0.0, id, args).await
|
do_post_extrude(sketch_groups[0].clone(), 0.0, args).await
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ async fn inner_revolve(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_post_extrude(sketch_group, 0.0, id, args).await
|
do_post_extrude(sketch_group, 0.0, args).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
81
src/wasm-lib/tests/executor/inputs/slow_lego.kcl.tmpl
Normal file
81
src/wasm-lib/tests/executor/inputs/slow_lego.kcl.tmpl
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// 2x8 Lego Brick
|
||||||
|
// A standard Lego brick with 2 bumps wide and 8 bumps long.
|
||||||
|
// Define constants
|
||||||
|
const lbumps = 10 // number of bumps long
|
||||||
|
const wbumps = {{N}} // number of bumps wide
|
||||||
|
const pitch = 8.0
|
||||||
|
const clearance = 0.1
|
||||||
|
const bumpDiam = 4.8
|
||||||
|
const bumpHeight = 1.8
|
||||||
|
const height = 9.6
|
||||||
|
const t = (pitch - (2 * clearance) - bumpDiam) / 2.0
|
||||||
|
const totalLength = lbumps * pitch - (2.0 * clearance)
|
||||||
|
const totalWidth = wbumps * pitch - (2.0 * clearance)
|
||||||
|
// Create the plane for the pegs. This is a hack so that the pegs can be patterned along the face of the lego base.
|
||||||
|
const pegFace = {
|
||||||
|
plane: {
|
||||||
|
origin: { x: 0, y: 0, z: height },
|
||||||
|
xAxis: { x: 1, y: 0, z: 0 },
|
||||||
|
yAxis: { x: 0, y: 1, z: 0 },
|
||||||
|
zAxis: { x: 0, y: 0, z: 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create the plane for the tubes underneath the lego. This is a hack so that the tubes can be patterned underneath the lego.
|
||||||
|
const tubeFace = {
|
||||||
|
plane: {
|
||||||
|
origin: { x: 0, y: 0, z: height - t },
|
||||||
|
xAxis: { x: 1, y: 0, z: 0 },
|
||||||
|
yAxis: { x: 0, y: 1, z: 0 },
|
||||||
|
zAxis: { x: 0, y: 0, z: 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Make the base
|
||||||
|
const s = startSketchOn('XY')
|
||||||
|
|> startProfileAt([-totalWidth / 2, -totalLength / 2], %)
|
||||||
|
|> line([totalWidth, 0], %)
|
||||||
|
|> line([0, totalLength], %)
|
||||||
|
|> line([-totalWidth, 0], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(height, %)
|
||||||
|
|
||||||
|
// Sketch and extrude a rectangular shape to create the shell underneath the lego. This is a hack until we have a shell function.
|
||||||
|
const shellExtrude = startSketchOn(s, "start")
|
||||||
|
|> startProfileAt([
|
||||||
|
-(totalWidth / 2 - t),
|
||||||
|
-(totalLength / 2 - t)
|
||||||
|
], %)
|
||||||
|
|> line([totalWidth - (2 * t), 0], %)
|
||||||
|
|> line([0, totalLength - (2 * t)], %)
|
||||||
|
|> line([-(totalWidth - (2 * t)), 0], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(-(height - t), %)
|
||||||
|
|
||||||
|
fn tr = (i) => {
|
||||||
|
let j = i + 1
|
||||||
|
let x = (j/wbumps) * pitch
|
||||||
|
let y = (j % wbumps) * pitch
|
||||||
|
return {
|
||||||
|
translate: [x, y, 0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the pegs on the top of the base
|
||||||
|
const totalBumps = (wbumps * lbumps)-1
|
||||||
|
const peg = startSketchOn(s, 'end')
|
||||||
|
|> circle([
|
||||||
|
-(pitch*(wbumps-1)/2),
|
||||||
|
-(pitch*(lbumps-1)/2)
|
||||||
|
], bumpDiam / 2, %)
|
||||||
|
|> patternLinear2d({
|
||||||
|
axis: [1, 0],
|
||||||
|
repetitions: wbumps-1,
|
||||||
|
distance: pitch
|
||||||
|
}, %)
|
||||||
|
|> patternLinear2d({
|
||||||
|
axis: [0, 1],
|
||||||
|
repetitions: lbumps-1,
|
||||||
|
distance: pitch
|
||||||
|
}, %)
|
||||||
|
|> extrude(bumpHeight, %)
|
||||||
|
// |> patternTransform(int(totalBumps-1), tr, %)
|
||||||
|
|
Reference in New Issue
Block a user