Compare commits
47 Commits
nadro/brok
...
jtran/plus
Author | SHA1 | Date | |
---|---|---|---|
4de0b57ea4 | |||
fba62dab98 | |||
a85a534d6b | |||
6ddbb7a31d | |||
051bb0589e | |||
7f9851ae28 | |||
fbcbb341e2 | |||
4a080d1583 | |||
85c721fb49 | |||
27af2d08a3 | |||
fb8b975b5e | |||
62d8d45a58 | |||
ae3440df0a | |||
af658c909d | |||
7ec11d23c8 | |||
30000a1eac | |||
cb3b45747c | |||
fe66310f2d | |||
fefb6cfe87 | |||
0f8375cbb4 | |||
107adc77b3 | |||
4356885aa2 | |||
6a2027cd51 | |||
f49cf8281c | |||
7de27c648f | |||
344fb6f84d | |||
df808b3e58 | |||
e1ab6bbc48 | |||
0a1f35b89a | |||
78278d6889 | |||
6f1a539e83 | |||
0ad619e1d2 | |||
8d876a806e | |||
c7f0a6c2a0 | |||
e4941cb524 | |||
1b687a82a6 | |||
1bb882acf8 | |||
478bf34f2b | |||
dbc87292e4 | |||
bb3a74076f | |||
0cd6031aae | |||
1e1bdbd6e7 | |||
631b63b1b6 | |||
eabcf86436 | |||
7ce0ef770a | |||
599ab33e40 | |||
c584d942d4 |
4
.github/workflows/build-apps.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
||||
- name: Download Wasm Cache
|
||||
id: download-wasm
|
||||
if: ${{ github.event_name == 'pull_request' && steps.filter.outputs.rust == 'false' }}
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
uses: dawidd6/action-download-artifact@v11
|
||||
continue-on-error: true
|
||||
with:
|
||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||
@ -362,7 +362,7 @@ jobs:
|
||||
|
||||
- name: Authenticate to Google Cloud
|
||||
if: ${{ env.IS_STAGING == 'true' }}
|
||||
uses: 'google-github-actions/auth@v2.1.8'
|
||||
uses: 'google-github-actions/auth@v2.1.10'
|
||||
with:
|
||||
credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'
|
||||
|
||||
|
12
.github/workflows/cargo-test.yml
vendored
@ -25,8 +25,8 @@ jobs:
|
||||
- runner=8cpu-linux-x64
|
||||
- extras=s3-cache
|
||||
steps:
|
||||
- uses: runs-on/action@v1
|
||||
- uses: actions/create-github-app-token@v1
|
||||
- uses: runs-on/action@v2
|
||||
- uses: actions/create-github-app-token@v2
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||
@ -149,8 +149,8 @@ jobs:
|
||||
partitionIndex: [1, 2, 3, 4, 5, 6]
|
||||
partitionTotal: [6]
|
||||
steps:
|
||||
- uses: runs-on/action@v1
|
||||
- uses: actions/create-github-app-token@v1
|
||||
- uses: runs-on/action@v2
|
||||
- uses: actions/create-github-app-token@v2
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||
@ -207,8 +207,8 @@ jobs:
|
||||
- runner=32cpu-linux-x64
|
||||
- extras=s3-cache
|
||||
steps:
|
||||
- uses: runs-on/action@v1
|
||||
- uses: actions/create-github-app-token@v1
|
||||
- uses: runs-on/action@v2
|
||||
- uses: actions/create-github-app-token@v2
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||
|
6
.github/workflows/e2e-tests.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
||||
- name: Download Wasm cache
|
||||
id: download-wasm
|
||||
if: ${{ github.event_name != 'schedule' && steps.filter.outputs.rust == 'false' }}
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
uses: dawidd6/action-download-artifact@v11
|
||||
continue-on-error: true
|
||||
with:
|
||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||
@ -110,7 +110,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
|
||||
- uses: actions/create-github-app-token@v1
|
||||
- uses: actions/create-github-app-token@v2
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||
@ -230,7 +230,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
|
||||
- uses: actions/create-github-app-token@v1
|
||||
- uses: actions/create-github-app-token@v2
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||
|
2
.github/workflows/generate-website-docs.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/create-github-app-token@v1
|
||||
- uses: actions/create-github-app-token@v2
|
||||
id: app-token
|
||||
with:
|
||||
# required
|
||||
|
2
.github/workflows/kcl-language-server.yml
vendored
@ -328,7 +328,7 @@ jobs:
|
||||
mkdir -p releases/language-server/${{ env.TAG }}
|
||||
cp -r build/* releases/language-server/${{ env.TAG }}
|
||||
- name: "Authenticate to Google Cloud"
|
||||
uses: "google-github-actions/auth@v2.1.8"
|
||||
uses: "google-github-actions/auth@v2.1.10"
|
||||
with:
|
||||
credentials_json: "${{ secrets.GOOGLE_CLOUD_DL_SA }}"
|
||||
- name: Set up Cloud SDK
|
||||
|
6
.github/workflows/kcl-python-bindings.yml
vendored
@ -113,7 +113,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
uses: astral-sh/setup-uv@v6
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
- uses: taiki-e/install-action@just
|
||||
- name: Run tests
|
||||
@ -130,7 +130,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
uses: astral-sh/setup-uv@v6
|
||||
- name: Install codespell
|
||||
run: |
|
||||
uv venv .venv
|
||||
@ -161,7 +161,7 @@ jobs:
|
||||
with:
|
||||
path: rust/kcl-python-bindings
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
uses: astral-sh/setup-uv@v6
|
||||
- name: do uv things
|
||||
run: |
|
||||
cd rust/kcl-python-bindings
|
||||
|
2
.github/workflows/publish-apps-release.yml
vendored
@ -108,7 +108,7 @@ jobs:
|
||||
run: npm run files:set-notes
|
||||
|
||||
- name: Authenticate to Google Cloud
|
||||
uses: 'google-github-actions/auth@v2.1.8'
|
||||
uses: 'google-github-actions/auth@v2.1.10'
|
||||
with:
|
||||
credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'
|
||||
|
||||
|
30
.github/workflows/static-analysis.yml
vendored
@ -120,6 +120,36 @@ jobs:
|
||||
|
||||
- run: npm run circular-deps:diff
|
||||
|
||||
npm-url-checker:
|
||||
runs-on: ubuntu-latest
|
||||
needs: npm-build-wasm
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
- run: npm install
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: Copy prepared wasm
|
||||
run: |
|
||||
ls -R prepared-wasm
|
||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||
mkdir rust/kcl-wasm-lib/pkg
|
||||
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||
|
||||
- name: Copy prepared ts-rs bindings
|
||||
run: |
|
||||
ls -R prepared-ts-rs-bindings
|
||||
mkdir rust/kcl-lib/bindings
|
||||
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
||||
|
||||
- run: npm run url-checker:diff
|
||||
|
||||
python-codespell:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
|
2
.gitignore
vendored
@ -87,4 +87,4 @@ venv
|
||||
|
||||
.vscode-test
|
||||
.biome/
|
||||
.million
|
||||
.million
|
@ -235,6 +235,47 @@ To display logging (to the terminal or console) set `ZOO_LOG=1`. This will log s
|
||||
|
||||
To enable memory metrics, build with `--features dhat-heap`.
|
||||
|
||||
## Running scripts
|
||||
|
||||
There are multiple scripts under the folder path `./scripts` which can be used in various settings.
|
||||
|
||||
### Pattern for a static file, npm run commands, and CI-CD checks
|
||||
|
||||
If you want to implement a static checker follow this pattern. Two static checkers we have are circular dependency checks in our typescript code and url checker to see if any hard coded URL is the typescript application 404s. We have a set of known files in `./scripts/known/*.txt` which is the baseline.
|
||||
|
||||
If you improve the baseline, run the overwrite command and commit the new smaller baseline. Try not to make the baseline bigger, the CI CD will complain.
|
||||
These baselines are to hold us to higher standards and help implement automated testing against the repository
|
||||
|
||||
#### Output result to stdout
|
||||
- `npm run circular-deps`
|
||||
- `npm run url-checker`
|
||||
|
||||
- create a `<name>.sh` file that will run the static checker then output the result to `stdout`
|
||||
|
||||
#### Overwrite result to known .txt file on disk
|
||||
|
||||
If the application needs to overwrite the known file on disk use this pattern. This known .txt file will be source controlled as the baseline
|
||||
|
||||
- `npm run circular-deps:overwrite`
|
||||
- `npm run url-checker:overwrite`
|
||||
|
||||
#### Diff baseline and current
|
||||
|
||||
These commands will write a /tmp/ file on disk and compare it to the known file in the repository. This command will also be used in the CI CD pipeline for automated checks
|
||||
|
||||
- create a `diff-<name>.sh` file that is the script to diff your tmp file to the baseline
|
||||
e.g. `diff-url-checker.sh`
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
npm run url-checker > /tmp/urls.txt
|
||||
diff --ignore-blank-lines -w /tmp/urls.txt ./scripts/known/urls.txt
|
||||
```
|
||||
|
||||
- `npm run circular-deps:diff`
|
||||
- `npm run url-checker:diff`
|
||||
|
||||
## Proposing changes
|
||||
|
||||
Before you submit a contribution PR to this repo, please ensure that:
|
||||
@ -280,6 +321,9 @@ Assign someone to each section of the manual checklist generated by the issue te
|
||||
Follow the instructions [here](./rust/README.md) to publish new crates.
|
||||
This ensures that the KCL accepted by the app is also accepted by the CLI.
|
||||
|
||||
If there are documentation changes, merge the corresponding Dependabot PRs [here](https://github.com/KittyCAD/website/pulls/app%2Fdependabot) for the website.
|
||||
You can trigger Dependabot to check for updates [here](https://github.com/KittyCAD/website/network/updates/17261214/jobs).
|
||||
|
||||
#### 5. Publish the release
|
||||
|
||||
Head over to https://github.com/KittyCAD/modeling-app/releases/new, pick the newly created tag and type it in the **Release title** field as well.
|
||||
|
3
Makefile
@ -62,7 +62,10 @@ else
|
||||
endif
|
||||
|
||||
public/kcl-samples/manifest.json: $(KCL_SOURCES)
|
||||
ifndef WINDOWS
|
||||
cd rust/kcl-lib && EXPECTORATE=overwrite cargo test generate_manifest
|
||||
@ touch $@
|
||||
endif
|
||||
|
||||
.vite/build/main.js: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
|
||||
npm run tronb:vite:dev
|
||||
|
@ -83,6 +83,13 @@ Allow orbiting in sketch mode.
|
||||
Whether to show the debug panel, which lets you see various states of the app to aid in development.
|
||||
|
||||
|
||||
**Default:** None
|
||||
|
||||
##### fixed_size_grid
|
||||
|
||||
If true, the grid cells will be fixed-size, where the width is your default length unit. If false, the grid will get larger as you zoom out, and smaller as you zoom in.
|
||||
|
||||
|
||||
**Default:** None
|
||||
|
||||
|
||||
|
48
docs/kcl-std/functions/std-sketch-planeOf.md
Normal file
55
docs/kcl-std/functions/std-sketch-rectangle.md
Normal file
@ -67,10 +67,12 @@ layout: manual
|
||||
* [`patternCircular2d`](/docs/kcl-std/functions/std-sketch-patternCircular2d)
|
||||
* [`patternLinear2d`](/docs/kcl-std/functions/std-sketch-patternLinear2d)
|
||||
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
|
||||
* [`planeOf`](/docs/kcl-std/functions/std-sketch-planeOf)
|
||||
* [`polygon`](/docs/kcl-std/functions/std-sketch-polygon)
|
||||
* [`profileStart`](/docs/kcl-std/functions/std-sketch-profileStart)
|
||||
* [`profileStartX`](/docs/kcl-std/functions/std-sketch-profileStartX)
|
||||
* [`profileStartY`](/docs/kcl-std/functions/std-sketch-profileStartY)
|
||||
* [`rectangle`](/docs/kcl-std/functions/std-sketch-rectangle)
|
||||
* [`revolve`](/docs/kcl-std/functions/std-sketch-revolve)
|
||||
* [`segAng`](/docs/kcl-std/functions/std-sketch-segAng)
|
||||
* [`segEnd`](/docs/kcl-std/functions/std-sketch-segEnd)
|
||||
|
@ -32,10 +32,12 @@ This module contains functions for creating and manipulating sketches, and makin
|
||||
* [`patternCircular2d`](/docs/kcl-std/functions/std-sketch-patternCircular2d)
|
||||
* [`patternLinear2d`](/docs/kcl-std/functions/std-sketch-patternLinear2d)
|
||||
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
|
||||
* [`planeOf`](/docs/kcl-std/functions/std-sketch-planeOf)
|
||||
* [`polygon`](/docs/kcl-std/functions/std-sketch-polygon)
|
||||
* [`profileStart`](/docs/kcl-std/functions/std-sketch-profileStart)
|
||||
* [`profileStartX`](/docs/kcl-std/functions/std-sketch-profileStartX)
|
||||
* [`profileStartY`](/docs/kcl-std/functions/std-sketch-profileStartY)
|
||||
* [`rectangle`](/docs/kcl-std/functions/std-sketch-rectangle)
|
||||
* [`revolve`](/docs/kcl-std/functions/std-sketch-revolve)
|
||||
* [`segAng`](/docs/kcl-std/functions/std-sketch-segAng)
|
||||
* [`segEnd`](/docs/kcl-std/functions/std-sketch-segEnd)
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
TEST_COLORS,
|
||||
commonPoints,
|
||||
getUtils,
|
||||
enableConsoleLogEverything,
|
||||
} from '@e2e/playwright/test-utils'
|
||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
|
||||
@ -179,19 +178,7 @@ test.describe('Basic sketch', () => {
|
||||
cmdBar,
|
||||
scene,
|
||||
editor,
|
||||
tronApp,
|
||||
}) => {
|
||||
// await tronApp.cleanProjectDir({
|
||||
// app: {
|
||||
// appearance: {
|
||||
// theme: 'light',
|
||||
// },
|
||||
// },
|
||||
// })
|
||||
enableConsoleLogEverything({
|
||||
page,
|
||||
tronApp,
|
||||
})
|
||||
await doBasicSketch(page, ['code'], { cmdBar, scene, homePage, editor })
|
||||
})
|
||||
|
||||
@ -201,7 +188,6 @@ test.describe('Basic sketch', () => {
|
||||
cmdBar,
|
||||
scene,
|
||||
editor,
|
||||
tronApp,
|
||||
}) => {
|
||||
// Load the app with the code panes
|
||||
await page.addInitScript(async (persistModelingContext) => {
|
||||
|
@ -12,7 +12,7 @@ test.describe('Point and click for boolean workflows', () => {
|
||||
},
|
||||
{
|
||||
name: 'subtract',
|
||||
code: 'subtract([extrude001], tools = [extrude006])',
|
||||
code: 'subtract(extrude001, tools = extrude006)',
|
||||
},
|
||||
{
|
||||
name: 'intersect',
|
||||
@ -81,6 +81,8 @@ test.describe('Point and click for boolean workflows', () => {
|
||||
if (operationName !== 'subtract') {
|
||||
// should down shift key to select multiple objects
|
||||
await page.keyboard.down('Shift')
|
||||
} else {
|
||||
await cmdBar.progressCmdBar()
|
||||
}
|
||||
|
||||
// Select second object
|
||||
@ -103,8 +105,8 @@ test.describe('Point and click for boolean workflows', () => {
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
Tool: '1 path',
|
||||
Target: '1 path',
|
||||
Solids: '1 path',
|
||||
Tools: '1 path',
|
||||
},
|
||||
commandName,
|
||||
})
|
||||
|
@ -5,6 +5,7 @@ import { uuidv4 } from '@src/lib/utils'
|
||||
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
|
||||
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
||||
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||
import { getUtils } from '@e2e/playwright/test-utils'
|
||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
|
||||
@ -14,13 +15,18 @@ test.describe('Can create sketches on all planes and their back sides', () => {
|
||||
homePage: HomePageFixture,
|
||||
scene: SceneFixture,
|
||||
toolbar: ToolbarFixture,
|
||||
cmdBar: CmdBarFixture,
|
||||
plane: string,
|
||||
clickCoords: { x: number; y: number }
|
||||
) => {
|
||||
const u = await getUtils(page)
|
||||
// await page.addInitScript(() => {
|
||||
// localStorage.setItem('persistCode', '@settings(defaultLengthUnit = in)')
|
||||
// })
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
// await scene.settled(cmdBar)
|
||||
const XYPlanRed: [number, number, number] = [98, 50, 51]
|
||||
await scene.expectPixelColor(XYPlanRed, { x: 700, y: 300 }, 15)
|
||||
|
||||
@ -119,12 +125,166 @@ test.describe('Can create sketches on all planes and their back sides', () => {
|
||||
]
|
||||
|
||||
for (const config of planeConfigs) {
|
||||
test(config.plane, async ({ page, homePage, scene, toolbar }) => {
|
||||
test(config.plane, async ({ page, homePage, scene, toolbar, cmdBar }) => {
|
||||
await sketchOnPlaneAndBackSideTest(
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
config.plane,
|
||||
config.coords
|
||||
)
|
||||
})
|
||||
}
|
||||
})
|
||||
test.describe('Can create sketches on offset planes and their back sides', () => {
|
||||
const sketchOnPlaneAndBackSideTest = async (
|
||||
page: Page,
|
||||
homePage: HomePageFixture,
|
||||
scene: SceneFixture,
|
||||
toolbar: ToolbarFixture,
|
||||
cmdbar: CmdBarFixture,
|
||||
plane: string,
|
||||
clickCoords: { x: number; y: number }
|
||||
) => {
|
||||
const u = await getUtils(page)
|
||||
await page.addInitScript(() => {
|
||||
localStorage.setItem(
|
||||
'persistCode',
|
||||
`@settings(defaultLengthUnit = in)
|
||||
xyPlane = offsetPlane(XY, offset = 0.05)
|
||||
xzPlane = offsetPlane(XZ, offset = 0.05)
|
||||
yzPlane = offsetPlane(YZ, offset = 0.05)
|
||||
`
|
||||
)
|
||||
})
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
// await scene.settled(cmdbar)
|
||||
const XYPlanRed: [number, number, number] = [74, 74, 74]
|
||||
await scene.expectPixelColor(XYPlanRed, { x: 700, y: 300 }, 15)
|
||||
|
||||
await u.openDebugPanel()
|
||||
|
||||
const coord =
|
||||
plane === '-XY' || plane === '-YZ' || plane === 'XZ' ? -100 : 100
|
||||
const camCommand: EngineCommand = {
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_look_at',
|
||||
center: { x: 0, y: 0, z: 0 },
|
||||
vantage: { x: coord, y: coord, z: coord },
|
||||
up: { x: 0, y: 0, z: 1 },
|
||||
},
|
||||
}
|
||||
const updateCamCommand: EngineCommand = {
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_get_settings',
|
||||
},
|
||||
}
|
||||
|
||||
const prefix = plane.length === 3 ? '-' : ''
|
||||
const planeName = plane
|
||||
.slice(plane.length === 3 ? 1 : 0)
|
||||
.toLocaleLowerCase()
|
||||
|
||||
const codeLine1 = `sketch001 = startSketchOn(${prefix}${planeName}Plane)`
|
||||
const codeLine2 = `profile001 = startProfile(sketch001, at = [${0.91 + (plane[0] === '-' ? 0.01 : 0)}, -${1.21 + (plane[0] === '-' ? 0.01 : 0)}])`
|
||||
|
||||
await u.openDebugPanel()
|
||||
|
||||
await u.clearCommandLogs()
|
||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||
|
||||
await u.sendCustomCmd(camCommand)
|
||||
await page.waitForTimeout(100)
|
||||
await u.sendCustomCmd(updateCamCommand)
|
||||
|
||||
await u.closeDebugPanel()
|
||||
|
||||
await toolbar.openFeatureTreePane()
|
||||
await toolbar.getDefaultPlaneVisibilityButton('XY').click()
|
||||
await toolbar.getDefaultPlaneVisibilityButton('XZ').click()
|
||||
await toolbar.getDefaultPlaneVisibilityButton('YZ').click()
|
||||
await expect(
|
||||
toolbar
|
||||
.getDefaultPlaneVisibilityButton('YZ')
|
||||
.locator('[aria-label="eye crossed out"]')
|
||||
).toBeVisible()
|
||||
|
||||
await page.mouse.click(clickCoords.x, clickCoords.y)
|
||||
await page.waitForTimeout(600) // wait for animation
|
||||
|
||||
await toolbar.waitUntilSketchingReady()
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'line Line', exact: true })
|
||||
).toBeVisible()
|
||||
|
||||
await u.closeDebugPanel()
|
||||
await page.mouse.click(707, 393)
|
||||
|
||||
await expect(page.locator('.cm-content')).toContainText(codeLine1)
|
||||
await expect(page.locator('.cm-content')).toContainText(codeLine2)
|
||||
|
||||
await page
|
||||
.getByRole('button', { name: 'line Line', exact: true })
|
||||
.first()
|
||||
.click()
|
||||
await u.openAndClearDebugPanel()
|
||||
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||
|
||||
await u.clearCommandLogs()
|
||||
await u.removeCurrentCode()
|
||||
}
|
||||
|
||||
const planeConfigs = [
|
||||
{
|
||||
plane: 'XY',
|
||||
coords: { x: 600, y: 388 },
|
||||
description: 'red plane',
|
||||
},
|
||||
{
|
||||
plane: 'YZ',
|
||||
coords: { x: 700, y: 250 },
|
||||
description: 'green plane',
|
||||
},
|
||||
{
|
||||
plane: 'XZ',
|
||||
coords: { x: 684, y: 427 },
|
||||
description: 'blue plane',
|
||||
},
|
||||
{
|
||||
plane: '-XY',
|
||||
coords: { x: 600, y: 118 },
|
||||
description: 'back of red plane',
|
||||
},
|
||||
{
|
||||
plane: '-YZ',
|
||||
coords: { x: 700, y: 219 },
|
||||
description: 'back of green plane',
|
||||
},
|
||||
{
|
||||
plane: '-XZ',
|
||||
coords: { x: 700, y: 80 },
|
||||
description: 'back of blue plane',
|
||||
},
|
||||
]
|
||||
|
||||
for (const config of planeConfigs) {
|
||||
test(config.plane, async ({ page, homePage, scene, toolbar, cmdBar }) => {
|
||||
await sketchOnPlaneAndBackSideTest(
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
config.plane,
|
||||
config.coords
|
||||
)
|
||||
|
@ -265,6 +265,8 @@ middle(0)
|
||||
})
|
||||
await expect(
|
||||
page.getByText(`assert failed: Expected 0 to be greater than 0 but it wasn't
|
||||
|
||||
Backtrace:
|
||||
assert()
|
||||
check()
|
||||
middle()`)
|
||||
|
@ -525,7 +525,9 @@ test.describe('Command bar tests', () => {
|
||||
const projectName = 'test'
|
||||
const beforeKclCode = `a = 5
|
||||
b = a * a
|
||||
c = 3 + a`
|
||||
c = 3 + a
|
||||
theta = 45deg
|
||||
`
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const testProject = join(dir, projectName)
|
||||
await fsp.mkdir(testProject, { recursive: true })
|
||||
@ -615,9 +617,45 @@ c = 3 + a`
|
||||
stage: 'commandBarClosed',
|
||||
})
|
||||
})
|
||||
await test.step(`Edit a parameter with explicit units via command bar`, async () => {
|
||||
await cmdBar.cmdBarOpenBtn.click()
|
||||
await cmdBar.chooseCommand('edit parameter')
|
||||
await cmdBar
|
||||
.selectOption({
|
||||
name: 'theta',
|
||||
})
|
||||
.click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
commandName: 'Edit parameter',
|
||||
currentArgKey: 'value',
|
||||
currentArgValue: '45deg',
|
||||
headerArguments: {
|
||||
Name: 'theta',
|
||||
Value: '',
|
||||
},
|
||||
highlightedHeaderArg: 'value',
|
||||
})
|
||||
await cmdBar.argumentInput
|
||||
.locator('[contenteditable]')
|
||||
.fill('45deg + 1deg')
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
commandName: 'Edit parameter',
|
||||
headerArguments: {
|
||||
Name: 'theta',
|
||||
Value: '46deg',
|
||||
},
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'commandBarClosed',
|
||||
})
|
||||
})
|
||||
|
||||
await editor.expectEditor.toContain(
|
||||
`a = 5b = a * amyParameter001 = ${newValue}c = 3 + a`
|
||||
`a = 5b = a * amyParameter001 = ${newValue}c = 3 + atheta = 45deg + 1deg`
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -288,7 +288,7 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-info')
|
||||
await expect(
|
||||
page.getByText('Identifiers must be lowerCamelCase').first()
|
||||
page.getByText('Identifiers should be lowerCamelCase').first()
|
||||
).toBeVisible()
|
||||
|
||||
await page.locator('#code-pane button:first-child').click()
|
||||
@ -314,7 +314,7 @@ sketch_001 = startSketchOn(XY)
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-info')
|
||||
await expect(
|
||||
page.getByText('Identifiers must be lowerCamelCase').first()
|
||||
page.getByText('Identifiers should be lowerCamelCase').first()
|
||||
).toBeVisible()
|
||||
})
|
||||
|
||||
@ -511,7 +511,7 @@ sketch_001 = startSketchOn(XY)
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-info')
|
||||
await expect(
|
||||
page.getByText('Identifiers must be lowerCamelCase').first()
|
||||
page.getByText('Identifiers should be lowerCamelCase').first()
|
||||
).toBeVisible()
|
||||
|
||||
// focus the editor
|
||||
@ -539,7 +539,7 @@ sketch_001 = startSketchOn(XY)
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-info')
|
||||
await expect(
|
||||
page.getByText('Identifiers must be lowerCamelCase').first()
|
||||
page.getByText('Identifiers should be lowerCamelCase').first()
|
||||
).toBeVisible()
|
||||
})
|
||||
|
||||
@ -681,7 +681,7 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-info')
|
||||
await expect(
|
||||
page.getByText('Identifiers must be lowerCamelCase').first()
|
||||
page.getByText('Identifiers should be lowerCamelCase').first()
|
||||
).toBeVisible()
|
||||
|
||||
// select the line that's causing the error and delete it
|
||||
@ -1617,4 +1617,33 @@ sketch001 = startSketchOn(XZ)
|
||||
// Verify error is still visible
|
||||
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(1)
|
||||
})
|
||||
|
||||
test('Core dump hotkey', async ({ page, scene, cmdBar, homePage }) => {
|
||||
await page.addInitScript(async () => {
|
||||
localStorage.setItem(
|
||||
'persistCode',
|
||||
`sketch001 = startSketchOn(XZ)
|
||||
profile001 = circle(sketch001, center = [-100.0, -100.0], radius = 50.0)
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
const viewportSize = { width: 1200, height: 800 }
|
||||
await page.setBodyDimensions(viewportSize)
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
await scene.connectionEstablished()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
const modifier = process.platform === 'darwin' ? 'Meta' : 'Control'
|
||||
|
||||
await page.keyboard.press(`${modifier}+Shift+.`)
|
||||
|
||||
const toast1 = page.getByText('Starting core dump...')
|
||||
await expect(toast1).toBeVisible()
|
||||
|
||||
const toast2 = page.getByText('Core dump completed')
|
||||
await expect(toast2).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
@ -187,6 +187,13 @@ export class CmdBarFixture {
|
||||
return this.page.getByRole('option', options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an optional argument from the command bar during review
|
||||
*/
|
||||
clickOptionalArgument = async (argName: string) => {
|
||||
await this.page.getByTestId(`cmd-bar-add-optional-arg-${argName}`).click()
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks the Create new variable button for kcl input
|
||||
*/
|
||||
|
@ -274,6 +274,13 @@ export class ToolbarFixture {
|
||||
.nth(operationIndex)
|
||||
}
|
||||
|
||||
getDefaultPlaneVisibilityButton(plane: 'XY' | 'XZ' | 'YZ' = 'XY') {
|
||||
const index = plane === 'XZ' ? 0 : plane === 'XY' ? 1 : 2
|
||||
return this.featureTreePane
|
||||
.getByTestId('feature-tree-visibility-toggle')
|
||||
.nth(index)
|
||||
}
|
||||
|
||||
/**
|
||||
* View source on a specific operation in the Feature Tree pane.
|
||||
* @param operationName The name of the operation type
|
||||
|
@ -7,6 +7,7 @@ import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
import { bracket } from '@e2e/playwright/fixtures/bracket'
|
||||
import type { CmdBarSerialised } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||
|
||||
// test file is for testing point an click code gen functionality that's not sketch mode related
|
||||
|
||||
@ -135,17 +136,17 @@ test.describe('Point-and-click tests', () => {
|
||||
highlightedHeaderArg: 'length',
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await page.keyboard.insertText('width - 0.001')
|
||||
await page.keyboard.insertText('width - 0.001in')
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
Length: '4.999',
|
||||
Length: '4.999in',
|
||||
},
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
await editor.expectEditor.toContain('extrude(length = width - 0.001)')
|
||||
await editor.expectEditor.toContain('extrude(length = width - 0.001in)')
|
||||
})
|
||||
|
||||
await test.step(`Edit second extrude via feature tree`, async () => {
|
||||
@ -1141,6 +1142,20 @@ openSketch = startSketchOn(XY)
|
||||
})
|
||||
})
|
||||
|
||||
const initialCmdBarStateHelix: CmdBarSerialised = {
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'mode',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
Mode: '',
|
||||
AngleStart: '',
|
||||
Revolutions: '',
|
||||
Radius: '',
|
||||
},
|
||||
highlightedHeaderArg: 'mode',
|
||||
commandName: 'Helix',
|
||||
}
|
||||
|
||||
test('Helix point-and-click on default axis', async ({
|
||||
context,
|
||||
page,
|
||||
@ -1150,30 +1165,14 @@ openSketch = startSketchOn(XY)
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
// One dumb hardcoded screen pixel value
|
||||
const testPoint = { x: 620, y: 257 }
|
||||
const expectedOutput = `helix001 = helix( axis = X, radius = 5, length = 5, revolutions = 1, angleStart = 270, ccw = false,)`
|
||||
const expectedOutput = `helix001 = helix( axis = X, radius = 5, length = 5, revolutions = 1, angleStart = 270,)`
|
||||
const expectedLine = `axis=X,`
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
await scene.connectionEstablished()
|
||||
|
||||
await test.step(`Go through the command bar flow`, async () => {
|
||||
await toolbar.helixButton.click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'mode',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
Mode: '',
|
||||
AngleStart: '',
|
||||
Revolutions: '',
|
||||
Radius: '',
|
||||
CounterClockWise: '',
|
||||
},
|
||||
highlightedHeaderArg: 'mode',
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.expectState(initialCmdBarStateHelix)
|
||||
await cmdBar.progressCmdBar()
|
||||
await expect.poll(() => page.getByText('Axis').count()).toBe(6)
|
||||
await cmdBar.progressCmdBar()
|
||||
@ -1190,7 +1189,6 @@ openSketch = startSketchOn(XY)
|
||||
AngleStart: '',
|
||||
Length: '',
|
||||
Radius: '',
|
||||
CounterClockWise: '',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
@ -1207,11 +1205,10 @@ openSketch = startSketchOn(XY)
|
||||
Revolutions: '1',
|
||||
Length: '5',
|
||||
Radius: '5',
|
||||
CounterClockWise: '',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.submit()
|
||||
})
|
||||
|
||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||
@ -1221,8 +1218,6 @@ openSketch = startSketchOn(XY)
|
||||
activeLines: [expectedLine],
|
||||
highlightedCode: '',
|
||||
})
|
||||
// Red plane is now gone, white helix is there
|
||||
await scene.expectPixelColor([250, 250, 250], testPoint, 15)
|
||||
})
|
||||
|
||||
await test.step(`Edit helix through the feature tree`, async () => {
|
||||
@ -1234,21 +1229,18 @@ openSketch = startSketchOn(XY)
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Helix',
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'CounterClockWise',
|
||||
currentArgValue: '',
|
||||
currentArgKey: 'length',
|
||||
currentArgValue: '5',
|
||||
headerArguments: {
|
||||
Axis: 'X',
|
||||
AngleStart: '270',
|
||||
Revolutions: '1',
|
||||
Radius: '5',
|
||||
Length: initialInput,
|
||||
CounterClockWise: '',
|
||||
},
|
||||
highlightedHeaderArg: 'CounterClockWise',
|
||||
highlightedHeaderArg: 'length',
|
||||
})
|
||||
await page.keyboard.press('Shift+Backspace')
|
||||
await expect(cmdBar.currentArgumentInput).toBeVisible()
|
||||
await cmdBar.currentArgumentInput.locator('.cm-content').fill(newInput)
|
||||
await page.keyboard.insertText(newInput)
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
@ -1258,11 +1250,10 @@ openSketch = startSketchOn(XY)
|
||||
Revolutions: '1',
|
||||
Radius: '5',
|
||||
Length: newInput,
|
||||
CounterClockWise: '',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.submit()
|
||||
await toolbar.closeFeatureTreePane()
|
||||
await editor.openPane()
|
||||
await editor.expectEditor.toContain('length = ' + newInput)
|
||||
@ -1273,174 +1264,238 @@ openSketch = startSketchOn(XY)
|
||||
const operationButton = await toolbar.getFeatureTreeOperation('Helix', 0)
|
||||
await operationButton.click({ button: 'left' })
|
||||
await page.keyboard.press('Delete')
|
||||
// Red plane is back
|
||||
await scene.expectPixelColor([96, 52, 52], testPoint, 15)
|
||||
await scene.settled(cmdBar)
|
||||
await editor.expectEditor.not.toContain('helix')
|
||||
await expect(
|
||||
await toolbar.getFeatureTreeOperation('Helix', 0)
|
||||
).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
const helixCases = [
|
||||
{
|
||||
selectionType: 'segment',
|
||||
testPoint: { x: 513, y: 221 },
|
||||
expectedOutput: `helix001 = helix( axis = seg01, radius = 1, revolutions = 20, angleStart = 0, ccw = false,)`,
|
||||
expectedEditedOutput: `helix001 = helix( axis = seg01, radius = 5, revolutions = 20, angleStart = 0, ccw = false,)`,
|
||||
},
|
||||
{
|
||||
selectionType: 'sweepEdge',
|
||||
testPoint: { x: 564, y: 364 },
|
||||
expectedOutput: `helix001 = helix( axis = getOppositeEdge(seg01), radius = 1, revolutions = 20, angleStart = 0, ccw = false,)`,
|
||||
expectedEditedOutput: `helix001 = helix( axis = getOppositeEdge(seg01), radius = 5, revolutions = 20, angleStart = 0, ccw = false,)`,
|
||||
},
|
||||
]
|
||||
helixCases.map(
|
||||
({ selectionType, testPoint, expectedOutput, expectedEditedOutput }) => {
|
||||
test(`Helix point-and-click around ${selectionType}`, async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
editor,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
page.on('console', console.log)
|
||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
||||
profile001 = startProfile(sketch001, at = [0, 0])
|
||||
|> yLine(length = 100)
|
||||
|> line(endAbsolute = [100, 0])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude001 = extrude(profile001, length = 100)`
|
||||
test(`Helix point-and-click around segment`, async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
editor,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
||||
profile001 = startProfile(sketch001, at = [0, 0])
|
||||
|> yLine(length = 100)
|
||||
|> line(endAbsolute = [100, 0])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()`
|
||||
await context.addInitScript((initialCode) => {
|
||||
localStorage.setItem('persistCode', initialCode)
|
||||
}, initialCode)
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
// One dumb hardcoded screen pixel value
|
||||
const [clickOnEdge] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
||||
|
||||
await context.addInitScript((initialCode) => {
|
||||
localStorage.setItem('persistCode', initialCode)
|
||||
}, initialCode)
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
await test.step(`Go through the command bar flow`, async () => {
|
||||
await toolbar.closePane('code')
|
||||
await toolbar.helixButton.click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'mode',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
AngleStart: '',
|
||||
Mode: '',
|
||||
CounterClockWise: '',
|
||||
Radius: '',
|
||||
Revolutions: '',
|
||||
},
|
||||
highlightedHeaderArg: 'mode',
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.selectOption({ name: 'Edge' }).click()
|
||||
await expect
|
||||
.poll(() => page.getByText('Please select one').count())
|
||||
.toBe(1)
|
||||
await clickOnEdge()
|
||||
await page.waitForTimeout(1000)
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.waitForTimeout(1000)
|
||||
await cmdBar.argumentInput.focus()
|
||||
await page.waitForTimeout(1000)
|
||||
await page.keyboard.insertText('20')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('0')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('1')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('100')
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
Mode: 'Edge',
|
||||
Edge: `1 ${selectionType}`,
|
||||
AngleStart: '0',
|
||||
Revolutions: '20',
|
||||
Radius: '1',
|
||||
CounterClockWise: '',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.waitForTimeout(1000)
|
||||
})
|
||||
|
||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||
await toolbar.openPane('code')
|
||||
await editor.expectEditor.toContain(expectedOutput)
|
||||
await toolbar.closePane('code')
|
||||
})
|
||||
|
||||
await test.step(`Edit helix through the feature tree`, async () => {
|
||||
await toolbar.openPane('feature-tree')
|
||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||
'Helix',
|
||||
0
|
||||
)
|
||||
await operationButton.dblclick()
|
||||
const initialInput = '1'
|
||||
const newInput = '5'
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Helix',
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'CounterClockWise',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
AngleStart: '0',
|
||||
Revolutions: '20',
|
||||
Radius: initialInput,
|
||||
CounterClockWise: '',
|
||||
},
|
||||
highlightedHeaderArg: 'CounterClockWise',
|
||||
})
|
||||
await page
|
||||
.getByRole('button', { name: 'radius', exact: false })
|
||||
.click()
|
||||
await expect(cmdBar.currentArgumentInput).toBeVisible()
|
||||
await cmdBar.currentArgumentInput
|
||||
.locator('.cm-content')
|
||||
.fill(newInput)
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
AngleStart: '0',
|
||||
Revolutions: '20',
|
||||
Radius: newInput,
|
||||
CounterClockWise: '',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
await toolbar.closePane('feature-tree')
|
||||
await toolbar.openPane('code')
|
||||
await editor.expectEditor.toContain(expectedEditedOutput)
|
||||
await toolbar.closePane('code')
|
||||
})
|
||||
|
||||
await test.step('Delete helix via feature tree selection', async () => {
|
||||
await toolbar.openPane('feature-tree')
|
||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||
'Helix',
|
||||
0
|
||||
)
|
||||
await operationButton.click({ button: 'left' })
|
||||
await page.keyboard.press('Delete')
|
||||
await editor.expectEditor.not.toContain(expectedEditedOutput)
|
||||
await expect(
|
||||
await toolbar.getFeatureTreeOperation('Helix', 0)
|
||||
).not.toBeVisible()
|
||||
})
|
||||
await test.step(`Go through the command bar flow`, async () => {
|
||||
await toolbar.closePane('code')
|
||||
await toolbar.helixButton.click()
|
||||
await cmdBar.expectState(initialCmdBarStateHelix)
|
||||
await cmdBar.selectOption({ name: 'Edge' }).click()
|
||||
await editor.selectText('yLine(length = 100)')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('1')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('2')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('3')
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
Mode: 'Edge',
|
||||
Edge: `1 segment`,
|
||||
AngleStart: '2',
|
||||
Revolutions: '1',
|
||||
Radius: '3',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
}
|
||||
)
|
||||
await cmdBar.submit()
|
||||
await scene.settled(cmdBar)
|
||||
})
|
||||
|
||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||
await toolbar.openPane('code')
|
||||
await editor.expectEditor.toContain(
|
||||
`
|
||||
helix001 = helix(
|
||||
axis = seg01,
|
||||
radius = 3,
|
||||
revolutions = 1,
|
||||
angleStart = 2,
|
||||
)`,
|
||||
{ shouldNormalise: true }
|
||||
)
|
||||
await toolbar.closePane('code')
|
||||
})
|
||||
})
|
||||
|
||||
test(`Helix point-and-click around sweepEdge with edit and delete flows`, async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
editor,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
||||
profile001 = startProfile(sketch001, at = [0, 0])
|
||||
|> yLine(length = 100)
|
||||
|> line(endAbsolute = [100, 0])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude001 = extrude(profile001, length = 100)`
|
||||
|
||||
// One dumb hardcoded screen pixel value to click on the sweepEdge, can't think of another way?
|
||||
const testPoint = { x: 564, y: 364 }
|
||||
const [clickOnEdge] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
||||
|
||||
await context.addInitScript((initialCode) => {
|
||||
localStorage.setItem('persistCode', initialCode)
|
||||
}, initialCode)
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
await test.step(`Go through the command bar flow`, async () => {
|
||||
await toolbar.closePane('code')
|
||||
await toolbar.helixButton.click()
|
||||
await cmdBar.expectState(initialCmdBarStateHelix)
|
||||
await cmdBar.selectOption({ name: 'Edge' }).click()
|
||||
await expect
|
||||
.poll(() => page.getByText('Please select one').count())
|
||||
.toBe(1)
|
||||
await clickOnEdge()
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.argumentInput.focus()
|
||||
await page.keyboard.insertText('20')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('0')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('1')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.keyboard.insertText('100')
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
Mode: 'Edge',
|
||||
Edge: `1 sweepEdge`,
|
||||
AngleStart: '0',
|
||||
Revolutions: '20',
|
||||
Radius: '1',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.submit()
|
||||
await scene.settled(cmdBar)
|
||||
})
|
||||
|
||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||
await toolbar.openPane('code')
|
||||
await editor.expectEditor.toContain(
|
||||
`
|
||||
helix001 = helix(
|
||||
axis = getOppositeEdge(seg01),
|
||||
radius = 1,
|
||||
revolutions = 20,
|
||||
angleStart = 0,
|
||||
)`,
|
||||
{ shouldNormalise: true }
|
||||
)
|
||||
await toolbar.closePane('code')
|
||||
})
|
||||
|
||||
await test.step(`Edit helix through the feature tree`, async () => {
|
||||
await toolbar.openPane('feature-tree')
|
||||
const operationButton = await toolbar.getFeatureTreeOperation('Helix', 0)
|
||||
await operationButton.dblclick()
|
||||
const initialInput = '1'
|
||||
const newInput = '5'
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Helix',
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'radius',
|
||||
currentArgValue: initialInput,
|
||||
headerArguments: {
|
||||
AngleStart: '0',
|
||||
Revolutions: '20',
|
||||
Radius: initialInput,
|
||||
},
|
||||
highlightedHeaderArg: 'radius',
|
||||
})
|
||||
await page.keyboard.insertText(newInput)
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
AngleStart: '0',
|
||||
Revolutions: '20',
|
||||
Radius: newInput,
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.clickOptionalArgument('ccw')
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Helix',
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'CounterClockWise',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
AngleStart: '0',
|
||||
Revolutions: '20',
|
||||
Radius: newInput,
|
||||
CounterClockWise: '',
|
||||
},
|
||||
highlightedHeaderArg: 'CounterClockWise',
|
||||
})
|
||||
await cmdBar.selectOption({ name: 'True' }).click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
AngleStart: '0',
|
||||
Revolutions: '20',
|
||||
Radius: newInput,
|
||||
CounterClockWise: '',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.submit()
|
||||
await toolbar.closePane('feature-tree')
|
||||
await toolbar.openPane('code')
|
||||
await editor.expectEditor.toContain(
|
||||
`
|
||||
helix001 = helix(
|
||||
axis = getOppositeEdge(seg01),
|
||||
radius = 5,
|
||||
revolutions = 20,
|
||||
angleStart = 0,
|
||||
ccw = true,
|
||||
)`,
|
||||
{ shouldNormalise: true }
|
||||
)
|
||||
await toolbar.closePane('code')
|
||||
})
|
||||
|
||||
await test.step('Delete helix via feature tree selection', async () => {
|
||||
await toolbar.openPane('feature-tree')
|
||||
const operationButton = await toolbar.getFeatureTreeOperation('Helix', 0)
|
||||
await operationButton.click({ button: 'left' })
|
||||
await page.keyboard.press('Delete')
|
||||
await editor.expectEditor.not.toContain('helix')
|
||||
await expect(
|
||||
await toolbar.getFeatureTreeOperation('Helix', 0)
|
||||
).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
test('Helix point-and-click on cylinder', async ({
|
||||
context,
|
||||
@ -1470,26 +1525,12 @@ extrude001 = extrude(profile001, length = 100)
|
||||
// One dumb hardcoded screen pixel value
|
||||
const testPoint = { x: 620, y: 257 }
|
||||
const [clickOnWall] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
||||
const expectedOutput = `helix001 = helix( cylinder = extrude001, revolutions = 1, angleStart = 360, ccw = false,)`
|
||||
const expectedLine = `cylinder = extrude001,`
|
||||
const expectedEditedOutput = `helix001 = helix( cylinder = extrude001, revolutions = 1, angleStart = 360, ccw = true,)`
|
||||
const expectedOutput = `helix001 = helix(cylinder = extrude001, revolutions = 1, angleStart = 360)`
|
||||
const expectedEditedOutput = `helix001 = helix(cylinder = extrude001, revolutions = 1, angleStart = 10)`
|
||||
|
||||
await test.step(`Go through the command bar flow`, async () => {
|
||||
await toolbar.helixButton.click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'mode',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
Mode: '',
|
||||
AngleStart: '',
|
||||
Revolutions: '',
|
||||
Radius: '',
|
||||
CounterClockWise: '',
|
||||
},
|
||||
highlightedHeaderArg: 'mode',
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.expectState(initialCmdBarStateHelix)
|
||||
await cmdBar.selectOption({ name: 'Cylinder' }).click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
@ -1500,7 +1541,6 @@ extrude001 = extrude(profile001, length = 100)
|
||||
Cylinder: '',
|
||||
AngleStart: '',
|
||||
Revolutions: '',
|
||||
CounterClockWise: '',
|
||||
},
|
||||
highlightedHeaderArg: 'cylinder',
|
||||
commandName: 'Helix',
|
||||
@ -1516,18 +1556,17 @@ extrude001 = extrude(profile001, length = 100)
|
||||
Cylinder: '1 face',
|
||||
AngleStart: '360',
|
||||
Revolutions: '1',
|
||||
CounterClockWise: '',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.submit()
|
||||
})
|
||||
|
||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||
await editor.expectEditor.toContain(expectedOutput)
|
||||
await editor.expectState({
|
||||
diagnostics: [],
|
||||
activeLines: [expectedLine],
|
||||
activeLines: [expectedOutput],
|
||||
highlightedCode: '',
|
||||
})
|
||||
})
|
||||
@ -1539,22 +1578,21 @@ extrude001 = extrude(profile001, length = 100)
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Helix',
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'CounterClockWise',
|
||||
currentArgValue: '',
|
||||
currentArgKey: 'angleStart',
|
||||
currentArgValue: '360',
|
||||
headerArguments: {
|
||||
AngleStart: '360',
|
||||
Revolutions: '1',
|
||||
CounterClockWise: '',
|
||||
},
|
||||
highlightedHeaderArg: 'CounterClockWise',
|
||||
highlightedHeaderArg: 'angleStart',
|
||||
})
|
||||
await cmdBar.selectOption({ name: 'True' }).click()
|
||||
await page.keyboard.insertText('10')
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
AngleStart: '360',
|
||||
AngleStart: '10',
|
||||
Revolutions: '1',
|
||||
CounterClockWise: 'true',
|
||||
},
|
||||
commandName: 'Helix',
|
||||
})
|
||||
@ -1610,6 +1648,8 @@ sketch002 = startSketchOn(plane001)
|
||||
testPoint.y + 80
|
||||
)
|
||||
const loftDeclaration = 'loft001 = loft([sketch001, sketch002])'
|
||||
const editedLoftDeclaration =
|
||||
'loft001 = loft([sketch001, sketch002], vDegree = 3)'
|
||||
|
||||
await test.step(`Look for the white of the sketch001 shape`, async () => {
|
||||
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
||||
@ -1681,6 +1721,39 @@ sketch002 = startSketchOn(plane001)
|
||||
await scene.expectPixelColor([89, 89, 89], testPoint, 15)
|
||||
})
|
||||
|
||||
await test.step('Go through the edit flow via feature tree', async () => {
|
||||
await toolbar.openPane('feature-tree')
|
||||
const op = await toolbar.getFeatureTreeOperation('Loft', 0)
|
||||
await op.dblclick()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {},
|
||||
commandName: 'Loft',
|
||||
})
|
||||
await cmdBar.clickOptionalArgument('vDegree')
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'vDegree',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
VDegree: '',
|
||||
},
|
||||
highlightedHeaderArg: 'vDegree',
|
||||
commandName: 'Loft',
|
||||
})
|
||||
await page.keyboard.insertText('3')
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
VDegree: '3',
|
||||
},
|
||||
commandName: 'Loft',
|
||||
})
|
||||
await cmdBar.submit()
|
||||
await editor.expectEditor.toContain(editedLoftDeclaration)
|
||||
})
|
||||
|
||||
await test.step('Delete loft via feature tree selection', async () => {
|
||||
await editor.closePane()
|
||||
const operationButton = await toolbar.getFeatureTreeOperation('Loft', 0)
|
||||
@ -1691,72 +1764,6 @@ sketch002 = startSketchOn(plane001)
|
||||
})
|
||||
})
|
||||
|
||||
// TODO: merge with above test. Right now we're not able to delete a loft
|
||||
// right after creation via selection for some reason, so we go with a new instance
|
||||
test('Loft and offset plane deletion via selection', async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
cmdBar,
|
||||
}) => {
|
||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
||||
|> circle(center = [0, 0], radius = 30)
|
||||
plane001 = offsetPlane(XZ, offset = 50)
|
||||
sketch002 = startSketchOn(plane001)
|
||||
|> circle(center = [0, 0], radius = 20)
|
||||
loft001 = loft([sketch001, sketch002])
|
||||
`
|
||||
await context.addInitScript((initialCode) => {
|
||||
localStorage.setItem('persistCode', initialCode)
|
||||
}, initialCode)
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
// One dumb hardcoded screen pixel value
|
||||
const testPoint = { x: 575, y: 200 }
|
||||
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
||||
const [clickOnSketch2] = scene.makeMouseHelpers(
|
||||
testPoint.x,
|
||||
testPoint.y + 80
|
||||
)
|
||||
|
||||
await test.step(`Delete loft`, async () => {
|
||||
// Check for loft
|
||||
await scene.expectPixelColor([89, 89, 89], testPoint, 15)
|
||||
await clickOnSketch1()
|
||||
await expect(page.locator('.cm-activeLine')).toHaveText(`
|
||||
|> circle(center = [0, 0], radius = 30)
|
||||
`)
|
||||
await page.keyboard.press('Delete')
|
||||
// Check for sketch 1
|
||||
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
||||
})
|
||||
|
||||
await test.step('Delete sketch002', async () => {
|
||||
await page.waitForTimeout(1000)
|
||||
await clickOnSketch2()
|
||||
await expect(page.locator('.cm-activeLine')).toHaveText(`
|
||||
|> circle(center = [0, 0], radius = 20)
|
||||
`)
|
||||
await page.keyboard.press('Delete')
|
||||
// Check for plane001
|
||||
await scene.expectPixelColor([228, 228, 228], testPoint, 15)
|
||||
})
|
||||
|
||||
await test.step('Delete plane001', async () => {
|
||||
await page.waitForTimeout(1000)
|
||||
await clickOnSketch2()
|
||||
await expect(page.locator('.cm-activeLine')).toHaveText(`
|
||||
plane001 = offsetPlane(XZ, offset = 50)
|
||||
`)
|
||||
await page.keyboard.press('Delete')
|
||||
// Check for sketch 1
|
||||
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
||||
})
|
||||
})
|
||||
|
||||
const sweepCases = [
|
||||
{
|
||||
targetType: 'circle',
|
||||
@ -1954,6 +1961,7 @@ profile002 = startProfile(sketch002, at = [0, 0])
|
||||
sketch001 = startSketchOn(XZ)
|
||||
profile001 = ${circleCode}`
|
||||
const sweepDeclaration = 'sweep001 = sweep(profile001, path = helix001)'
|
||||
const editedSweepDeclaration = `sweep001 = sweep(profile001, path = helix001, relativeTo = 'sketchPlane')`
|
||||
|
||||
await context.addInitScript((initialCode) => {
|
||||
localStorage.setItem('persistCode', initialCode)
|
||||
@ -2015,11 +2023,43 @@ profile001 = ${circleCode}`
|
||||
await editor.expectEditor.toContain(sweepDeclaration)
|
||||
})
|
||||
|
||||
await test.step('Go through the edit flow via feature tree', async () => {
|
||||
await toolbar.openPane('feature-tree')
|
||||
const op = await toolbar.getFeatureTreeOperation('Sweep', 0)
|
||||
await op.dblclick()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {},
|
||||
commandName: 'Sweep',
|
||||
})
|
||||
await cmdBar.clickOptionalArgument('relativeTo')
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'relativeTo',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
RelativeTo: '',
|
||||
},
|
||||
highlightedHeaderArg: 'relativeTo',
|
||||
commandName: 'Sweep',
|
||||
})
|
||||
await cmdBar.selectOption({ name: 'sketchPlane' }).click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
RelativeTo: 'sketchPlane',
|
||||
},
|
||||
commandName: 'Sweep',
|
||||
})
|
||||
await cmdBar.submit()
|
||||
await editor.expectEditor.toContain(editedSweepDeclaration)
|
||||
})
|
||||
|
||||
await test.step('Delete sweep via feature tree selection', async () => {
|
||||
const sweep = await toolbar.getFeatureTreeOperation('Sweep', 0)
|
||||
await sweep.click()
|
||||
await page.keyboard.press('Delete')
|
||||
await editor.expectEditor.not.toContain(sweepDeclaration)
|
||||
await editor.expectEditor.not.toContain(editedSweepDeclaration)
|
||||
})
|
||||
})
|
||||
|
||||
@ -3879,6 +3919,8 @@ sketch002 = startSketchOn(extrude001, face = rectangleSegmentA001)
|
||||
|
||||
// Edit flow
|
||||
const newAngle = '270'
|
||||
const newAngle2 = '5'
|
||||
const editedCodeToFind = `revolve001 = revolve(sketch003, angle = ${newAngle}, axis = seg01, bidirectionalAngle = ${newAngle2}, )`
|
||||
await toolbar.openPane('feature-tree')
|
||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||
'Revolve',
|
||||
@ -3904,11 +3946,33 @@ sketch002 = startSketchOn(extrude001, face = rectangleSegmentA001)
|
||||
},
|
||||
commandName: 'Revolve',
|
||||
})
|
||||
await cmdBar.clickOptionalArgument('bidirectionalAngle')
|
||||
await cmdBar.expectState({
|
||||
commandName: 'Revolve',
|
||||
currentArgKey: 'bidirectionalAngle',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
Angle: newAngle,
|
||||
BidirectionalAngle: '',
|
||||
},
|
||||
highlightedHeaderArg: 'bidirectionalAngle',
|
||||
stage: 'arguments',
|
||||
})
|
||||
await page.keyboard.insertText(newAngle2)
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
Angle: newAngle,
|
||||
BidirectionalAngle: newAngle2,
|
||||
},
|
||||
commandName: 'Revolve',
|
||||
})
|
||||
await cmdBar.submit()
|
||||
await toolbar.closePane('feature-tree')
|
||||
await editor.expectEditor.toContain(
|
||||
newCodeToFind.replace('angle = 360', 'angle = ' + newAngle)
|
||||
)
|
||||
await editor.expectEditor.toContain(editedCodeToFind, {
|
||||
shouldNormalise: true,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -4923,4 +4987,154 @@ extrude001 = extrude(profile001 length = 1)`
|
||||
await editor.expectEditor.toContain(badCode, { shouldNormalise: true })
|
||||
})
|
||||
})
|
||||
|
||||
test('Point-and-click extrude with optional args', async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
editor,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
const squareProfileCode = `length001 = 100
|
||||
sketch001 = startSketchOn(XY)
|
||||
profile001 = startProfile(sketch001, at = [0, 0])
|
||||
|> yLine(length = length001)
|
||||
|> xLine(length = length001)
|
||||
|> yLine(length = -length001)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
`
|
||||
await context.addInitScript((initialCode) => {
|
||||
localStorage.setItem('persistCode', initialCode)
|
||||
}, squareProfileCode)
|
||||
await homePage.goToModelingScene()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
await test.step('Select through code', async () => {
|
||||
await editor.selectText('startProfile(sketch001, at = [0, 0])')
|
||||
})
|
||||
|
||||
await test.step('Go through command bar flow', async () => {
|
||||
await toolbar.extrudeButton.click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'sketches',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
Profiles: '',
|
||||
Length: '',
|
||||
},
|
||||
highlightedHeaderArg: 'Profiles',
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'length',
|
||||
currentArgValue: '5',
|
||||
headerArguments: {
|
||||
Profiles: '1 profile',
|
||||
Length: '',
|
||||
},
|
||||
highlightedHeaderArg: 'length',
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
Profiles: '1 profile',
|
||||
Length: '5',
|
||||
},
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await cmdBar.clickOptionalArgument('bidirectionalLength')
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'bidirectionalLength',
|
||||
currentArgValue: '',
|
||||
headerArguments: {
|
||||
Profiles: '1 profile',
|
||||
Length: '5',
|
||||
BidirectionalLength: '',
|
||||
},
|
||||
highlightedHeaderArg: 'bidirectionalLength',
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await page.keyboard.insertText('10')
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
Profiles: '1 profile',
|
||||
Length: '5',
|
||||
BidirectionalLength: '10',
|
||||
},
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await cmdBar.submit()
|
||||
})
|
||||
|
||||
await test.step('Check that the code has changed', async () => {
|
||||
await scene.settled(cmdBar)
|
||||
await editor.expectEditor.toContain(
|
||||
`extrude001 = extrude(profile001, length = 5, bidirectionalLength = 10)`,
|
||||
{ shouldNormalise: true }
|
||||
)
|
||||
})
|
||||
|
||||
await test.step('Go through the edit flow via feature tree', async () => {
|
||||
await toolbar.openPane('feature-tree')
|
||||
const op = await toolbar.getFeatureTreeOperation('Extrude', 0)
|
||||
await op.dblclick()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'length',
|
||||
currentArgValue: '5',
|
||||
headerArguments: {
|
||||
Length: '5',
|
||||
BidirectionalLength: '10',
|
||||
},
|
||||
highlightedHeaderArg: 'length',
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await page.keyboard.insertText('10')
|
||||
await cmdBar.progressCmdBar()
|
||||
await page.getByRole('button', { name: 'BidirectionalLength' }).click()
|
||||
await cmdBar.expectState({
|
||||
stage: 'arguments',
|
||||
currentArgKey: 'bidirectionalLength',
|
||||
currentArgValue: '10',
|
||||
headerArguments: {
|
||||
Length: '10',
|
||||
BidirectionalLength: '10',
|
||||
},
|
||||
highlightedHeaderArg: 'bidirectionalLength',
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await page.keyboard.insertText('20')
|
||||
await cmdBar.progressCmdBar()
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
Length: '10',
|
||||
BidirectionalLength: '20',
|
||||
},
|
||||
commandName: 'Extrude',
|
||||
})
|
||||
await cmdBar.submit()
|
||||
})
|
||||
|
||||
await test.step('Check that the code has changed again', async () => {
|
||||
await scene.settled(cmdBar)
|
||||
await toolbar.closePane('feature-tree')
|
||||
await toolbar.openPane('code')
|
||||
await editor.expectEditor.toContain(
|
||||
`extrude001 = extrude(profile001, length = 10, bidirectionalLength = 20)`,
|
||||
{ shouldNormalise: true }
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
@ -8,13 +8,10 @@ export const TEST_SETTINGS_KEY = '/settings.toml'
|
||||
export const TEST_SETTINGS: DeepPartial<Settings> = {
|
||||
app: {
|
||||
appearance: {
|
||||
theme: Themes.Light,
|
||||
theme: Themes.Dark,
|
||||
},
|
||||
onboarding_status: 'dismissed',
|
||||
show_debug_panel: true,
|
||||
// Tests were written before this setting existed.
|
||||
// It's true by default because it's a good user experience, but
|
||||
// these tests require it to be false.
|
||||
fixed_size_grid: false,
|
||||
},
|
||||
modeling: {
|
||||
|
@ -880,6 +880,10 @@ export async function setup(
|
||||
},
|
||||
...TEST_SETTINGS.project,
|
||||
onboarding_status: 'dismissed',
|
||||
// Tests were written before this setting existed.
|
||||
// It's true by default because it's a good user experience, but
|
||||
// these tests require it to be false.
|
||||
fixed_size_grid: false,
|
||||
},
|
||||
project: {
|
||||
...TEST_SETTINGS.project,
|
||||
|
18
flake.lock
generated
@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1745998881,
|
||||
"narHash": "sha256-vonyYAKJSlsX4n9GCsS0pHxR6yCrfqBIuGvANlkwG6U=",
|
||||
"lastModified": 1750865895,
|
||||
"narHash": "sha256-p2dWAQcLVzquy9LxYCZPwyUdugw78Qv3ChvnX755qHA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "423d2df5b04b4ee7688c3d71396e872afa236a89",
|
||||
"rev": "61c0f513911459945e2cb8bf333dc849f1b976ff",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -36,11 +36,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1745998881,
|
||||
"narHash": "sha256-vonyYAKJSlsX4n9GCsS0pHxR6yCrfqBIuGvANlkwG6U=",
|
||||
"lastModified": 1750865895,
|
||||
"narHash": "sha256-p2dWAQcLVzquy9LxYCZPwyUdugw78Qv3ChvnX755qHA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "423d2df5b04b4ee7688c3d71396e872afa236a89",
|
||||
"rev": "61c0f513911459945e2cb8bf333dc849f1b976ff",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -78,11 +78,11 @@
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1745980514,
|
||||
"narHash": "sha256-CITAeiuXGjDvT5iZBXr6vKVWQwsUQLJUMFO91bfJFC4=",
|
||||
"lastModified": 1750964660,
|
||||
"narHash": "sha256-YQ6EyFetjH1uy5JhdhRdPe6cuNXlYpMAQePFfZj4W7M=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "7fbdae44b0f40ea432e46fd152ad8be0f8f41ad6",
|
||||
"rev": "04f0fcfb1a50c63529805a798b4b5c21610ff390",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -125,18 +125,57 @@ test('Shows a loading spinner when uninitialized credit count', async () => {
|
||||
await expect(queryByTestId('spinner')).toBeVisible()
|
||||
})
|
||||
|
||||
test('Shows the total credits for Unknown subscription', async () => {
|
||||
const data = {
|
||||
balance: {
|
||||
monthlyApiCreditsRemaining: 10,
|
||||
stableApiCreditsRemaining: 25,
|
||||
},
|
||||
subscriptions: {
|
||||
monthlyPayAsYouGoApiCreditsTotal: 20,
|
||||
name: "unknown",
|
||||
}
|
||||
const unKnownTierData = {
|
||||
balance: {
|
||||
monthlyApiCreditsRemaining: 10,
|
||||
stableApiCreditsRemaining: 25,
|
||||
},
|
||||
subscriptions: {
|
||||
monthlyPayAsYouGoApiCreditsTotal: 20,
|
||||
name: "unknown",
|
||||
}
|
||||
}
|
||||
|
||||
const freeTierData = {
|
||||
balance: {
|
||||
monthlyApiCreditsRemaining: 10,
|
||||
stableApiCreditsRemaining: 0,
|
||||
},
|
||||
subscriptions: {
|
||||
monthlyPayAsYouGoApiCreditsTotal: 20,
|
||||
name: "free",
|
||||
}
|
||||
}
|
||||
|
||||
const proTierData = {
|
||||
// These are all ignored
|
||||
balance: {
|
||||
monthlyApiCreditsRemaining: 10,
|
||||
stableApiCreditsRemaining: 0,
|
||||
},
|
||||
subscriptions: {
|
||||
// This should be ignored because it's Pro tier.
|
||||
monthlyPayAsYouGoApiCreditsTotal: 20,
|
||||
name: "pro",
|
||||
}
|
||||
}
|
||||
|
||||
const enterpriseTierData = {
|
||||
// These are all ignored, user is part of an org.
|
||||
balance: {
|
||||
monthlyApiCreditsRemaining: 10,
|
||||
stableApiCreditsRemaining: 0,
|
||||
},
|
||||
subscriptions: {
|
||||
// This should be ignored because it's Pro tier.
|
||||
monthlyPayAsYouGoApiCreditsTotal: 20,
|
||||
// This should be ignored because the user is part of an Org.
|
||||
name: "free",
|
||||
}
|
||||
}
|
||||
|
||||
test('Shows the total credits for Unknown subscription', async () => {
|
||||
const data = unKnownTierData
|
||||
server.use(
|
||||
http.get('*/user/payment/balance', (req, res, ctx) => {
|
||||
return HttpResponse.json(createUserPaymentBalanceResponse(data.balance))
|
||||
@ -166,17 +205,7 @@ test('Shows the total credits for Unknown subscription', async () => {
|
||||
})
|
||||
|
||||
test('Progress bar reflects ratio left of Free subscription', async () => {
|
||||
const data = {
|
||||
balance: {
|
||||
monthlyApiCreditsRemaining: 10,
|
||||
stableApiCreditsRemaining: 0,
|
||||
},
|
||||
subscriptions: {
|
||||
monthlyPayAsYouGoApiCreditsTotal: 20,
|
||||
name: "free",
|
||||
}
|
||||
}
|
||||
|
||||
const data = freeTierData
|
||||
server.use(
|
||||
http.get('*/user/payment/balance', (req, res, ctx) => {
|
||||
return HttpResponse.json(createUserPaymentBalanceResponse(data.balance))
|
||||
@ -212,19 +241,7 @@ test('Progress bar reflects ratio left of Free subscription', async () => {
|
||||
})
|
||||
})
|
||||
test('Shows infinite credits for Pro subscription', async () => {
|
||||
const data = {
|
||||
// These are all ignored
|
||||
balance: {
|
||||
monthlyApiCreditsRemaining: 10,
|
||||
stableApiCreditsRemaining: 0,
|
||||
},
|
||||
subscriptions: {
|
||||
// This should be ignored because it's Pro tier.
|
||||
monthlyPayAsYouGoApiCreditsTotal: 20,
|
||||
name: "pro",
|
||||
}
|
||||
}
|
||||
|
||||
const data = proTierData
|
||||
server.use(
|
||||
http.get('*/user/payment/balance', (req, res, ctx) => {
|
||||
return HttpResponse.json(createUserPaymentBalanceResponse(data.balance))
|
||||
@ -255,19 +272,7 @@ test('Shows infinite credits for Pro subscription', async () => {
|
||||
await expect(queryByTestId('billing-remaining-progress-bar-inline')).toBe(null)
|
||||
})
|
||||
test('Shows infinite credits for Enterprise subscription', async () => {
|
||||
const data = {
|
||||
// These are all ignored, user is part of an org.
|
||||
balance: {
|
||||
monthlyApiCreditsRemaining: 10,
|
||||
stableApiCreditsRemaining: 0,
|
||||
},
|
||||
subscriptions: {
|
||||
// This should be ignored because it's Pro tier.
|
||||
monthlyPayAsYouGoApiCreditsTotal: 20,
|
||||
// This should be ignored because the user is part of an Org.
|
||||
name: "free",
|
||||
}
|
||||
}
|
||||
const data = enterpriseTierData
|
||||
|
||||
server.use(
|
||||
http.get('*/user/payment/balance', (req, res, ctx) => {
|
||||
@ -297,3 +302,58 @@ test('Shows infinite credits for Enterprise subscription', async () => {
|
||||
await expect(queryByTestId('infinity')).toBeVisible()
|
||||
await expect(queryByTestId('billing-remaining-progress-bar-inline')).toBe(null)
|
||||
})
|
||||
|
||||
test('Show upgrade button if credits are not infinite', async () => {
|
||||
const data = freeTierData
|
||||
server.use(
|
||||
http.get('*/user/payment/balance', (req, res, ctx) => {
|
||||
return HttpResponse.json(createUserPaymentBalanceResponse(data.balance))
|
||||
}),
|
||||
http.get('*/user/payment/subscriptions', (req, res, ctx) => {
|
||||
return HttpResponse.json(createUserPaymentSubscriptionsResponse(data.subscriptions))
|
||||
}),
|
||||
http.get('*/org', (req, res, ctx) => {
|
||||
return new HttpResponse(403)
|
||||
}),
|
||||
)
|
||||
|
||||
const billingActor = createActor(billingMachine, { input: BILLING_CONTEXT_DEFAULTS }).start()
|
||||
|
||||
const { queryByTestId } = render(<BillingDialog
|
||||
billingActor={billingActor}
|
||||
/>)
|
||||
|
||||
await act(() => {
|
||||
billingActor.send({ type: BillingTransition.Update, apiToken: "it doesn't matter wtf this is :)" })
|
||||
})
|
||||
|
||||
await expect(queryByTestId('billing-upgrade-button')).toBeVisible()
|
||||
})
|
||||
|
||||
test('Hide upgrade button if credits are infinite', async () => {
|
||||
const data = enterpriseTierData
|
||||
server.use(
|
||||
http.get('*/user/payment/balance', (req, res, ctx) => {
|
||||
return HttpResponse.json(createUserPaymentBalanceResponse(data.balance))
|
||||
}),
|
||||
http.get('*/user/payment/subscriptions', (req, res, ctx) => {
|
||||
return HttpResponse.json(createUserPaymentSubscriptionsResponse(data.subscriptions))
|
||||
}),
|
||||
// Ok finally the first use of an org lol
|
||||
http.get('*/org', (req, res, ctx) => {
|
||||
return HttpResponse.json(createOrgResponse())
|
||||
}),
|
||||
)
|
||||
|
||||
const billingActor = createActor(billingMachine, { input: BILLING_CONTEXT_DEFAULTS }).start()
|
||||
|
||||
const { queryByTestId } = render(<BillingDialog
|
||||
billingActor={billingActor}
|
||||
/>)
|
||||
|
||||
await act(() => {
|
||||
billingActor.send({ type: BillingTransition.Update, apiToken: "it doesn't matter wtf this is :)" })
|
||||
})
|
||||
|
||||
await expect(queryByTestId('billing-upgrade-button')).toBe(null)
|
||||
})
|
||||
|
1118
package-lock.json
generated
@ -110,8 +110,11 @@
|
||||
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
||||
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
|
||||
"lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
|
||||
"url-checker":"./scripts/url-checker.sh",
|
||||
"url-checker:overwrite":"npm run url-checker > scripts/known/urls.txt",
|
||||
"url-checker:diff":"./scripts/diff-url-checker.sh",
|
||||
"circular-deps": "dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx",
|
||||
"circular-deps:overwrite": "npm run circular-deps | sed '$d' | grep -v '^npm run' > known-circular.txt",
|
||||
"circular-deps:overwrite": "npm run circular-deps | sed '$d' | grep -v '^npm run' > scripts/known/circular.txt",
|
||||
"circular-deps:diff": "./scripts/diff-circular-deps.sh",
|
||||
"circular-deps:diff:nodejs": "npm run circular-deps:diff || node ./scripts/diff.js",
|
||||
"files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
|
||||
|
@ -29,7 +29,7 @@
|
||||
"vscode-uri": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.14.1",
|
||||
"@types/node": "^24.0.7",
|
||||
"ts-node": "^10.9.2"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
153
rust/Cargo.lock
generated
@ -178,7 +178,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -189,7 +189,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -211,7 +211,7 @@ checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -514,7 +514,7 @@ dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -740,7 +740,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -751,7 +751,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -810,7 +810,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -831,7 +831,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -841,7 +841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -906,7 +906,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -944,7 +944,7 @@ checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1119,7 +1119,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1223,7 +1223,7 @@ dependencies = [
|
||||
"inflections",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1599,7 +1599,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1814,7 +1814,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-bumper"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1825,26 +1825,26 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-derive-docs"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kcl-directory-test-macro"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kcl-language-server"
|
||||
version = "0.2.82"
|
||||
version = "0.2.84"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1865,7 +1865,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-language-server-release"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1885,7 +1885,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.2.82"
|
||||
version = "0.2.84"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx 0.5.1",
|
||||
@ -1962,7 +1962,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-python-bindings"
|
||||
version = "0.3.82"
|
||||
version = "0.3.84"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kcl-lib",
|
||||
@ -1977,7 +1977,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-test-server"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hyper 0.14.32",
|
||||
@ -1990,7 +1990,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-to-core"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -2004,7 +2004,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-wasm-lib"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bson",
|
||||
@ -2071,9 +2071,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kittycad-modeling-cmds"
|
||||
version = "0.2.123"
|
||||
version = "0.2.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8f3c1b4b4ddb9aa336a09933f2550f9882552e321187b7bcff47f006379c3aa"
|
||||
checksum = "cfd09d95f8bbeb090d4d1137c9bf421eb75763f7a30e4a9e8eefa249ddf20bd3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@ -2104,7 +2104,7 @@ dependencies = [
|
||||
"kittycad-modeling-cmds-macros-impl",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2115,7 +2115,7 @@ checksum = "fdb4ee23cc996aa2dca7584d410e8826e08161e1ac4335bb646d5ede33f37cb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2311,7 +2311,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2640,7 +2640,7 @@ dependencies = [
|
||||
"regex",
|
||||
"regex-syntax 0.8.5",
|
||||
"structmeta",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2654,7 +2654,7 @@ dependencies = [
|
||||
"regex",
|
||||
"regex-syntax 0.8.5",
|
||||
"structmeta",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2710,7 +2710,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2754,7 +2754,7 @@ dependencies = [
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2809,7 +2809,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2921,7 +2921,7 @@ dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2981,7 +2981,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"pyo3-macros-backend",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2994,7 +2994,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"pyo3-build-config",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3492,7 +3492,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_derive_internals",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3556,7 +3556,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3567,7 +3567,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3591,14 +3591,14 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.8"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
||||
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@ -3815,7 +3815,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"structmeta-derive",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3826,7 +3826,7 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3848,7 +3848,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3891,9 +3891,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.103"
|
||||
version = "2.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8"
|
||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -3917,7 +3917,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3941,7 +3941,7 @@ dependencies = [
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4050,7 +4050,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4061,7 +4061,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4173,7 +4173,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4217,9 +4217,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.22"
|
||||
version = "0.8.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae"
|
||||
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
@ -4238,9 +4238,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.26"
|
||||
version = "0.22.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e"
|
||||
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||
dependencies = [
|
||||
"indexmap 2.9.0",
|
||||
"serde",
|
||||
@ -4341,7 +4341,7 @@ checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4369,7 +4369,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4428,13 +4428,12 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs"
|
||||
version = "10.1.0"
|
||||
version = "11.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e640d9b0964e9d39df633548591090ab92f7a4567bc31d3891af23471a3365c6"
|
||||
checksum = "6ef1b7a6d914a34127ed8e1fa927eb7088903787bcded4fa3eef8f85ee1568be"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"indexmap 2.9.0",
|
||||
"lazy_static",
|
||||
"serde_json",
|
||||
"thiserror 2.0.12",
|
||||
"ts-rs-macros",
|
||||
@ -4444,13 +4443,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs-macros"
|
||||
version = "10.1.0"
|
||||
version = "11.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e9d8656589772eeec2cf7a8264d9cda40fb28b9bc53118ceb9e8c07f8f38730"
|
||||
checksum = "e9d4ed7b4c18cc150a6a0a1e9ea1ecfa688791220781af6e119f9599a8502a0a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
@ -4636,7 +4635,7 @@ dependencies = [
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4707,7 +4706,7 @@ dependencies = [
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -4743,7 +4742,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -4778,7 +4777,7 @@ checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5068,7 +5067,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -5113,7 +5112,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5124,7 +5123,7 @@ checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5144,7 +5143,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@ -5165,7 +5164,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5187,7 +5186,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -36,7 +36,7 @@ dashmap = { version = "6.1.0" }
|
||||
http = "1"
|
||||
indexmap = "2.9.0"
|
||||
kittycad = { version = "0.3.37", default-features = false, features = ["js", "requests"] }
|
||||
kittycad-modeling-cmds = { version = "0.2.123", features = ["ts-rs", "websocket"] }
|
||||
kittycad-modeling-cmds = { version = "0.2.125", features = ["ts-rs", "websocket"] }
|
||||
lazy_static = "1.5.0"
|
||||
miette = "7.6.0"
|
||||
pyo3 = { version = "0.24.2" }
|
||||
@ -60,6 +60,6 @@ lossy_float_literal = "warn"
|
||||
result_large_err = "allow"
|
||||
|
||||
# Example: how to point modeling-app at a different repo (e.g. a branch or a local clone)
|
||||
#[patch.crates-io]
|
||||
#kittycad-modeling-cmds = { path = "../../../modeling-api/modeling-cmds" }
|
||||
#kittycad-modeling-session = { path = "../../../modeling-api/modeling-session" }
|
||||
# [patch.crates-io]
|
||||
# kittycad-modeling-cmds = { path = "../../modeling-api/modeling-cmds/" }
|
||||
# kittycad-modeling-session = { path = "../../modeling-api/modeling-session" }
|
||||
|
@ -8,6 +8,9 @@ lint:
|
||||
# Ensure we can build without extra feature flags.
|
||||
cargo clippy -p kcl-lib --all-targets -- -D warnings
|
||||
|
||||
lint-fix:
|
||||
cargo clippy --workspace --all-targets --all-features --fix
|
||||
|
||||
# Run the stdlib docs generation
|
||||
redo-kcl-stdlib-docs-no-imgs:
|
||||
EXPECTORATE=overwrite {{cnr}} {{kcl_lib_flags}} docs::gen_std_tests::test_generate_stdlib
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
[package]
|
||||
name = "kcl-bumper"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/KittyCAD/modeling-api"
|
||||
rust-version = "1.76"
|
||||
@ -19,7 +19,7 @@ anyhow = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
semver = "1.0.25"
|
||||
serde = { workspace = true }
|
||||
toml_edit = "0.22.26"
|
||||
toml_edit = "0.22.27"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-derive-docs"
|
||||
description = "A tool for generating documentation from Rust derive macros"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
@ -14,7 +14,7 @@ bench = false
|
||||
[dependencies]
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "2.0.103", features = ["full"] }
|
||||
syn = { version = "2.0.104", features = ["full"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -97,8 +97,11 @@ pub const TEST_NAMES: &[&str] = &[
|
||||
"std-offsetPlane-2",
|
||||
"std-offsetPlane-3",
|
||||
"std-offsetPlane-4",
|
||||
"std-sketch-planeOf-0",
|
||||
"std-sketch-circle-0",
|
||||
"std-sketch-circle-1",
|
||||
"std-sketch-rectangle-0",
|
||||
"std-sketch-rectangle-1",
|
||||
"std-sketch-patternTransform2d-0",
|
||||
"std-sketch-revolve-0",
|
||||
"std-sketch-revolve-1",
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-directory-test-macro"
|
||||
description = "A tool for generating tests from a directory of kcl files"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
@ -14,7 +14,7 @@ bench = false
|
||||
convert_case = "0.8.0"
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "2.0.103", features = ["full"] }
|
||||
syn = { version = "2.0.104", features = ["full"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "kcl-language-server-release"
|
||||
version = "0.1.82"
|
||||
version = "0.1.84"
|
||||
edition = "2021"
|
||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||
publish = false
|
||||
|
@ -42,7 +42,7 @@ impl Build {
|
||||
.to_string();
|
||||
|
||||
if !stable {
|
||||
version = format!("{}-nightly", version);
|
||||
version = format!("{version}-nightly");
|
||||
}
|
||||
|
||||
let release_tag = if stable {
|
||||
@ -59,10 +59,7 @@ impl Build {
|
||||
if stable && !release_tag.contains(&version) {
|
||||
// bail early if the tag doesn't match the version
|
||||
// TODO: error here when we use the tags with kcl
|
||||
println!(
|
||||
"Tag {} doesn't match version {}. Did you forget to update Cargo.toml?",
|
||||
release_tag, version
|
||||
);
|
||||
println!("Tag {release_tag} doesn't match version {version}. Did you forget to update Cargo.toml?");
|
||||
}
|
||||
|
||||
build_server(sh, &version, &target)?;
|
||||
|
@ -95,10 +95,10 @@ async fn main() -> Result<()> {
|
||||
// Format fields using the provided closure.
|
||||
// We want to make this very concise otherwise the logs are not able to be read by humans.
|
||||
let format = tracing_subscriber::fmt::format::debug_fn(|writer, field, value| {
|
||||
if format!("{}", field) == "message" {
|
||||
write!(writer, "{}: {:?}", field, value)
|
||||
if format!("{field}") == "message" {
|
||||
write!(writer, "{field}: {value:?}")
|
||||
} else {
|
||||
write!(writer, "{}", field)
|
||||
write!(writer, "{field}")
|
||||
}
|
||||
})
|
||||
// Separate each field with a comma.
|
||||
|
@ -2,7 +2,7 @@
|
||||
name = "kcl-language-server"
|
||||
description = "A language server for KCL."
|
||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||
version = "0.2.82"
|
||||
version = "0.2.84"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
@ -123,7 +123,7 @@
|
||||
"@vscode/test-electron": "^2.4.1",
|
||||
"@vscode/vsce": "^3.3.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"esbuild": "^0.25.2",
|
||||
"esbuild": "^0.25.3",
|
||||
"glob": "^11.0.1",
|
||||
"mocha": "^11.1.0",
|
||||
"typescript": "^5.8.3"
|
||||
|
@ -87,10 +87,10 @@ async fn main() -> Result<()> {
|
||||
// Format fields using the provided closure.
|
||||
// We want to make this very concise otherwise the logs are not able to be read by humans.
|
||||
let format = tracing_subscriber::fmt::format::debug_fn(|writer, field, value| {
|
||||
if format!("{}", field) == "message" {
|
||||
write!(writer, "{}: {:?}", field, value)
|
||||
if format!("{field}") == "message" {
|
||||
write!(writer, "{field}: {value:?}")
|
||||
} else {
|
||||
write!(writer, "{}", field)
|
||||
write!(writer, "{field}")
|
||||
}
|
||||
})
|
||||
// Separate each field with a comma.
|
||||
@ -151,7 +151,7 @@ async fn run_cmd(opts: &Opts) -> Result<()> {
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Some(sig) = signals.forever().next() {
|
||||
log::info!("received signal: {:?}", sig);
|
||||
log::info!("received signal: {sig:?}");
|
||||
log::info!("triggering cleanup...");
|
||||
|
||||
// Exit the process.
|
||||
|
@ -1,11 +1,11 @@
|
||||
[package]
|
||||
name = "kcl-lib"
|
||||
description = "KittyCAD Language implementation and tools"
|
||||
version = "0.2.82"
|
||||
edition = "2021"
|
||||
version = "0.2.84"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
rust-version = "1.83"
|
||||
rust-version = "1.88"
|
||||
authors = ["Jess Frazelle", "Adam Chalmers", "KittyCAD, Inc"]
|
||||
keywords = ["kcl", "KittyCAD", "CAD"]
|
||||
exclude = ["tests/*", "benches/*", "examples/*", "e2e/*", "bindings/*", "fuzz/*"]
|
||||
@ -74,8 +74,8 @@ sha2 = "0.10.9"
|
||||
tabled = { version = "0.20.0", optional = true }
|
||||
tempfile = "3.20"
|
||||
thiserror = "2.0.0"
|
||||
toml = "0.8.22"
|
||||
ts-rs = { version = "10.1.0", features = [
|
||||
toml = "0.8.23"
|
||||
ts-rs = { version = "11.0.1", features = [
|
||||
"uuid-impl",
|
||||
"url-impl",
|
||||
"chrono-impl",
|
||||
|
@ -4,7 +4,7 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
|
||||
const IGNORE_DIRS: [&str; 2] = ["step", "screenshots"];
|
||||
|
||||
@ -61,7 +61,7 @@ fn run_benchmarks(c: &mut Criterion) {
|
||||
|
||||
// Read the file content (panic on failure)
|
||||
let input_content = fs::read_to_string(&input_file)
|
||||
.unwrap_or_else(|e| panic!("Failed to read main.kcl in directory {}: {}", dir_name, e));
|
||||
.unwrap_or_else(|e| panic!("Failed to read main.kcl in directory {dir_name}: {e}"));
|
||||
|
||||
// Create a benchmark group for this directory
|
||||
let mut group = c.benchmark_group(&dir_name);
|
||||
@ -72,12 +72,12 @@ fn run_benchmarks(c: &mut Criterion) {
|
||||
#[cfg(feature = "benchmark-execution")]
|
||||
let program = kcl_lib::Program::parse_no_errs(&input_content).unwrap();
|
||||
|
||||
group.bench_function(format!("parse_{}", dir_name), |b| {
|
||||
group.bench_function(format!("parse_{dir_name}"), |b| {
|
||||
b.iter(|| kcl_lib::Program::parse_no_errs(black_box(&input_content)).unwrap())
|
||||
});
|
||||
|
||||
#[cfg(feature = "benchmark-execution")]
|
||||
group.bench_function(format!("execute_{}", dir_name), |b| {
|
||||
group.bench_function(format!("execute_{dir_name}"), |b| {
|
||||
b.iter(|| {
|
||||
if let Err(err) = rt.block_on(async {
|
||||
let ctx = kcl_lib::ExecutorContext::new_with_default_client().await?;
|
||||
@ -86,7 +86,7 @@ fn run_benchmarks(c: &mut Criterion) {
|
||||
ctx.close().await;
|
||||
Ok::<(), anyhow::Error>(())
|
||||
}) {
|
||||
panic!("Failed to execute program: {}", err);
|
||||
panic!("Failed to execute program: {err}");
|
||||
}
|
||||
})
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::hint::black_box;
|
||||
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
|
||||
pub fn bench_parse(c: &mut Criterion) {
|
||||
for (name, file) in [
|
||||
|
@ -1,4 +1,4 @@
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
|
||||
pub fn bench_digest(c: &mut Criterion) {
|
||||
for (name, file) in [
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::hint::black_box;
|
||||
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
|
||||
use kcl_lib::kcl_lsp_server;
|
||||
use tokio::runtime::Runtime;
|
||||
use tower_lsp::LanguageServer;
|
||||
|
@ -1,9 +1,9 @@
|
||||
//! Cache testing framework.
|
||||
|
||||
use kcl_lib::{bust_cache, ExecError, ExecOutcome};
|
||||
use kcl_lib::{ExecError, ExecOutcome, bust_cache};
|
||||
#[cfg(feature = "artifact-graph")]
|
||||
use kcl_lib::{exec::Operation, NodePathStep};
|
||||
use kcmc::{each_cmd as mcmd, ModelingCmd};
|
||||
use kcl_lib::{NodePathStep, exec::Operation};
|
||||
use kcmc::{ModelingCmd, each_cmd as mcmd};
|
||||
use kittycad_modeling_cmds as kcmc;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
@ -38,7 +38,7 @@ async fn cache_test(
|
||||
if !variation.other_files.is_empty() {
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let tmp_dir = tmp_dir
|
||||
.join(format!("kcl_test_{}", test_name))
|
||||
.join(format!("kcl_test_{test_name}"))
|
||||
.join(uuid::Uuid::new_v4().to_string());
|
||||
|
||||
// Create a temporary file for each of the other files.
|
||||
@ -56,7 +56,7 @@ async fn cache_test(
|
||||
Err(error) => {
|
||||
let report = error.clone().into_miette_report_with_outputs(variation.code).unwrap();
|
||||
let report = miette::Report::new(report);
|
||||
panic!("{:?}", report);
|
||||
panic!("{report:?}");
|
||||
}
|
||||
};
|
||||
|
||||
@ -69,7 +69,7 @@ async fn cache_test(
|
||||
.and_then(|x| x.decode().map_err(|e| ExecError::BadPng(e.to_string())))
|
||||
.unwrap();
|
||||
// Save the snapshot.
|
||||
let path = crate::assert_out(&format!("cache_{}_{}", test_name, index), &img);
|
||||
let path = crate::assert_out(&format!("cache_{test_name}_{index}"), &img);
|
||||
|
||||
img_results.push((path, img, outcome));
|
||||
}
|
||||
@ -337,8 +337,7 @@ extrude001 = extrude(profile001, length = 4)
|
||||
// 0] as a more lenient check.
|
||||
.map(|c| !c.range.is_synthetic() && c.node_path.is_empty())
|
||||
.unwrap_or(false),
|
||||
"artifact={:?}",
|
||||
artifact
|
||||
"artifact={artifact:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
mod cache;
|
||||
|
||||
use kcl_lib::{
|
||||
test_server::{execute_and_export_step, execute_and_snapshot, execute_and_snapshot_no_auth},
|
||||
BacktraceItem, ExecError, ModuleId, SourceRange,
|
||||
test_server::{execute_and_export_step, execute_and_snapshot, execute_and_snapshot_no_auth},
|
||||
};
|
||||
|
||||
/// The minimum permissible difference between asserted twenty-twenty images.
|
||||
@ -869,11 +869,13 @@ async fn kcl_test_revolve_bad_angle_low() {
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
assert!(result
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.contains("Expected angle to be between -360 and 360 and not 0, found `-455`"));
|
||||
assert!(
|
||||
result
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.contains("Expected angle to be between -360 and 360 and not 0, found `-455`")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
@ -895,11 +897,13 @@ async fn kcl_test_revolve_bad_angle_high() {
|
||||
let result = execute_and_snapshot(code, None).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
assert!(result
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.contains("Expected angle to be between -360 and 360 and not 0, found `455`"));
|
||||
assert!(
|
||||
result
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.contains("Expected angle to be between -360 and 360 and not 0, found `455`")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
@ -2090,7 +2094,10 @@ async fn kcl_test_better_type_names() {
|
||||
},
|
||||
None => todo!(),
|
||||
};
|
||||
assert_eq!(err, "This function expected the input argument to be one or more Solids or ImportedGeometry but it's actually of type Sketch. You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`");
|
||||
assert_eq!(
|
||||
err,
|
||||
"This function expected the input argument to be one or more Solids or ImportedGeometry but it's actually of type Sketch. You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 35 KiB |
@ -101,7 +101,7 @@ pub trait CoreDump: Clone {
|
||||
.meta()
|
||||
.create_debug_uploads(vec![kittycad::types::multipart::Attachment {
|
||||
name: "".to_string(),
|
||||
filepath: Some(format!(r#"modeling-app/coredump-{}.json"#, coredump_id).into()),
|
||||
filepath: Some(format!(r#"modeling-app/coredump-{coredump_id}.json"#).into()),
|
||||
content_type: Some("application/json".to_string()),
|
||||
data,
|
||||
}])
|
||||
|
@ -189,7 +189,7 @@ fn generate_example(index: usize, src: &str, props: &ExampleProperties, file_nam
|
||||
index
|
||||
);
|
||||
let image_data =
|
||||
std::fs::read(&image_path).unwrap_or_else(|_| panic!("Failed to read image file: {}", image_path));
|
||||
std::fs::read(&image_path).unwrap_or_else(|_| panic!("Failed to read image file: {image_path}"));
|
||||
base64::engine::general_purpose::STANDARD.encode(&image_data)
|
||||
};
|
||||
|
||||
@ -225,7 +225,7 @@ fn generate_type_from_kcl(ty: &TyData, file_name: String, example_name: String,
|
||||
|
||||
let output = hbs.render("kclType", &data)?;
|
||||
let output = cleanup_types(&output, kcl_std);
|
||||
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", file_name), &output);
|
||||
expectorate::assert_contents(format!("../../docs/kcl-std/{file_name}.md"), &output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -267,7 +267,7 @@ fn generate_mod_from_kcl(m: &ModData, file_name: String) -> Result<()> {
|
||||
});
|
||||
|
||||
let output = hbs.render("module", &data)?;
|
||||
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", file_name), &output);
|
||||
expectorate::assert_contents(format!("../../docs/kcl-std/{file_name}.md"), &output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -334,7 +334,7 @@ fn generate_function_from_kcl(
|
||||
|
||||
let output = hbs.render("function", &data)?;
|
||||
let output = &cleanup_types(&output, kcl_std);
|
||||
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", file_name), output);
|
||||
expectorate::assert_contents(format!("../../docs/kcl-std/{file_name}.md"), output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -378,7 +378,7 @@ fn generate_const_from_kcl(cnst: &ConstData, file_name: String, example_name: St
|
||||
|
||||
let output = hbs.render("const", &data)?;
|
||||
let output = cleanup_types(&output, kcl_std);
|
||||
expectorate::assert_contents(format!("../../docs/kcl-std/{}.md", file_name), &output);
|
||||
expectorate::assert_contents(format!("../../docs/kcl-std/{file_name}.md"), &output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use tower_lsp::lsp_types::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ModuleId,
|
||||
execution::annotations,
|
||||
parsing::{
|
||||
ast::types::{
|
||||
@ -15,7 +16,6 @@ use crate::{
|
||||
},
|
||||
token::NumericSuffix,
|
||||
},
|
||||
ModuleId,
|
||||
};
|
||||
|
||||
pub fn walk_prelude() -> ModData {
|
||||
@ -97,7 +97,7 @@ fn visit_module(name: &str, preferred_prefix: &str, names: WalkForNames) -> Resu
|
||||
ImportSelector::None { .. } => {
|
||||
let name = import.module_name().unwrap();
|
||||
if names.contains(&name) {
|
||||
Some(visit_module(&path[1], &format!("{}::", name), WalkForNames::All)?)
|
||||
Some(visit_module(&path[1], &format!("{name}::"), WalkForNames::All)?)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -451,7 +451,7 @@ impl ModData {
|
||||
let (name, qual_name, module_name) = if name == "prelude" {
|
||||
("std", "std".to_owned(), String::new())
|
||||
} else {
|
||||
(name, format!("std::{}", name), "std".to_owned())
|
||||
(name, format!("std::{name}"), "std".to_owned())
|
||||
};
|
||||
Self {
|
||||
preferred_name: format!("{preferred_prefix}{name}"),
|
||||
@ -767,14 +767,12 @@ impl ArgData {
|
||||
for s in &arr.elements {
|
||||
let Expr::Literal(lit) = s else {
|
||||
panic!(
|
||||
"Invalid value in `snippetArray`, all items must be string literals but found {:?}",
|
||||
s
|
||||
"Invalid value in `snippetArray`, all items must be string literals but found {s:?}"
|
||||
);
|
||||
};
|
||||
let LiteralValue::String(litstr) = &lit.inner.value else {
|
||||
panic!(
|
||||
"Invalid value in `snippetArray`, all items must be string literals but found {:?}",
|
||||
s
|
||||
"Invalid value in `snippetArray`, all items must be string literals but found {s:?}"
|
||||
);
|
||||
};
|
||||
items.push(litstr.to_owned());
|
||||
@ -816,7 +814,7 @@ impl ArgData {
|
||||
}
|
||||
match self.ty.as_deref() {
|
||||
Some("Sketch") if self.kind == ArgKind::Special => None,
|
||||
Some(s) if s.starts_with("number") => Some((index, format!(r#"{label}${{{}:10}}"#, index))),
|
||||
Some(s) if s.starts_with("number") => Some((index, format!(r#"{label}${{{index}:10}}"#))),
|
||||
Some("Point2d") => Some((index + 1, format!(r#"{label}[${{{}:0}}, ${{{}:0}}]"#, index, index + 1))),
|
||||
Some("Point3d") => Some((
|
||||
index + 2,
|
||||
@ -831,7 +829,7 @@ impl ArgData {
|
||||
Some("Sketch") | Some("Sketch | Helix") => Some((index, format!(r#"{label}${{{index}:sketch000}}"#))),
|
||||
Some("Edge") => Some((index, format!(r#"{label}${{{index}:tag_or_edge_fn}}"#))),
|
||||
Some("[Edge; 1+]") => Some((index, format!(r#"{label}[${{{index}:tag_or_edge_fn}}]"#))),
|
||||
Some("Plane") | Some("Solid | Plane") => Some((index, format!(r#"{label}${{{}:XY}}"#, index))),
|
||||
Some("Plane") | Some("Solid | Plane") => Some((index, format!(r#"{label}${{{index}:XY}}"#))),
|
||||
Some("[TaggedFace; 2]") => Some((
|
||||
index + 1,
|
||||
format!(r#"{label}[${{{}:tag}}, ${{{}:tag}}]"#, index, index + 1),
|
||||
@ -841,10 +839,10 @@ impl ArgData {
|
||||
if self.name == "color" {
|
||||
Some((index, format!(r"{label}${{{}:{}}}", index, "\"#ff0000\"")))
|
||||
} else {
|
||||
Some((index, format!(r#"{label}${{{}:"string"}}"#, index)))
|
||||
Some((index, format!(r#"{label}${{{index}:"string"}}"#)))
|
||||
}
|
||||
}
|
||||
Some("bool") => Some((index, format!(r#"{label}${{{}:false}}"#, index))),
|
||||
Some("bool") => Some((index, format!(r#"{label}${{{index}:false}}"#))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -1298,7 +1296,10 @@ mod test {
|
||||
continue;
|
||||
}
|
||||
let name = format!("{}-{i}", f.qual_name.replace("::", "-"));
|
||||
assert!(TEST_NAMES.contains(&&*name), "Missing test for example \"{name}\", maybe need to update kcl-derive-docs/src/example_tests.rs?")
|
||||
assert!(
|
||||
TEST_NAMES.contains(&&*name),
|
||||
"Missing test for example \"{name}\", maybe need to update kcl-derive-docs/src/example_tests.rs?"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1334,7 +1335,9 @@ mod test {
|
||||
};
|
||||
|
||||
let Some(DocData::Fn(d)) = data.children.get(&format!("I:{qualname}")) else {
|
||||
panic!("Could not find data for {NAME} (missing a child entry for {qualname}), maybe need to update kcl-derive-docs/src/example_tests.rs?");
|
||||
panic!(
|
||||
"Could not find data for {NAME} (missing a child entry for {qualname}), maybe need to update kcl-derive-docs/src/example_tests.rs?"
|
||||
);
|
||||
};
|
||||
|
||||
for (i, eg) in d.examples.iter().enumerate() {
|
||||
@ -1362,6 +1365,8 @@ mod test {
|
||||
return;
|
||||
}
|
||||
|
||||
panic!("Could not find data for {NAME} (no example {number}), maybe need to update kcl-derive-docs/src/example_tests.rs?");
|
||||
panic!(
|
||||
"Could not find data for {NAME} (no example {number}), maybe need to update kcl-derive-docs/src/example_tests.rs?"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,11 @@
|
||||
//! tasks.
|
||||
|
||||
use std::sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Arc,
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
use tokio::sync::{mpsc, Notify};
|
||||
use tokio::sync::{Notify, mpsc};
|
||||
|
||||
use crate::errors::KclError;
|
||||
|
||||
|
@ -3,26 +3,26 @@
|
||||
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use anyhow::{Result, anyhow};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use indexmap::IndexMap;
|
||||
use kcmc::{
|
||||
ModelingCmd,
|
||||
websocket::{
|
||||
BatchResponse, FailureWebSocketResponse, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData,
|
||||
SuccessWebSocketResponse, WebSocketRequest, WebSocketResponse,
|
||||
},
|
||||
ModelingCmd,
|
||||
};
|
||||
use kittycad_modeling_cmds::{self as kcmc};
|
||||
use tokio::sync::{mpsc, oneshot, RwLock};
|
||||
use tokio::sync::{RwLock, mpsc, oneshot};
|
||||
use tokio_tungstenite::tungstenite::Message as WsMsg;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
SourceRange,
|
||||
engine::{AsyncTasks, EngineManager, EngineStats},
|
||||
errors::{KclError, KclErrorDetails},
|
||||
execution::{DefaultPlanes, IdGenerator},
|
||||
SourceRange,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -85,7 +85,7 @@ impl TcpRead {
|
||||
let msg = match msg {
|
||||
Ok(msg) => msg,
|
||||
Err(e) if matches!(e, tokio_tungstenite::tungstenite::Error::Protocol(_)) => {
|
||||
return Err(WebSocketReadError::Read(e))
|
||||
return Err(WebSocketReadError::Read(e));
|
||||
}
|
||||
Err(e) => return Err(anyhow::anyhow!("Error reading from engine's WebSocket: {e}").into()),
|
||||
};
|
||||
@ -427,7 +427,7 @@ impl EngineManager for EngineConnection {
|
||||
request_sent: tx,
|
||||
})
|
||||
.await
|
||||
.map_err(|e| KclError::new_engine(KclErrorDetails::new(format!("Failed to send debug: {}", e), vec![])))?;
|
||||
.map_err(|e| KclError::new_engine(KclErrorDetails::new(format!("Failed to send debug: {e}"), vec![])))?;
|
||||
|
||||
let _ = rx.await;
|
||||
Ok(())
|
||||
@ -463,7 +463,7 @@ impl EngineManager for EngineConnection {
|
||||
.await
|
||||
.map_err(|e| {
|
||||
KclError::new_engine(KclErrorDetails::new(
|
||||
format!("Failed to send modeling command: {}", e),
|
||||
format!("Failed to send modeling command: {e}"),
|
||||
vec![source_range],
|
||||
))
|
||||
})?;
|
||||
@ -533,7 +533,7 @@ impl EngineManager for EngineConnection {
|
||||
}
|
||||
|
||||
Err(KclError::new_engine(KclErrorDetails::new(
|
||||
format!("Modeling command timed out `{}`", id),
|
||||
format!("Modeling command timed out `{id}`"),
|
||||
vec![source_range],
|
||||
)))
|
||||
}
|
||||
|
@ -12,16 +12,16 @@ use kcmc::{
|
||||
WebSocketResponse,
|
||||
},
|
||||
};
|
||||
use kittycad_modeling_cmds::{self as kcmc, websocket::ModelingCmdReq, ImportFiles, ModelingCmd};
|
||||
use kittycad_modeling_cmds::{self as kcmc, ImportFiles, ModelingCmd, websocket::ModelingCmdReq};
|
||||
use tokio::sync::RwLock;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
SourceRange,
|
||||
engine::{AsyncTasks, EngineStats},
|
||||
errors::KclError,
|
||||
exec::DefaultPlanes,
|
||||
execution::IdGenerator,
|
||||
SourceRange,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -11,10 +11,10 @@ use uuid::Uuid;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::{
|
||||
SourceRange,
|
||||
engine::{AsyncTasks, EngineStats},
|
||||
errors::{KclError, KclErrorDetails},
|
||||
execution::{DefaultPlanes, IdGenerator},
|
||||
SourceRange,
|
||||
};
|
||||
|
||||
#[wasm_bindgen(module = "/../../src/lang/std/engineConnection.ts")]
|
||||
|
@ -12,15 +12,15 @@ pub mod conn_wasm;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Arc,
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
},
|
||||
};
|
||||
|
||||
pub use async_tasks::AsyncTasks;
|
||||
use indexmap::IndexMap;
|
||||
use kcmc::{
|
||||
each_cmd as mcmd,
|
||||
ModelingCmd, each_cmd as mcmd,
|
||||
length_unit::LengthUnit,
|
||||
ok_response::OkModelingCmdResponse,
|
||||
shared::Color,
|
||||
@ -28,7 +28,6 @@ use kcmc::{
|
||||
BatchResponse, ModelingBatch, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData, WebSocketRequest,
|
||||
WebSocketResponse,
|
||||
},
|
||||
ModelingCmd,
|
||||
};
|
||||
use kittycad_modeling_cmds as kcmc;
|
||||
use parse_display::{Display, FromStr};
|
||||
@ -39,9 +38,9 @@ use uuid::Uuid;
|
||||
use web_time::Instant;
|
||||
|
||||
use crate::{
|
||||
errors::{KclError, KclErrorDetails},
|
||||
execution::{types::UnitLen, DefaultPlanes, IdGenerator, PlaneInfo, Point3d},
|
||||
SourceRange,
|
||||
errors::{KclError, KclErrorDetails},
|
||||
execution::{DefaultPlanes, IdGenerator, PlaneInfo, Point3d, types::UnitLen},
|
||||
};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
@ -291,7 +290,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
// the artifact graph won't care either if its gone since you can't select it
|
||||
// anymore anyways.
|
||||
if let Err(err) = self.async_tasks().join_all().await {
|
||||
crate::log::logln!("Error waiting for async tasks (this is typically fine and just means that an edge became something else): {:?}", err);
|
||||
crate::log::logln!(
|
||||
"Error waiting for async tasks (this is typically fine and just means that an edge became something else): {:?}",
|
||||
err
|
||||
);
|
||||
}
|
||||
|
||||
// Flush the batch to make sure nothing remains.
|
||||
@ -499,7 +501,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
}
|
||||
_ => {
|
||||
return Err(KclError::new_engine(KclErrorDetails::new(
|
||||
format!("The request is not a modeling command: {:?}", req),
|
||||
format!("The request is not a modeling command: {req:?}"),
|
||||
vec![*range],
|
||||
)));
|
||||
}
|
||||
@ -529,7 +531,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
} else {
|
||||
// We should never get here.
|
||||
Err(KclError::new_engine(KclErrorDetails::new(
|
||||
format!("Failed to get batch response: {:?}", response),
|
||||
format!("Failed to get batch response: {response:?}"),
|
||||
vec![source_range],
|
||||
)))
|
||||
}
|
||||
@ -544,7 +546,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
// an error.
|
||||
let source_range = id_to_source_range.get(cmd_id.as_ref()).cloned().ok_or_else(|| {
|
||||
KclError::new_engine(KclErrorDetails::new(
|
||||
format!("Failed to get source range for command ID: {:?}", cmd_id),
|
||||
format!("Failed to get source range for command ID: {cmd_id:?}"),
|
||||
vec![],
|
||||
))
|
||||
})?;
|
||||
@ -554,7 +556,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
self.parse_websocket_response(ws_resp, source_range)
|
||||
}
|
||||
_ => Err(KclError::new_engine(KclErrorDetails::new(
|
||||
format!("The final request is not a modeling command: {:?}", final_req),
|
||||
format!("The final request is not a modeling command: {final_req:?}"),
|
||||
vec![source_range],
|
||||
))),
|
||||
}
|
||||
@ -663,7 +665,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
let info = DEFAULT_PLANE_INFO.get(&name).ok_or_else(|| {
|
||||
// We should never get here.
|
||||
KclError::new_engine(KclErrorDetails::new(
|
||||
format!("Failed to get default plane info for: {:?}", name),
|
||||
format!("Failed to get default plane info for: {name:?}"),
|
||||
vec![source_range],
|
||||
))
|
||||
})?;
|
||||
@ -739,7 +741,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
// Get the source range for the command.
|
||||
let source_range = id_to_source_range.get(cmd_id).cloned().ok_or_else(|| {
|
||||
KclError::new_engine(KclErrorDetails::new(
|
||||
format!("Failed to get source range for command ID: {:?}", cmd_id),
|
||||
format!("Failed to get source range for command ID: {cmd_id:?}"),
|
||||
vec![],
|
||||
))
|
||||
})?;
|
||||
@ -754,7 +756,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
// Return an error that we did not get an error or the response we wanted.
|
||||
// This should never happen but who knows.
|
||||
Err(KclError::new_engine(KclErrorDetails::new(
|
||||
format!("Failed to find response for command ID: {:?}", id),
|
||||
format!("Failed to find response for command ID: {id:?}"),
|
||||
vec![],
|
||||
)))
|
||||
}
|
||||
|
@ -7,11 +7,11 @@ use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
|
||||
#[cfg(feature = "artifact-graph")]
|
||||
use crate::execution::{ArtifactCommand, ArtifactGraph, Operation};
|
||||
use crate::{
|
||||
ModuleId,
|
||||
execution::DefaultPlanes,
|
||||
lsp::IntoDiagnostic,
|
||||
modules::{ModulePath, ModuleSource},
|
||||
source_range::SourceRange,
|
||||
ModuleId,
|
||||
};
|
||||
|
||||
/// How did the KCL execution fail
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use kittycad_modeling_cmds::coord::{System, KITTYCAD, OPENGL, VULKAN};
|
||||
use kittycad_modeling_cmds::coord::{KITTYCAD, OPENGL, System, VULKAN};
|
||||
|
||||
use crate::{
|
||||
KclError, SourceRange,
|
||||
errors::KclErrorDetails,
|
||||
execution::types::{UnitAngle, UnitLen},
|
||||
parsing::ast::types::{Annotation, Expr, LiteralValue, Node, ObjectProperty},
|
||||
KclError, SourceRange,
|
||||
};
|
||||
|
||||
/// Annotations which should cause re-execution if they change.
|
||||
|