2025-04-01 23:54:26 -07:00
|
|
|
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
|
|
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
|
|
|
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
2025-03-20 23:52:30 -04:00
|
|
|
import {
|
|
|
|
getUtils,
|
2025-04-15 05:43:39 -04:00
|
|
|
headerMasks,
|
2025-05-09 06:04:45 -07:00
|
|
|
lowerRightMasks,
|
2025-04-01 23:54:26 -07:00
|
|
|
settingsToToml,
|
|
|
|
} from '@e2e/playwright/test-utils'
|
|
|
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
2025-05-14 19:37:14 -07:00
|
|
|
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
|
2023-11-24 08:59:24 +11:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
test.beforeEach(async ({ page, context }) => {
|
2024-04-16 14:29:33 -04:00
|
|
|
// Make the user avatar image always 404
|
|
|
|
// so we see the fallback menu icon for all snapshot tests
|
|
|
|
await page.route('https://lh3.googleusercontent.com/**', async (route) => {
|
|
|
|
await route.fulfill({
|
|
|
|
status: 404,
|
|
|
|
contentType: 'text/plain',
|
|
|
|
body: 'Not Found!',
|
|
|
|
})
|
|
|
|
})
|
2024-04-02 10:29:34 -04:00
|
|
|
})
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
// Help engine-manager: tear shit down.
|
|
|
|
test.afterEach(async ({ page }) => {
|
|
|
|
await page.evaluate(() => {
|
2025-03-13 10:54:00 -04:00
|
|
|
window.engineCommandManager.tearDown()
|
2025-03-05 14:09:21 -05:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2024-03-05 11:52:43 +11:00
|
|
|
test.setTimeout(60_000)
|
2023-11-24 08:59:24 +11:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
const extrudeDefaultPlane = async (
|
|
|
|
context: any,
|
|
|
|
page: any,
|
|
|
|
cmdBar: CmdBarFixture,
|
|
|
|
scene: SceneFixture,
|
|
|
|
plane: string
|
|
|
|
) => {
|
2025-03-21 22:39:12 +13:00
|
|
|
const code = `part001 = startSketchOn(${plane})
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [7.00, 4.40])
|
2025-03-05 14:09:21 -05:00
|
|
|
|> line(end = [6.60, -0.20])
|
|
|
|
|> line(end = [2.80, 5.00])
|
|
|
|
|> line(end = [-5.60, 4.40])
|
|
|
|
|> line(end = [-5.40, -3.80])
|
|
|
|
|> close()
|
|
|
|
|> extrude(length = 10.00)
|
|
|
|
`
|
|
|
|
|
|
|
|
// This probably does absolutely nothing based on my trip through here.
|
|
|
|
await page.addInitScript(async () => {
|
2024-04-03 13:22:56 +11:00
|
|
|
localStorage.setItem(
|
|
|
|
'SETTINGS_PERSIST_KEY',
|
2025-03-05 18:03:49 -08:00
|
|
|
settingsToToml({
|
|
|
|
settings: {
|
|
|
|
modeling: {
|
|
|
|
base_unit: 'in',
|
|
|
|
mouse_controls: 'zoo',
|
|
|
|
},
|
|
|
|
app: {
|
|
|
|
onboarding_status: 'dismissed',
|
|
|
|
show_debug_panel: true,
|
2025-04-01 20:39:55 -07:00
|
|
|
appearance: {
|
|
|
|
theme: 'dark',
|
|
|
|
},
|
2025-03-05 18:03:49 -08:00
|
|
|
},
|
|
|
|
project: {
|
2025-04-03 14:38:52 -04:00
|
|
|
default_project_name: 'untitled',
|
2025-03-05 18:03:49 -08:00
|
|
|
},
|
|
|
|
text_editor: {
|
|
|
|
text_wrapping: true,
|
|
|
|
},
|
|
|
|
},
|
2024-04-03 13:22:56 +11:00
|
|
|
})
|
|
|
|
)
|
|
|
|
})
|
2024-04-17 20:18:07 -07:00
|
|
|
|
|
|
|
await page.addInitScript(async (code: string) => {
|
2024-02-17 12:19:46 +11:00
|
|
|
localStorage.setItem('persistCode', code)
|
2025-03-05 14:09:21 -05:00
|
|
|
}, code)
|
2024-04-17 20:18:07 -07:00
|
|
|
|
2024-05-23 02:20:40 -07:00
|
|
|
const u = await getUtils(page)
|
2024-02-17 12:19:46 +11:00
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
2024-06-29 18:10:07 -07:00
|
|
|
|
2024-02-17 12:19:46 +11:00
|
|
|
await u.waitForAuthSkipAppStart()
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
2024-02-17 12:19:46 +11:00
|
|
|
|
2024-04-17 20:18:07 -07:00
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-04-17 20:18:07 -07:00
|
|
|
})
|
|
|
|
await u.openKclCodePanel()
|
|
|
|
}
|
2024-04-18 15:16:08 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
test.describe(
|
|
|
|
'extrude on default planes should be stable',
|
|
|
|
{ tag: '@snapshot' },
|
|
|
|
() => {
|
2025-03-05 14:09:21 -05:00
|
|
|
test('XY', async ({ page, context, cmdBar, scene }) => {
|
|
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, 'XY')
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
2024-04-19 11:56:21 -04:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
test('XZ', async ({ page, context, cmdBar, scene }) => {
|
|
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, 'XZ')
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
2024-04-19 11:56:21 -04:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
test('YZ', async ({ page, context, cmdBar, scene }) => {
|
|
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, 'YZ')
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
2024-04-19 11:56:21 -04:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
test('-XY', async ({ page, context, cmdBar, scene }) => {
|
|
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, '-XY')
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
2024-04-19 11:56:21 -04:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
test('-XZ', async ({ page, context, cmdBar, scene }) => {
|
|
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, '-XZ')
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
2024-04-19 11:56:21 -04:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
test('-YZ', async ({ page, context, cmdBar, scene }) => {
|
|
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, '-YZ')
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
2024-04-19 11:56:21 -04:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
test(
|
|
|
|
'Draft segments should look right',
|
|
|
|
{ tag: '@snapshot' },
|
2025-03-18 11:14:12 +11:00
|
|
|
async ({ page, scene, toolbar }) => {
|
2024-05-23 02:20:40 -07:00
|
|
|
const u = await getUtils(page)
|
2024-04-11 13:37:49 -04:00
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
|
|
|
await u.waitForAuthSkipAppStart()
|
2024-08-05 21:30:16 +10:00
|
|
|
|
2025-03-18 11:14:12 +11:00
|
|
|
const startXPx = 600
|
|
|
|
const [endOfTangentClk, endOfTangentMv] = scene.makeMouseHelpers(
|
|
|
|
startXPx + PUR * 30,
|
|
|
|
500 - PUR * 20,
|
|
|
|
{ steps: 10 }
|
|
|
|
)
|
|
|
|
const [threePointArcMidPointClk, threePointArcMidPointMv] =
|
|
|
|
scene.makeMouseHelpers(800, 250, { steps: 10 })
|
|
|
|
const [threePointArcEndPointClk, threePointArcEndPointMv] =
|
|
|
|
scene.makeMouseHelpers(750, 285, { steps: 10 })
|
|
|
|
const [arcCenterClk, arcCenterMv] = scene.makeMouseHelpers(750, 210, {
|
|
|
|
steps: 10,
|
|
|
|
})
|
|
|
|
const [arcEndClk, arcEndMv] = scene.makeMouseHelpers(750, 150, {
|
|
|
|
steps: 10,
|
|
|
|
})
|
|
|
|
|
2024-04-11 13:37:49 -04:00
|
|
|
// click on "Start Sketch" button
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
|
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
|
|
|
200
|
|
|
|
)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-04-11 13:37:49 -04:00
|
|
|
// select a plane
|
|
|
|
await page.mouse.click(700, 200)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2025-03-21 22:39:12 +13:00
|
|
|
let code = `sketch001 = startSketchOn(XZ)`
|
2024-06-18 16:08:41 +10:00
|
|
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.waitForTimeout(700) // TODO detect animation ending, or disable animation
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-04-11 13:37:49 -04:00
|
|
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
2025-04-25 16:01:35 -05:00
|
|
|
code += `profile001 = startProfile(sketch001, at = [182.59, -246.32])`
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
2024-04-11 13:37:49 -04:00
|
|
|
await page.waitForTimeout(100)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.mouse.move(startXPx + PUR * 20, 500 - PUR * 10)
|
2025-03-05 14:09:21 -05:00
|
|
|
|
|
|
|
await page.waitForTimeout(500)
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2025-02-15 00:57:04 +11:00
|
|
|
const lineEndClick = () =>
|
|
|
|
page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
|
|
|
await lineEndClick()
|
2025-03-05 14:09:21 -05:00
|
|
|
await page.waitForTimeout(500)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-06-18 16:08:41 +10:00
|
|
|
code += `
|
2025-04-03 07:31:18 +11:00
|
|
|
|> xLine(length = 184.3)`
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2025-04-25 06:40:33 +10:00
|
|
|
await toolbar.selectTangentialArc()
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2025-02-15 00:57:04 +11:00
|
|
|
// click on the end of the profile to continue it
|
2025-03-05 14:09:21 -05:00
|
|
|
await page.waitForTimeout(500)
|
2025-02-15 00:57:04 +11:00
|
|
|
await lineEndClick()
|
2025-03-05 14:09:21 -05:00
|
|
|
await page.waitForTimeout(500)
|
2025-02-15 00:57:04 +11:00
|
|
|
|
|
|
|
// click to continue profile
|
|
|
|
await page.mouse.move(813, 392, { steps: 10 })
|
2025-03-05 14:09:21 -05:00
|
|
|
await page.waitForTimeout(500)
|
2025-02-15 00:57:04 +11:00
|
|
|
|
2025-03-18 11:14:12 +11:00
|
|
|
await endOfTangentMv()
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-04-11 13:37:49 -04:00
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-04-11 13:37:49 -04:00
|
|
|
})
|
2025-03-18 11:14:12 +11:00
|
|
|
await endOfTangentClk()
|
|
|
|
|
|
|
|
await toolbar.selectThreePointArc()
|
|
|
|
await page.waitForTimeout(500)
|
|
|
|
await endOfTangentClk()
|
|
|
|
await threePointArcMidPointMv()
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2025-03-18 11:14:12 +11:00
|
|
|
})
|
|
|
|
await threePointArcMidPointClk()
|
|
|
|
await page.waitForTimeout(100)
|
|
|
|
|
|
|
|
await threePointArcEndPointMv()
|
|
|
|
await page.waitForTimeout(500)
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2025-03-18 11:14:12 +11:00
|
|
|
})
|
|
|
|
|
|
|
|
await threePointArcEndPointClk()
|
|
|
|
await page.waitForTimeout(100)
|
|
|
|
|
|
|
|
await toolbar.selectArc()
|
|
|
|
await page.waitForTimeout(100)
|
|
|
|
|
|
|
|
// continue the profile
|
|
|
|
await threePointArcEndPointClk()
|
|
|
|
await page.waitForTimeout(100)
|
|
|
|
await arcCenterMv()
|
|
|
|
await page.waitForTimeout(500)
|
|
|
|
await arcCenterClk()
|
|
|
|
|
|
|
|
await arcEndMv()
|
|
|
|
await page.waitForTimeout(500)
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2025-03-18 11:14:12 +11:00
|
|
|
})
|
|
|
|
await arcEndClk()
|
2024-08-05 21:30:16 +10:00
|
|
|
}
|
|
|
|
)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
test(
|
|
|
|
'Draft rectangles should look right',
|
|
|
|
{ tag: '@snapshot' },
|
2025-03-05 14:09:21 -05:00
|
|
|
async ({ page, context, cmdBar, scene }) => {
|
2024-05-23 02:20:40 -07:00
|
|
|
const u = await getUtils(page)
|
2024-04-02 10:29:34 -04:00
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
2024-06-29 18:10:07 -07:00
|
|
|
|
2024-04-02 10:29:34 -04:00
|
|
|
await u.waitForAuthSkipAppStart()
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-04-02 10:29:34 -04:00
|
|
|
// click on "Start Sketch" button
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
|
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
|
|
|
200
|
|
|
|
)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-04-02 10:29:34 -04:00
|
|
|
// select a plane
|
|
|
|
await page.mouse.click(700, 200)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(page.locator('.cm-content')).toHaveText(
|
2025-03-21 22:39:12 +13:00
|
|
|
`sketch001 = startSketchOn(XZ)`
|
2024-08-05 21:30:16 +10:00
|
|
|
)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
// Wait for camera animation
|
|
|
|
await page.waitForTimeout(2000)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-04-02 10:29:34 -04:00
|
|
|
const startXPx = 600
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
// Equip the rectangle tool
|
|
|
|
await page
|
2024-08-16 07:15:42 -04:00
|
|
|
.getByRole('button', { name: 'rectangle Corner rectangle', exact: true })
|
2024-08-05 21:30:16 +10:00
|
|
|
.click()
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
// Draw the rectangle
|
|
|
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 30)
|
|
|
|
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 10, { steps: 5 })
|
2024-10-18 04:31:00 -04:00
|
|
|
await page.waitForTimeout(800)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
// Ensure the draft rectangle looks the same as it usually does
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
2024-09-23 22:42:51 +10:00
|
|
|
test(
|
|
|
|
'Draft circle should look right',
|
|
|
|
{ tag: '@snapshot' },
|
2025-03-05 14:09:21 -05:00
|
|
|
async ({ page, context, cmdBar, scene }) => {
|
2024-09-23 22:42:51 +10:00
|
|
|
const u = await getUtils(page)
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
|
|
|
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
|
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
|
|
|
200
|
|
|
|
)
|
|
|
|
|
|
|
|
// select a plane
|
|
|
|
await page.mouse.click(700, 200)
|
|
|
|
|
|
|
|
await expect(page.locator('.cm-content')).toHaveText(
|
2025-03-21 22:39:12 +13:00
|
|
|
`sketch001 = startSketchOn(XZ)`
|
2024-09-23 22:42:51 +10:00
|
|
|
)
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
// Wait for camera animation
|
|
|
|
await page.waitForTimeout(2000)
|
2024-09-23 22:42:51 +10:00
|
|
|
|
|
|
|
const startXPx = 600
|
|
|
|
|
|
|
|
// Equip the rectangle tool
|
|
|
|
// await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
|
|
|
await page.getByTestId('circle-center').click()
|
|
|
|
|
|
|
|
// Draw the rectangle
|
|
|
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
|
|
|
|
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 10, { steps: 5 })
|
|
|
|
|
|
|
|
// Ensure the draft rectangle looks the same as it usually does
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-09-23 22:42:51 +10:00
|
|
|
})
|
|
|
|
await expect(page.locator('.cm-content')).toHaveText(
|
2025-04-03 07:31:18 +11:00
|
|
|
`sketch001 = startSketchOn(XZ)profile001 = circle(sketch001, center = [366.89, -62.01], radius = 1)`
|
2024-09-23 22:42:51 +10:00
|
|
|
)
|
|
|
|
}
|
|
|
|
)
|
2024-08-05 21:30:16 +10:00
|
|
|
|
|
|
|
test.describe(
|
|
|
|
'Client side scene scale should match engine scale',
|
|
|
|
{ tag: '@snapshot' },
|
|
|
|
() => {
|
2025-04-25 06:40:33 +10:00
|
|
|
test('Inch scale', async ({ page, cmdBar, scene, toolbar }) => {
|
2024-08-05 21:30:16 +10:00
|
|
|
const u = await getUtils(page)
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
|
|
|
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
|
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
|
|
|
200
|
|
|
|
)
|
|
|
|
|
|
|
|
// select a plane
|
|
|
|
await page.mouse.click(700, 200)
|
|
|
|
|
2025-03-21 22:39:12 +13:00
|
|
|
let code = `sketch001 = startSketchOn(XZ)`
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
// Wait for camera animation
|
|
|
|
await page.waitForTimeout(2000)
|
2024-08-05 21:30:16 +10:00
|
|
|
|
|
|
|
const startXPx = 600
|
|
|
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
2025-04-25 16:01:35 -05:00
|
|
|
code += `profile001 = startProfile(sketch001, at = [182.59, -246.32])`
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
await page.waitForTimeout(100)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
|
|
|
await page.waitForTimeout(100)
|
2024-03-02 08:20:50 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
code += `
|
2025-04-03 07:31:18 +11:00
|
|
|
|> xLine(length = 184.3)`
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(u.codeLocator).toHaveText(code)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2025-04-25 06:40:33 +10:00
|
|
|
await toolbar.selectTangentialArc()
|
2025-05-30 14:44:31 +02:00
|
|
|
await page.waitForTimeout(200)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2025-02-15 00:57:04 +11:00
|
|
|
// click to continue profile
|
|
|
|
await page.mouse.click(813, 392)
|
2025-05-30 14:44:31 +02:00
|
|
|
await page.waitForTimeout(300)
|
2025-02-15 00:57:04 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
|
|
|
|
|
|
|
code += `
|
2025-05-30 14:44:31 +02:00
|
|
|
|> tangentialArc(end = [184.31, 184.31])`
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
|
|
|
|
// click tangential arc tool again to unequip it
|
2025-04-25 06:40:33 +10:00
|
|
|
// it will be available directly in the toolbar since it was last equipped
|
|
|
|
await toolbar.tangentialArcBtn.click()
|
2025-05-30 14:44:31 +02:00
|
|
|
await page.waitForTimeout(1000)
|
2024-08-05 21:30:16 +10:00
|
|
|
|
|
|
|
// screen shot should show the sketch
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
|
|
|
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
|
|
() => page.getByRole('button', { name: 'Exit Sketch' }).click(),
|
|
|
|
200
|
|
|
|
)
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
2024-08-05 21:30:16 +10:00
|
|
|
|
|
|
|
// second screen shot should look almost identical, i.e. scale should be the same.
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
2024-04-02 10:29:34 -04:00
|
|
|
})
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2025-04-25 06:40:33 +10:00
|
|
|
test('Millimeter scale', async ({
|
|
|
|
page,
|
|
|
|
context,
|
|
|
|
cmdBar,
|
|
|
|
scene,
|
|
|
|
toolbar,
|
|
|
|
}) => {
|
2025-03-05 14:09:21 -05:00
|
|
|
await context.addInitScript(
|
2024-08-05 21:30:16 +10:00
|
|
|
async ({ settingsKey, settings }) => {
|
|
|
|
localStorage.setItem(settingsKey, settings)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
settingsKey: TEST_SETTINGS_KEY,
|
2025-03-05 18:03:49 -08:00
|
|
|
settings: settingsToToml({
|
2024-08-05 21:30:16 +10:00
|
|
|
settings: {
|
|
|
|
...TEST_SETTINGS,
|
|
|
|
modeling: {
|
|
|
|
...TEST_SETTINGS.modeling,
|
2025-03-05 18:03:49 -08:00
|
|
|
base_unit: 'mm',
|
2024-08-05 21:30:16 +10:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
const u = await getUtils(page)
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
|
|
|
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
2024-08-05 21:30:16 +10:00
|
|
|
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
|
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
|
|
|
200
|
|
|
|
)
|
|
|
|
|
|
|
|
// select a plane
|
|
|
|
await page.mouse.click(700, 200)
|
|
|
|
|
2025-03-21 22:39:12 +13:00
|
|
|
let code = `sketch001 = startSketchOn(XZ)`
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
// Wait for camera animation
|
|
|
|
await page.waitForTimeout(2000)
|
2024-08-05 21:30:16 +10:00
|
|
|
|
|
|
|
const startXPx = 600
|
|
|
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
2025-04-25 16:01:35 -05:00
|
|
|
code += `profile001 = startProfile(sketch001, at = [182.59, -246.32])`
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
await page.waitForTimeout(100)
|
2024-03-01 06:55:49 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
|
|
|
await page.waitForTimeout(100)
|
|
|
|
|
|
|
|
code += `
|
2025-03-07 22:07:16 -06:00
|
|
|
|> xLine(length = 184.3)`
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
|
2025-04-25 06:40:33 +10:00
|
|
|
await toolbar.selectTangentialArc()
|
2025-05-30 14:44:31 +02:00
|
|
|
await page.waitForTimeout(200)
|
2024-08-05 21:30:16 +10:00
|
|
|
|
2025-02-15 00:57:04 +11:00
|
|
|
// click to continue profile
|
|
|
|
await page.mouse.click(813, 392)
|
2025-05-30 14:44:31 +02:00
|
|
|
await page.waitForTimeout(300)
|
2025-02-15 00:57:04 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
|
|
|
|
|
|
|
code += `
|
2025-05-30 14:44:31 +02:00
|
|
|
|> tangentialArc(end = [184.31, 184.31])`
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
|
2025-04-25 06:40:33 +10:00
|
|
|
await toolbar.tangentialArcBtn.click()
|
2025-05-30 14:44:31 +02:00
|
|
|
await page.waitForTimeout(1000)
|
2024-08-05 21:30:16 +10:00
|
|
|
|
|
|
|
// screen shot should show the sketch
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
|
|
|
|
|
|
|
// exit sketch
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
|
|
() => page.getByRole('button', { name: 'Exit Sketch' }).click(),
|
|
|
|
200
|
|
|
|
)
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
2024-08-05 21:30:16 +10:00
|
|
|
|
|
|
|
// second screen shot should look almost identical, i.e. scale should be the same.
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
2024-04-02 10:29:34 -04:00
|
|
|
})
|
2024-08-05 21:30:16 +10:00
|
|
|
}
|
|
|
|
)
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
test(
|
|
|
|
'Sketch on face with none z-up',
|
|
|
|
{ tag: '@snapshot' },
|
2025-03-05 14:09:21 -05:00
|
|
|
async ({ page, context, cmdBar, scene }) => {
|
2024-08-05 21:30:16 +10:00
|
|
|
const u = await getUtils(page)
|
|
|
|
await context.addInitScript(async (KCL_DEFAULT_LENGTH) => {
|
|
|
|
localStorage.setItem(
|
|
|
|
'persistCode',
|
2025-03-21 22:39:12 +13:00
|
|
|
`part001 = startSketchOn(-XZ)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [1.4, 2.47])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [9.31, 10.55], tag = $seg01)
|
|
|
|
|> line(end = [11.91, -10.42])
|
|
|
|
|> close()
|
|
|
|
|> extrude(length = ${KCL_DEFAULT_LENGTH})
|
2025-04-14 05:58:19 -04:00
|
|
|
part002 = startSketchOn(part001, face = seg01)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [8, 8])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [4.68, 3.05])
|
|
|
|
|> line(end = [0, -7.79])
|
|
|
|
|> close()
|
|
|
|
|> extrude(length = ${KCL_DEFAULT_LENGTH})
|
2024-03-22 10:23:04 +11:00
|
|
|
`
|
2024-08-05 21:30:16 +10:00
|
|
|
)
|
|
|
|
}, KCL_DEFAULT_LENGTH)
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
2024-06-29 18:10:07 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await u.waitForAuthSkipAppStart()
|
2024-04-16 12:31:50 -04:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
2024-04-16 12:31:50 -04:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
// Wait for the second extrusion to appear
|
|
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
|
|
// rendering, because an execution-done message is not sufficient.
|
|
|
|
await page.waitForTimeout(1000)
|
2024-04-16 12:31:50 -04:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(
|
|
|
|
page.getByRole('button', { name: 'Start Sketch' })
|
|
|
|
).not.toBeDisabled()
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
|
|
|
let previousCodeContent = await page.locator('.cm-content').innerText()
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
// click at 641, 135
|
|
|
|
await page.mouse.click(641, 135)
|
|
|
|
await expect(page.locator('.cm-content')).not.toHaveText(
|
|
|
|
previousCodeContent
|
|
|
|
)
|
|
|
|
previousCodeContent = await page.locator('.cm-content').innerText()
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.waitForTimeout(300)
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
2024-05-23 17:05:54 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
test(
|
|
|
|
'Zoom to fit on load - solid 2d',
|
|
|
|
{ tag: '@snapshot' },
|
2025-03-05 14:09:21 -05:00
|
|
|
async ({ page, context, cmdBar, scene }) => {
|
2024-08-05 21:30:16 +10:00
|
|
|
const u = await getUtils(page)
|
|
|
|
await context.addInitScript(async () => {
|
|
|
|
localStorage.setItem(
|
|
|
|
'persistCode',
|
2025-03-21 22:39:12 +13:00
|
|
|
`part001 = startSketchOn(XY)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [-10, -10])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [20, 0])
|
|
|
|
|> line(end = [0, 20])
|
|
|
|
|> line(end = [-20, 0])
|
|
|
|
|> close()
|
2024-05-23 17:05:54 -07:00
|
|
|
`
|
2024-08-05 21:30:16 +10:00
|
|
|
)
|
|
|
|
}, KCL_DEFAULT_LENGTH)
|
2024-05-23 17:05:54 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
2024-06-29 18:10:07 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await u.waitForAuthSkipAppStart()
|
2024-05-23 17:05:54 -07:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
2024-05-23 17:05:54 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
// Wait for the second extrusion to appear
|
|
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
|
|
// rendering, because an execution-done message is not sufficient.
|
2024-10-18 04:31:00 -04:00
|
|
|
await page.waitForTimeout(2000)
|
2024-05-23 17:05:54 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
2024-05-23 17:05:54 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
test(
|
|
|
|
'Zoom to fit on load - solid 3d',
|
|
|
|
{ tag: '@snapshot' },
|
2025-03-05 14:09:21 -05:00
|
|
|
async ({ page, context, cmdBar, scene }) => {
|
2024-08-05 21:30:16 +10:00
|
|
|
const u = await getUtils(page)
|
|
|
|
await context.addInitScript(async () => {
|
|
|
|
localStorage.setItem(
|
|
|
|
'persistCode',
|
2025-03-21 22:39:12 +13:00
|
|
|
`part001 = startSketchOn(XY)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [-10, -10])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [20, 0])
|
|
|
|
|> line(end = [0, 20])
|
|
|
|
|> line(end = [-20, 0])
|
|
|
|
|> close()
|
|
|
|
|> extrude(length = 10)
|
2024-05-23 17:05:54 -07:00
|
|
|
`
|
2024-08-05 21:30:16 +10:00
|
|
|
)
|
|
|
|
}, KCL_DEFAULT_LENGTH)
|
2024-05-23 17:05:54 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
2024-06-29 18:10:07 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await u.waitForAuthSkipAppStart()
|
2024-05-23 17:05:54 -07:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
2024-05-23 17:05:54 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
// Wait for the second extrusion to appear
|
|
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
|
|
// rendering, because an execution-done message is not sufficient.
|
2024-10-18 04:31:00 -04:00
|
|
|
await page.waitForTimeout(2000)
|
2024-05-23 17:05:54 -07:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
await expect(page).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-08-05 21:30:16 +10:00
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
2024-07-01 15:31:42 -04:00
|
|
|
|
2024-08-05 21:30:16 +10:00
|
|
|
test.describe('Grid visibility', { tag: '@snapshot' }, () => {
|
2025-03-05 14:09:21 -05:00
|
|
|
test('Grid turned off to on via command bar', async ({
|
|
|
|
page,
|
|
|
|
cmdBar,
|
|
|
|
scene,
|
|
|
|
}) => {
|
2024-12-10 18:50:22 -08:00
|
|
|
const u = await getUtils(page)
|
|
|
|
const stream = page.getByTestId('stream')
|
|
|
|
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
await page.goto('/')
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
|
|
|
|
2024-12-10 18:50:22 -08:00
|
|
|
await u.closeKclCodePanel()
|
|
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
|
|
// rendering, because an execution-done message is not sufficient.
|
|
|
|
await page.waitForTimeout(1000)
|
|
|
|
|
|
|
|
// Open the command bar.
|
|
|
|
await page
|
|
|
|
.getByRole('button', { name: 'Commands', exact: false })
|
|
|
|
.or(page.getByRole('button', { name: '⌘K' }))
|
|
|
|
.click()
|
|
|
|
const commandName = 'show scale grid'
|
|
|
|
const commandOption = page.getByRole('option', {
|
|
|
|
name: commandName,
|
|
|
|
exact: false,
|
|
|
|
})
|
|
|
|
const cmdSearchBar = page.getByPlaceholder('Search commands')
|
|
|
|
// This selector changes after we set the setting
|
|
|
|
await cmdSearchBar.fill(commandName)
|
|
|
|
await expect(commandOption).toBeVisible()
|
|
|
|
await commandOption.click()
|
|
|
|
|
|
|
|
const toggleInput = page.getByPlaceholder('Off')
|
|
|
|
await expect(toggleInput).toBeVisible()
|
|
|
|
await expect(toggleInput).toBeFocused()
|
|
|
|
|
|
|
|
// Select On
|
|
|
|
await page.keyboard.press('ArrowDown')
|
|
|
|
await expect(page.getByRole('option', { name: 'Off' })).toHaveAttribute(
|
|
|
|
'data-headlessui-state',
|
|
|
|
'active selected'
|
|
|
|
)
|
|
|
|
await page.keyboard.press('ArrowUp')
|
|
|
|
await expect(page.getByRole('option', { name: 'On' })).toHaveAttribute(
|
|
|
|
'data-headlessui-state',
|
|
|
|
'active'
|
|
|
|
)
|
|
|
|
await page.keyboard.press('Enter')
|
|
|
|
|
|
|
|
// Check the toast appeared
|
|
|
|
await expect(
|
|
|
|
page.getByText(`Set show scale grid to "true" as a user default`)
|
|
|
|
).toBeVisible()
|
|
|
|
|
|
|
|
await expect(stream).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: [...headerMasks(page), ...lowerRightMasks(page)],
|
2024-12-10 18:50:22 -08:00
|
|
|
})
|
|
|
|
})
|
2024-08-17 14:15:11 -07:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
test('Grid turned off', async ({ page, cmdBar, scene }) => {
|
2024-07-01 15:31:42 -04:00
|
|
|
const u = await getUtils(page)
|
|
|
|
const stream = page.getByTestId('stream')
|
|
|
|
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
await page.goto('/')
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
|
|
|
|
2024-07-01 15:31:42 -04:00
|
|
|
await u.closeKclCodePanel()
|
|
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
|
|
// rendering, because an execution-done message is not sufficient.
|
|
|
|
await page.waitForTimeout(1000)
|
|
|
|
|
|
|
|
await expect(stream).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: [...headerMasks(page), ...lowerRightMasks(page)],
|
2024-07-01 15:31:42 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
test('Grid turned on', async ({ page, context, cmdBar, scene }) => {
|
|
|
|
await context.addInitScript(
|
2024-07-01 15:31:42 -04:00
|
|
|
async ({ settingsKey, settings }) => {
|
|
|
|
localStorage.setItem(settingsKey, settings)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
settingsKey: TEST_SETTINGS_KEY,
|
2025-03-05 18:03:49 -08:00
|
|
|
settings: settingsToToml({
|
2024-07-01 15:31:42 -04:00
|
|
|
settings: {
|
|
|
|
...TEST_SETTINGS,
|
|
|
|
modeling: {
|
|
|
|
...TEST_SETTINGS.modeling,
|
2025-03-05 18:03:49 -08:00
|
|
|
show_scale_grid: true,
|
2024-07-01 15:31:42 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
const u = await getUtils(page)
|
|
|
|
const stream = page.getByTestId('stream')
|
|
|
|
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
await page.goto('/')
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
|
|
|
|
2024-07-01 15:31:42 -04:00
|
|
|
await u.closeKclCodePanel()
|
|
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
|
|
// rendering, because an execution-done message is not sufficient.
|
|
|
|
await page.waitForTimeout(1000)
|
|
|
|
|
|
|
|
await expect(stream).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: [...headerMasks(page), ...lowerRightMasks(page)],
|
2024-07-01 15:31:42 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2024-08-21 15:02:54 +10:00
|
|
|
|
2025-05-15 11:58:00 -04:00
|
|
|
test('theme persists', async ({ page, context, homePage }) => {
|
2024-08-21 15:02:54 +10:00
|
|
|
const u = await getUtils(page)
|
|
|
|
await context.addInitScript(async () => {
|
|
|
|
localStorage.setItem(
|
|
|
|
'persistCode',
|
2025-03-21 22:39:12 +13:00
|
|
|
`part001 = startSketchOn(XY)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [-10, -10])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [20, 0])
|
|
|
|
|> line(end = [0, 20])
|
|
|
|
|> line(end = [-20, 0])
|
|
|
|
|> close()
|
|
|
|
|> extrude(length = 10)
|
2024-08-21 15:02:54 +10:00
|
|
|
`
|
|
|
|
)
|
|
|
|
}, KCL_DEFAULT_LENGTH)
|
|
|
|
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
|
2025-05-15 11:58:00 -04:00
|
|
|
await homePage.goToModelingScene()
|
2024-08-21 15:02:54 +10:00
|
|
|
await page.waitForTimeout(500)
|
|
|
|
|
|
|
|
// await page.getByRole('link', { name: 'Settings Settings (tooltip)' }).click()
|
|
|
|
await expect(page.getByTestId('settings-link')).toBeVisible()
|
|
|
|
await page.getByTestId('settings-link').click()
|
|
|
|
|
|
|
|
// open user settingns
|
|
|
|
await page.getByRole('radio', { name: 'person User' }).click()
|
|
|
|
|
|
|
|
await page.getByTestId('app-theme').selectOption('light')
|
|
|
|
|
|
|
|
await page.getByTestId('settings-close-button').click()
|
|
|
|
|
2025-06-17 16:29:27 -04:00
|
|
|
const networkToggle = page.getByTestId(/network-toggle/)
|
2024-08-21 15:02:54 +10:00
|
|
|
|
|
|
|
// simulate network down
|
|
|
|
await u.emulateNetworkConditions({
|
|
|
|
offline: true,
|
|
|
|
// values of 0 remove any active throttling. crbug.com/456324#c9
|
|
|
|
latency: 0,
|
|
|
|
downloadThroughput: -1,
|
|
|
|
uploadThroughput: -1,
|
|
|
|
})
|
|
|
|
|
|
|
|
// Disconnect and reconnect to check the theme persists through a reload
|
|
|
|
|
|
|
|
// Expect the network to be down
|
2025-05-15 11:58:00 -04:00
|
|
|
await expect(networkToggle).toContainText('Problem')
|
2024-08-21 15:02:54 +10:00
|
|
|
|
|
|
|
// simulate network up
|
|
|
|
await u.emulateNetworkConditions({
|
|
|
|
offline: false,
|
|
|
|
// values of 0 remove any active throttling. crbug.com/456324#c9
|
|
|
|
latency: 0,
|
|
|
|
downloadThroughput: -1,
|
|
|
|
uploadThroughput: -1,
|
|
|
|
})
|
|
|
|
|
2025-05-30 15:50:05 -04:00
|
|
|
await expect(networkToggle).toContainText('Network health (Strong)')
|
2024-08-21 15:02:54 +10:00
|
|
|
|
|
|
|
await expect(page.getByText('building scene')).not.toBeVisible()
|
|
|
|
|
|
|
|
await expect(page, 'expect screenshot to have light theme').toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-08-21 15:02:54 +10:00
|
|
|
})
|
|
|
|
})
|
2024-12-11 16:45:39 -08:00
|
|
|
|
|
|
|
test.describe('code color goober', { tag: '@snapshot' }, () => {
|
2025-03-05 14:09:21 -05:00
|
|
|
test('code color goober', async ({ page, context, scene, cmdBar }) => {
|
2024-12-11 16:45:39 -08:00
|
|
|
const u = await getUtils(page)
|
|
|
|
await context.addInitScript(async () => {
|
|
|
|
localStorage.setItem(
|
|
|
|
'persistCode',
|
|
|
|
`// Create a pipe using a sweep.
|
|
|
|
|
|
|
|
// Create a path for the sweep.
|
2025-03-21 22:39:12 +13:00
|
|
|
sweepPath = startSketchOn(XZ)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [0.05, 0.05])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [0, 7])
|
2025-04-15 05:43:39 -04:00
|
|
|
|> tangentialArc(angle = 90, radius = 5)
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [-3, 0])
|
2025-04-15 05:43:39 -04:00
|
|
|
|> tangentialArc(angle = -90, radius = 5)
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [0, 7])
|
2024-12-11 16:45:39 -08:00
|
|
|
|
2025-03-21 22:39:12 +13:00
|
|
|
sweepSketch = startSketchOn(XY)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [2, 0])
|
2025-04-18 17:40:44 -05:00
|
|
|
|> arc(angleStart = 0, angleEnd = 360, radius = 2)
|
2025-02-07 13:51:28 -05:00
|
|
|
|> sweep(path = sweepPath)
|
2025-02-07 16:36:51 -06:00
|
|
|
|> appearance(
|
2024-12-11 16:45:39 -08:00
|
|
|
color = "#bb00ff",
|
|
|
|
metalness = 90,
|
|
|
|
roughness = 90
|
2025-02-07 16:36:51 -06:00
|
|
|
)
|
2024-12-11 16:45:39 -08:00
|
|
|
`
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
2024-12-11 16:45:39 -08:00
|
|
|
|
|
|
|
await expect(page, 'expect small color widget').toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-12-11 16:45:39 -08:00
|
|
|
})
|
|
|
|
})
|
2025-05-14 19:37:14 -07:00
|
|
|
test('code color goober works with single quotes', async ({
|
|
|
|
page,
|
|
|
|
context,
|
|
|
|
scene,
|
|
|
|
cmdBar,
|
|
|
|
}) => {
|
|
|
|
const u = await getUtils(page)
|
|
|
|
await context.addInitScript(async () => {
|
|
|
|
localStorage.setItem(
|
|
|
|
'persistCode',
|
|
|
|
`// Create a pipe using a sweep.
|
|
|
|
|
|
|
|
// Create a path for the sweep.
|
|
|
|
sweepPath = startSketchOn(XZ)
|
|
|
|
|> startProfile(at = [0.05, 0.05])
|
|
|
|
|> line(end = [0, 7])
|
|
|
|
|> tangentialArc(angle = 90, radius = 5)
|
|
|
|
|> line(end = [-3, 0])
|
|
|
|
|> tangentialArc(angle = -90, radius = 5)
|
|
|
|
|> line(end = [0, 7])
|
|
|
|
|
|
|
|
sweepSketch = startSketchOn(XY)
|
|
|
|
|> startProfile(at = [2, 0])
|
|
|
|
|> arc(angleStart = 0, angleEnd = 360, radius = 2)
|
|
|
|
|> sweep(path = sweepPath)
|
|
|
|
|> appearance(
|
|
|
|
color = '#bb00ff',
|
|
|
|
metalness = 90,
|
|
|
|
roughness = 90
|
|
|
|
)
|
|
|
|
`
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
|
|
|
|
await expect(page, 'expect small color widget').toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
|
|
|
mask: lowerRightMasks(page),
|
|
|
|
})
|
|
|
|
})
|
2024-12-11 16:45:39 -08:00
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
test('code color goober opening window', async ({
|
|
|
|
page,
|
|
|
|
context,
|
|
|
|
scene,
|
|
|
|
cmdBar,
|
|
|
|
}) => {
|
2024-12-11 16:45:39 -08:00
|
|
|
const u = await getUtils(page)
|
|
|
|
await context.addInitScript(async () => {
|
|
|
|
localStorage.setItem(
|
|
|
|
'persistCode',
|
|
|
|
`// Create a pipe using a sweep.
|
|
|
|
|
|
|
|
// Create a path for the sweep.
|
2025-03-21 22:39:12 +13:00
|
|
|
sweepPath = startSketchOn(XZ)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [0.05, 0.05])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [0, 7])
|
2025-04-15 05:43:39 -04:00
|
|
|
|> tangentialArc(angle = 90, radius = 5)
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [-3, 0])
|
2025-04-15 05:43:39 -04:00
|
|
|
|> tangentialArc(angle = -90, radius = 5)
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [0, 7])
|
2024-12-11 16:45:39 -08:00
|
|
|
|
2025-03-21 22:39:12 +13:00
|
|
|
sweepSketch = startSketchOn(XY)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [2, 0])
|
2025-04-18 17:40:44 -05:00
|
|
|
|> arc(angleStart = 0, angleEnd = 360, radius = 2)
|
2025-02-07 13:51:28 -05:00
|
|
|
|> sweep(path = sweepPath)
|
2025-02-07 16:36:51 -06:00
|
|
|
|> appearance(
|
2024-12-11 16:45:39 -08:00
|
|
|
color = "#bb00ff",
|
|
|
|
metalness = 90,
|
|
|
|
roughness = 90
|
2025-02-07 16:36:51 -06:00
|
|
|
)
|
2024-12-11 16:45:39 -08:00
|
|
|
`
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
|
2025-03-05 14:09:21 -05:00
|
|
|
await scene.settled(cmdBar)
|
2024-12-11 16:45:39 -08:00
|
|
|
|
|
|
|
await expect(page.locator('.cm-css-color-picker-wrapper')).toBeVisible()
|
|
|
|
|
|
|
|
// Click the color widget
|
|
|
|
await page.locator('.cm-css-color-picker-wrapper input').click()
|
|
|
|
|
|
|
|
await expect(
|
|
|
|
page,
|
|
|
|
'expect small color widget to have window open'
|
|
|
|
).toHaveScreenshot({
|
|
|
|
maxDiffPixels: 100,
|
2025-05-09 06:04:45 -07:00
|
|
|
mask: lowerRightMasks(page),
|
2024-12-11 16:45:39 -08:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|