Compare commits

..

40 Commits

Author SHA1 Message Date
f418436730 fix: settings should be fixed now. 2025-06-23 14:57:59 -05:00
38c6b07df3 fix: saving off progress 2025-06-23 14:44:58 -05:00
549f845b51 fix: saving off progress 2025-06-23 14:44:24 -05:00
32c9304dac Warn on unused fields, always serialize fixed_size_grid 2025-06-23 14:25:03 -05:00
8a0891e01d Sample changes 2025-06-23 11:10:18 -05:00
d8ed24f463 Update snapshots 2025-06-21 01:19:28 +00:00
0422a18428 Merge branch 'main' into achalmers/grid-scale2 2025-06-20 20:01:36 -05:00
3a9e73d441 Revert "Update snapshots"
This reverts commit 43dd26ccdb.
2025-06-20 16:22:22 -05:00
287d0ef296 Make grid configurable via settings 2025-06-20 16:12:43 -05:00
35b8872678 Chore: clean up duplication of nodeToEdit props (#7553)
pierremtb/adhoc/cleanup-nodetoedit-in-config
2025-06-20 17:04:24 -04:00
2f245fe445 Fix: Lints with non-ASCII characters (#7554)
Non-ASCII characters in KCL source code would be displayed wrong, causing weird visuals or at worst, exceptions.

Before:
<img width="449" alt="Screenshot 2025-06-20 at 2 02 23 PM" src="https://github.com/user-attachments/assets/ecd7eef5-de2c-4176-b83e-6c631d081503" />

After:
<img width="459" alt="Screenshot 2025-06-20 at 2 34 10 PM" src="https://github.com/user-attachments/assets/fba2818e-1536-4482-ae09-7bc5b1754581" />
2025-06-20 20:03:00 +00:00
4b95980e9e Set CurrentValue arg to hidden (#7552)
We changed the way `hidden`ness is determined in #7506. Fixes #7551 by
making this one oddball command arg use that new explicit way.
2025-06-20 19:07:05 +00:00
53d6613d0d UTF-8 vs UTF-16 mismatch in KCL diagnostic SourceRanges (#7537)
# Background

The KCL interpreter (written in Rust) reports errors, lints and other diagnostics as UTF-8 source range offsets. JavaScript, including CodeMirror, represents source code as UTF-16 strings. 

# Problem

This means the UTF-8 source ranges sent from Rust don't correspond to the same text in the JS UTF-16 GUI. At best, this means the source ranges highlight the wrong thing if you use non-ASCII characters. At worst, it can cause exceptions by trying to highlight a range that doesn't even exist.

Here's the problem, on main: 

<img width="178" alt="Screenshot 2025-06-20 at 11 52 03 AM" src="https://github.com/user-attachments/assets/9a4e75bf-965f-49d8-b238-8868b35912a1" />

# Solution

We define a KCL SourceRange as _always_ being UTF-8. This means if a source range is constructed in JS, it should be converted to UTF-8. When these ranges are converted into CodeMirror diagnostics, they should be converted to UTF-16.

Here's the same code as above, but on this branch:

<img width="170" alt="Screenshot 2025-06-20 at 11 50 55 AM" src="https://github.com/user-attachments/assets/a5b971c0-0b02-4acd-8fcf-5a133331682b" />

Closes https://github.com/KittyCAD/modeling-app/issues/4327
2025-06-20 19:04:49 +00:00
416d0b37a2 Proper command bar UI support for optional args (#7506)
* WIP: Add bidirectional args to point-and-click Extrude
Will eventually close #7495

* Wire up edit flow for symmetric

* Show skip true args in header in review phase

* Add bidirectionalLength

* Make currentArg always part of header

* WIP

* Add twistAng

* Proper optional args line in review

* Labels in progress button and option arg section heading

* Clean up extrude specific changes

* More UI polish

* Remove options bool icon

* Fix labels for tests

* Upgrade e2e tests to cmdBar fixtures with fixes

* More fixes

* Fixed up more tests related to sweep behavior change

* Fix nodeToEdit not having hidden: true on Shell

* Add typecheck

* WIP: footer buttons

* back to reg width

* Clean up

* Clean up

* Fix tests and remove label

* Refactor

* Fix offset plane test

* Add CommandBarDivider

* Fix step back

* Add comment

* Fix it, thanks bot

* Clean up and inline optional heading

* Little case tweak

* Update src/components/CommandBar/CommandBarReview.tsx

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>

* Rename to CommandBarHeaderFooter

---------

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
2025-06-20 16:05:20 +00:00
bc136c302c Configurable grid 2025-06-20 10:46:18 -05:00
5f2a10ec7e docs: Add better docs for tolerance parameter (#7548)
* Add better docs for tolerance parameter

* Update generated docs
2025-06-20 11:42:14 -04:00
24edb66b3c WIP: #7249 Convert new variable name to camelCase automatically (#7546)
convert new variable name to camelcase automatically
2025-06-20 07:45:24 -04:00
903ba33c46 Make the Playwright API reporter more generic (#7534) 2025-06-19 20:19:53 -04:00
c5bf6ad42d Add ellipsis to match the other Loading components (#7526) 2025-06-20 00:09:25 +00:00
eeaa71142a Convert units of tolerance for CSG functions (#7540)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-06-20 07:14:30 +12:00
0d1fc1b513 Fix network machines indicator alignment (#7535)
* Fix network machines indicator alignment
By integrating it better with the new API

* Update snapshots

* Update snapshots

* Add networkMachineStatus only behind isDesktop

* Update snapshots

* Small cleanup

* Fix test-id

* Update snapshots

* Lint

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-19 16:48:09 +00:00
d510e58ebc Point staging version link to corresponding commit on GitHub (#7529)
* Add the 'Download the app' button back on web
Fixes #7527

* Fix staging release link in desktop app
Fixes #7513

* Update snapshots

* Update snapshots

* Update snapshots

* Add ref parsing logic and unit test

* Oops

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-19 11:30:28 -04:00
23a01e86e6 Add edit flow for Parameters to Feature Tree (#7536)
* Add edit flow to named parameters, show their value in feature tree

* Amend a feature tree test to include editing a parameter

* Enforce disallowing "create new variable" in edit parameter flow

* Add wrapping behavior! Sorry forgot to commit this

* Update src/machines/commandBarMachine.ts

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>

---------

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
2025-06-19 11:14:37 -04:00
9dd6e3e852 KCL: Support non-ASCII identifiers (#7525)
Both human and LLMs want to write KCL code in non-English languages. This is important and we should support it.

Note that errors are currently a bit broken with non-ASCII identifiers, see #4327
2025-06-19 14:10:21 +00:00
9eaacc2a51 KCL: involuteCircular can use diameter in addition to radius (#7519)
Mechanical engineers prefer using diameter over radius.
2025-06-19 14:09:24 +00:00
de6e0f6b18 Add the 'Download the app' button back on web (#7528)
* Add the 'Download the app' button back on web
Fixes #7527

* Update snapshots

* Update snapshots

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-19 12:56:37 +00:00
d02a9f59ae #6629 Make undo redo work without code pane being open (#7511)
* move useHotkey for undo/redo into App

* _editorView should be private

* get editorView should be a real get method for consistency

* resolve tsc errors

* fmt

* setView, setState are not exposed

* make undo work without editorview when kcl pane is closed

* lint

* circular deps

* resolve circular deps

* fix undo being 1 step late

* unrelated console.warn removed

* fix undo when code pane is closed during editing

* cleanup

* allow undo to get beyond when code editor has been mounted

* fix up clearHistory

* add test for testing  Undo with closed code pane
2025-06-19 11:26:51 +00:00
92f930dfc0 Improve release template regarding updater checks (#7532)
* Improve release template regarding updater checks

* Break it up and change update label
2025-06-19 09:32:22 +00:00
e651e0c2cf load wasm from custom port (#7514)
* load wasm from custom port

* Jon's suggestion
2025-06-19 09:20:01 +00:00
6358eed7e4 Release KCL 82 (#7531) 2025-06-19 01:03:13 +00:00
fe581ff1d2 Replace lower-right controls with a full status bar (#7443)
* Resurrect this branch with an initial commit

* Add telemetry to global default items

* Add credit progress bar to status bar

* Add selection info to status bar

* Add help menu to "local" side

* Rename statusBarItem utils

* Delete LowerRightControls, now unused

* fix lints

* Update snapshots

* Add test-id to network health indicator, which all E2E tests rely on

* Update src/components/StatusBar/StatusBar.tsx

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>

* Fix a couple little issues with the e2e tests

* Fix gizmo e2e tests (it moved) and network health test (it should not be on home page)

* More tweaks to accomodate changes to network health indicator

We made use of two test ID's to make Playwright aware of the state, one
of which was on the icon. Now that we want to normalize usage of the
status bar along a more limited API, that became a not possible. This
just tweaks some test code that relied on that fact.

* Fix lints

* Update snapshots

* Re-run CI

* Update snapshots

* Update snapshots

* Test fixes, label logic tweaks

* Update snapshots

* Update snapshots

* Fix up last few tests hopefully. Relative path syntax failed on windows

* Relative paths are behaving badly on Windows, use the old code here

* Update snapshots

* Update snapshots

* Tweak y-value to work on all platforms, ubuntu didn't like 438

* Fix tooltip and popover alignment on NetworkMachineIndicator

* Remove dire warning comment

* Update src/components/StatusBar/defaultStatusBarItems.tsx

Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>

* @lee-at-zoo-corp feedback, pull hooks out of UI code

* Re-run CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
2025-06-17 20:29:27 +00:00
b301fbba22 KCL: Remove stale extrudeTwist docs (#7503)
Thanks Greg
2025-06-17 18:39:34 +00:00
0c702e4bab Use nightly rustfmt in CI (#7509)
* Use nightly rustfmt in CI

* Fix current code to be nightly formatted
2025-06-17 18:30:33 +00:00
cd3b850a92 Merge branch 'main' into achalmers/grid-scale2 2025-06-16 14:06:27 -05:00
4267abc22f Change magic scale factor 2025-06-16 13:21:16 -05:00
21dffcd2de Regenerate snapshots 2025-06-16 13:21:15 -05:00
43dd26ccdb Update snapshots 2025-06-16 11:51:04 -05:00
4b9f1aa180 Update snapshots 2025-06-16 11:51:03 -05:00
310f40883b correct zoom scale factor 2025-06-16 11:51:03 -05:00
8fbdab8a94 Grid scale proportional to user's units
The grid lines should be 1 unit apart, where the unit is whatever the
user's defaultUnitLength setting is, e.g. 1mm or 1cm or 1in apart.
2025-06-16 11:51:02 -05:00
269 changed files with 2473 additions and 1181 deletions

View File

@ -9,6 +9,7 @@ VITE_KC_SITE_BASE_URL=https://dev.zoo.dev
VITE_KC_SITE_APP_URL=https://app.dev.zoo.dev
VITE_KC_SKIP_AUTH=false
VITE_KC_CONNECTION_TIMEOUT_MS=5000
#VITE_WASM_URL="optional way of overriding the wasm url, particular for unit tests which need this if you running not on the default 3000 port"
#VITE_KC_DEV_TOKEN="optional token to skip auth in the app"
#token="required token for playwright. TODO: clean up env vars in #3973"

View File

@ -2,7 +2,7 @@
name: Release
about: Create a new release for the Zoo Design Studio
title: "Cut release v1.?.?"
labels: [release]
labels: [meta/release]
---
> Instructions: https://github.com/KittyCAD/modeling-app/blob/main/CONTRIBUTING.md#shipping-releases
@ -19,7 +19,8 @@ Release builds URL: ???
* [ ] Confirm the application opens (dismiss the updater)
* [ ] Create a project with a basic Text-to-CAD prompt
* [ ] Confirm the result is viewable in an engine stream
* [ ] Open the application again and confirm the updater can downgrade
* [ ] Use 'Check for updates' to bring back the updater toast
* [ ] Confirm the app can update to the previous release
## macOS via ???
@ -27,7 +28,8 @@ Release builds URL: ???
* [ ] Confirm the application opens (dismiss the updater)
* [ ] Create a project with a basic Text-to-CAD prompt
* [ ] Confirm the result is viewable in an engine stream
* [ ] Open the application again and confirm the updater can downgrade
* [ ] Use 'Check for updates' to bring back the updater toast
* [ ] Confirm the app can update to the previous release
## Linux via ???
@ -35,4 +37,5 @@ Release builds URL: ???
* [ ] Confirm the application opens (dismiss the updater)
* [ ] Create a project with a basic Text-to-CAD prompt
* [ ] Confirm the result is viewable in an engine stream
* [ ] Open the application again and confirm the updater can downgrade
* [ ] Use 'Check for updates' to bring back the updater toast
* [ ] Confirm the app can update to the previous release

View File

@ -31,15 +31,15 @@ jobs:
- name: Use correct Rust toolchain
shell: bash
run: |
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
cp .github/workflows/nightly-rust-toolchain.toml rust-toolchain.toml
- name: Install rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache-workspaces: rust
components: rustfmt
- name: Run cargo fmt
- name: Run nightly cargo fmt
run: |
cd rust
cargo fmt -- --check
cargo +nightly fmt -- --check
shell: bash

View File

@ -0,0 +1,3 @@
[toolchain]
channel = "nightly"
components = ["rustfmt"]

File diff suppressed because one or more lines are too long

View File

@ -10,9 +10,11 @@ Extend the current sketch with a new involute circular curve.
```kcl
involuteCircular(
@sketch: Sketch,
startRadius: number(Length),
endRadius: number(Length),
angle: number(Angle),
startRadius?: number(Length),
endRadius?: number(Length),
startDiameter?: number(Length),
endDiameter?: number(Length),
reverse?: bool,
tag?: TagDecl,
): Sketch
@ -25,9 +27,11 @@ involuteCircular(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
| `startRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, start_radius is the radius of the inner circle. | Yes |
| `endRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, end_radius is the radius of the outer circle. | Yes |
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | The angle to rotate the involute by. A value of zero will produce a curve with a tangent along the x-axis at the start point of the curve. | Yes |
| `startRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, startRadius is the radius of the inner circle. Either `startRadius` or `startDiameter` must be given (but not both). | No |
| `endRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, endRadius is the radius of the outer circle. Either `endRadius` or `endDiameter` must be given (but not both). | No |
| `startDiameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, startDiameter describes the inner circle. Either `startRadius` or `startDiameter` must be given (but not both). | No |
| `endDiameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, endDiameter describes the outer circle. Either `endRadius` or `endDiameter` must be given (but not both). | No |
| `reverse` | [`bool`](/docs/kcl-std/types/std-types-bool) | If reverse is true, the segment will start from the end of the involute, otherwise it will start from that start. | No |
| `tag` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | Create a new tag which refers to this line. | No |

View File

@ -29,7 +29,7 @@ The sketches need to be closed and on different planes that are parallel.
| `vDegree` | [`number(_)`](/docs/kcl-std/types/std-types-number) | Degree of the interpolation. Must be greater than zero. For example, use 2 for quadratic, or 3 for cubic interpolation in the V direction. | No |
| `bezApproximateRational` | [`bool`](/docs/kcl-std/types/std-types-bool) | Attempt to approximate rational curves (such as arcs) using a bezier. This will remove banding around interpolations between arcs and non-arcs. It may produce errors in other scenarios. Over time, this field won't be necessary. | No |
| `baseCurveIndex` | [`number(_)`](/docs/kcl-std/types/std-types-number) | This can be set to override the automatically determined topological base curve, which is usually the first section encountered. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Tolerance for the loft operation. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
| `tagStart` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | A named tag for the face at the start of the loft, i.e. the original sketch. | No |
| `tagEnd` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | A named tag for the face at the end of the loft. | No |

View File

@ -38,7 +38,7 @@ revolved around the same axis.
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | The sketch or set of sketches that should be revolved | Yes |
| `axis` | [`Axis2d`](/docs/kcl-std/types/std-types-Axis2d) or [`Edge`](/docs/kcl-std/types/std-types-Edge) | Axis of revolution. | Yes |
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Angle to revolve (in degrees). Default is 360. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Tolerance for the revolve operation. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
| `symmetric` | [`bool`](/docs/kcl-std/types/std-types-bool) | If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch. | No |
| `bidirectionalAngle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | If specified, will also revolve in the opposite direction to 'angle' to the specified angle. If 'symmetric' is true, this value is ignored. | No |
| `tagStart` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | A named tag for the face at the start of the revolve, i.e. the original sketch. | No |

View File

@ -35,7 +35,7 @@ swept along the same path.
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | The sketch or set of sketches that should be swept in space. | Yes |
| `path` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Helix`](/docs/kcl-std/types/std-types-Helix) | The path to sweep the sketch along. | Yes |
| `sectional` | [`bool`](/docs/kcl-std/types/std-types-bool) | If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Tolerance for this operation. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
| `relativeTo` | [`string`](/docs/kcl-std/types/std-types-string) | What is the sweep relative to? Can be either 'sketchPlane' or 'trajectoryCurve'. | No |
| `tagStart` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | A named tag for the face at the start of the sweep, i.e. the original sketch. | No |
| `tagEnd` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | A named tag for the face at the end of the sweep. | No |

View File

@ -28,7 +28,7 @@ will smoothly blend the transition.
| `solid` | [`Solid`](/docs/kcl-std/types/std-types-Solid) | The solid whose edges should be filletted | Yes |
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The radius of the fillet | Yes |
| `tags` | [`[Edge; 1+]`](/docs/kcl-std/types/std-types-Edge) | The paths you want to fillet | Yes |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance for this fillet | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
| `tag` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | Create a new tag which refers to this fillet | No |
### Returns

View File

@ -24,7 +24,7 @@ verifying fit, and analyzing overlapping geometries in assemblies.
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `solids` | `[Solid; 2+]` | The solids to intersect. | Yes |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the intersection operation. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
### Returns

View File

@ -27,7 +27,7 @@ and complex multi-body part modeling.
|----------|------|-------------|----------|
| `solids` | [`[Solid; 1+]`](/docs/kcl-std/types/std-types-Solid) | The solids to use as the base to subtract from. | Yes |
| `tools` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) | The solids to subtract. | Yes |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the subtraction operation. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
### Returns

View File

@ -21,7 +21,7 @@ union(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `solids` | `[Solid; 2+]` | The solids to union. | Yes |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the union operation. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
### Returns

View File

@ -9,6 +9,7 @@ import {
TEST_COLORS,
commonPoints,
getUtils,
enableConsoleLogEverything,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
@ -178,7 +179,9 @@ test.describe('Basic sketch', () => {
cmdBar,
scene,
editor,
tronApp,
}) => {
enableConsoleLogEverything({ page, tronApp })
await doBasicSketch(page, ['code'], { cmdBar, scene, homePage, editor })
})

View File

@ -307,7 +307,7 @@ test.describe('Command bar tests', () => {
)
const continueButton = page.getByRole('button', { name: 'Continue' })
const submitButton = page.getByRole('button', { name: 'Submit command' })
const submitButton = page.getByTestId('command-bar-submit')
await continueButton.click()
// Review step and argument hotkeys

View File

@ -54,9 +54,7 @@ test(
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.keyboard.press('Enter')
await cmdBar.submit()
// Expect it to succeed
const errorToastMessage = page.getByText(`Error while exporting`)
@ -119,9 +117,7 @@ test(
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.keyboard.press('Enter')
await cmdBar.submit()
// Look out for the toast message
const exportingToastMessage = page.getByText(`Exporting...`)

View File

@ -229,11 +229,12 @@ test.describe('Feature Tree pane', () => {
const initialCode = `sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 5)
renamedExtrude = extrude(sketch001, length = ${initialInput})`
const newConstantName = 'length001'
const expectedCode = `${newConstantName} = 23
const newParameterName = 'length001'
const expectedCode = `${newParameterName} = 23
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 5)
renamedExtrude = extrude(sketch001, length = ${newConstantName})`
renamedExtrude = extrude(sketch001, length = ${newParameterName})`
const editedParameterValue = '23 * 2'
await context.folderSetupFn(async (dir) => {
const testDir = join(dir, 'test-sample')
@ -279,7 +280,7 @@ test.describe('Feature Tree pane', () => {
})
})
await test.step('Add a named constant for distance argument and submit', async () => {
await test.step('Add a parameter for distance argument and submit', async () => {
await expect(cmdBar.currentArgumentInput).toBeVisible()
await cmdBar.variableCheckbox.click()
await cmdBar.progressCmdBar()
@ -296,13 +297,43 @@ test.describe('Feature Tree pane', () => {
highlightedCode: '',
diagnostics: [],
activeLines: [
`renamedExtrude = extrude(sketch001, length = ${newConstantName})`,
`renamedExtrude = extrude(sketch001, length = ${newParameterName})`,
],
})
await editor.expectEditor.toContain(expectedCode, {
shouldNormalise: true,
})
})
await test.step('Edit the parameter via the feature tree', async () => {
const parameter = await toolbar.getFeatureTreeOperation('Parameter', 0)
await parameter.dblclick()
await cmdBar.expectState({
commandName: 'Edit parameter',
currentArgKey: 'value',
currentArgValue: '23',
headerArguments: {
Name: newParameterName,
Value: '23',
},
stage: 'arguments',
highlightedHeaderArg: 'value',
})
await cmdBar.argumentInput
.locator('[contenteditable]')
.fill(editedParameterValue)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
commandName: 'Edit parameter',
headerArguments: {
Name: newParameterName,
Value: '46', // Shows calculated result
},
})
await cmdBar.progressCmdBar()
await editor.expectEditor.toContain(editedParameterValue)
})
})
test(`User can edit an offset plane operation from the feature tree`, async ({
context,

View File

@ -118,15 +118,11 @@ export class CmdBarFixture {
return
}
const arrowButton = this.page.getByRole('button', {
name: 'arrow right Continue',
})
const arrowButton = this.page.getByTestId('command-bar-continue')
if (await arrowButton.isVisible()) {
await arrowButton.click()
await this.continue()
} else {
await this.page
.getByRole('button', { name: 'checkmark Submit command' })
.click()
await this.submit()
}
}

View File

@ -5,7 +5,7 @@ import type {
FullResult,
} from '@playwright/test/reporter'
class MyAPIReporter implements Reporter {
class APIReporter implements Reporter {
private pendingRequests: Promise<void>[] = []
private allResults: Record<string, any>[] = []
private blockingResults: Record<string, any>[] = []
@ -32,7 +32,7 @@ class MyAPIReporter implements Reporter {
'X-API-Key': process.env.TAB_API_KEY || '',
}),
body: JSON.stringify({
project: 'https://github.com/KittyCAD/modeling-app',
project: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}`,
branch:
process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
@ -60,7 +60,7 @@ class MyAPIReporter implements Reporter {
const payload = {
// Required information
project: 'https://github.com/KittyCAD/modeling-app',
project: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}`,
suite: process.env.CI_SUITE || 'e2e',
branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
@ -124,4 +124,4 @@ class MyAPIReporter implements Reporter {
}
}
export default MyAPIReporter
export default APIReporter

View File

@ -1083,14 +1083,13 @@ openSketch = startSketchOn(XY)
cmdBar,
}) => {
// One dumb hardcoded screen pixel value
const testPoint = { x: 700, y: 150 }
const testPoint = { x: 700, y: 200 }
// TODO: replace the testPoint selection with a feature tree click once that's supported #7544
const [clickOnXzPlane] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
const expectedOutput = `plane001 = offsetPlane(XZ, offset = 5)`
await homePage.goToModelingScene()
// FIXME: Since there is no KCL code loaded. We need to wait for the scene to load before we continue.
// The engine may not be connected
await page.waitForTimeout(15000)
await scene.settled(cmdBar)
await test.step(`Look for the blue of the XZ plane`, async () => {
//await scene.expectPixelColor([50, 51, 96], testPoint, 15) // FIXME
@ -1829,7 +1828,6 @@ profile002 = startProfile(sketch002, at = [0, 0])
currentArgKey: 'sketches',
currentArgValue: '',
headerArguments: {
Sectional: '',
Profiles: '',
Path: '',
},
@ -1843,7 +1841,6 @@ profile002 = startProfile(sketch002, at = [0, 0])
currentArgKey: 'path',
currentArgValue: '',
headerArguments: {
Sectional: '',
Profiles: '1 profile',
Path: '',
},
@ -1856,7 +1853,6 @@ profile002 = startProfile(sketch002, at = [0, 0])
currentArgKey: 'path',
currentArgValue: '',
headerArguments: {
Sectional: '',
Profiles: '1 profile',
Path: '',
},
@ -1869,7 +1865,6 @@ profile002 = startProfile(sketch002, at = [0, 0])
headerArguments: {
Profiles: '1 profile',
Path: '1 segment',
Sectional: '',
},
stage: 'review',
})
@ -1894,6 +1889,9 @@ profile002 = startProfile(sketch002, at = [0, 0])
0
)
await operationButton.dblclick({ button: 'left' })
await page
.getByRole('button', { name: 'sectional', exact: false })
.click()
await cmdBar.expectState({
commandName: 'Sweep',
currentArgKey: 'sectional',
@ -1971,7 +1969,6 @@ profile001 = ${circleCode}`
currentArgKey: 'sketches',
currentArgValue: '',
headerArguments: {
Sectional: '',
Profiles: '',
Path: '',
},
@ -1986,7 +1983,6 @@ profile001 = ${circleCode}`
currentArgKey: 'path',
currentArgValue: '',
headerArguments: {
Sectional: '',
Profiles: '1 profile',
Path: '',
},
@ -2000,7 +1996,6 @@ profile001 = ${circleCode}`
currentArgKey: 'path',
currentArgValue: '',
headerArguments: {
Sectional: '',
Profiles: '1 profile',
Path: '',
},
@ -2013,7 +2008,6 @@ profile001 = ${circleCode}`
headerArguments: {
Profiles: '1 profile',
Path: '1 helix',
Sectional: '',
},
stage: 'review',
})
@ -4734,7 +4728,6 @@ path001 = startProfile(sketch001, at = [0, 0])
headerArguments: {
Profiles: '',
Path: '',
Sectional: '',
},
highlightedHeaderArg: 'Profiles',
commandName: 'Sweep',
@ -4747,7 +4740,6 @@ path001 = startProfile(sketch001, at = [0, 0])
headerArguments: {
Profiles: '2 profiles',
Path: '',
Sectional: '',
},
highlightedHeaderArg: 'path',
commandName: 'Sweep',
@ -4760,7 +4752,6 @@ path001 = startProfile(sketch001, at = [0, 0])
headerArguments: {
Profiles: '2 profiles',
Path: '1 segment',
Sectional: '',
},
commandName: 'Sweep',
})

View File

@ -475,6 +475,7 @@ test.describe('Can export from electron app', () => {
},
tronApp.projectDirName,
page,
cmdBar,
method
)
)
@ -779,9 +780,6 @@ test.describe(`Project management commands`, () => {
const commandContinueButton = page.getByRole('button', {
name: 'Continue',
})
const commandSubmitButton = page.getByRole('button', {
name: 'Submit command',
})
const toastMessage = page.getByText(`Successfully renamed`)
await test.step(`Setup`, async () => {
@ -800,8 +798,7 @@ test.describe(`Project management commands`, () => {
await expect(commandContinueButton).toBeVisible()
await commandContinueButton.click()
await expect(commandSubmitButton).toBeVisible()
await commandSubmitButton.click()
await cmdBar.submit()
await expect(toastMessage).toBeVisible()
})
@ -837,9 +834,6 @@ test.describe(`Project management commands`, () => {
})
const projectNameOption = page.getByRole('option', { name: projectName })
const commandWarning = page.getByText('Are you sure you want to delete?')
const commandSubmitButton = page.getByRole('button', {
name: 'Submit command',
})
const toastMessage = page.getByText(`Successfully deleted`)
const noProjectsMessage = page.getByText('No projects found')
@ -859,8 +853,7 @@ test.describe(`Project management commands`, () => {
await projectNameOption.click()
await expect(commandWarning).toBeVisible()
await expect(commandSubmitButton).toBeVisible()
await commandSubmitButton.click()
await cmdBar.submit()
await expect(toastMessage).toBeVisible()
})
@ -894,9 +887,6 @@ test.describe(`Project management commands`, () => {
const commandContinueButton = page.getByRole('button', {
name: 'Continue',
})
const commandSubmitButton = page.getByRole('button', {
name: 'Submit command',
})
const toastMessage = page.getByText(`Successfully renamed`)
await test.step(`Setup`, async () => {
@ -914,8 +904,7 @@ test.describe(`Project management commands`, () => {
await expect(commandContinueButton).toBeVisible()
await commandContinueButton.click()
await expect(commandSubmitButton).toBeVisible()
await commandSubmitButton.click()
await cmdBar.submit()
await expect(toastMessage).toBeVisible()
})
@ -949,9 +938,6 @@ test.describe(`Project management commands`, () => {
})
const projectNameOption = page.getByRole('option', { name: projectName })
const commandWarning = page.getByText('Are you sure you want to delete?')
const commandSubmitButton = page.getByRole('button', {
name: 'Submit command',
})
const toastMessage = page.getByText(`Successfully deleted`)
const noProjectsMessage = page.getByText('No projects found')
@ -967,8 +953,7 @@ test.describe(`Project management commands`, () => {
await projectNameOption.click()
await expect(commandWarning).toBeVisible()
await expect(commandSubmitButton).toBeVisible()
await commandSubmitButton.click()
await cmdBar.submit()
await expect(toastMessage).toBeVisible()
})

View File

@ -1,6 +1,7 @@
import path from 'path'
import { bracket } from '@e2e/playwright/fixtures/bracket'
import type { Page } from '@playwright/test'
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import { reportRejection } from '@src/lib/trap'
import * as fsp from 'fs/promises'
@ -421,10 +422,7 @@ extrude002 = extrude(profile002, length = 150)
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.keyboard.press('Enter')
await cmdBar.submit()
// Find the toast.
// Look out for the toast message
@ -461,8 +459,7 @@ extrude002 = extrude(profile002, length = 150)
await page.keyboard.press('Enter')
// Click the checkbox
await expect(submitButton).toBeVisible()
await page.keyboard.press('Enter')
await cmdBar.submit()
// Find the toast.
// Look out for the toast message
@ -482,6 +479,7 @@ extrude002 = extrude(profile002, length = 150)
test('ensure you CAN export while an export is already going', async ({
page,
homePage,
cmdBar,
}) => {
const u = await getUtils(page)
await test.step('Set up the code and durations', async () => {
@ -516,11 +514,11 @@ extrude002 = extrude(profile002, length = 150)
const successToastMessage = page.getByText(`Exported successfully`)
await test.step('second export', async () => {
await clickExportButton(page)
await clickExportButton(page, cmdBar)
await expect(exportingToastMessage).toBeVisible()
await clickExportButton(page)
await clickExportButton(page, cmdBar)
await test.step('The first export still succeeds', async () => {
await Promise.all([
@ -537,7 +535,7 @@ extrude002 = extrude(profile002, length = 150)
await test.step('Successful, unblocked export', async () => {
// Try exporting again.
await clickExportButton(page)
await clickExportButton(page, cmdBar)
// Find the toast.
// Look out for the toast message
@ -575,7 +573,7 @@ extrude002 = extrude(profile002, length = 150)
name: 'Projects',
})
const projectLink = page.getByRole('link', { name: 'bracket' })
const networkHealthIndicator = page.getByTestId('network-toggle')
const networkHealthIndicator = page.getByTestId(/network-toggle/)
await test.step('Check the home page', async () => {
await expect(projectsHeading).toBeVisible()
@ -880,7 +878,7 @@ s2 = startSketchOn(XY)
})
})
async function clickExportButton(page: Page) {
async function clickExportButton(page: Page, cmdBar: CmdBarFixture) {
await test.step('Running export flow', async () => {
// export the model
const exportButton = page.getByTestId('export-pane-button')
@ -896,9 +894,6 @@ async function clickExportButton(page: Page) {
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.keyboard.press('Enter')
await cmdBar.submit()
})
}

View File

@ -1478,6 +1478,7 @@ sketch001 = startSketchOn(XZ)
await page.mouse.move(1200, 139)
await page.mouse.down()
await page.mouse.move(870, 250)
await page.mouse.up()
await page.waitForTimeout(200)
@ -1487,6 +1488,60 @@ sketch001 = startSketchOn(XZ)
)
})
test('Can undo with closed code pane', async ({
page,
homePage,
editor,
toolbar,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
const viewportSize = { width: 1500, height: 750 }
await page.setBodyDimensions(viewportSize)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`@settings(defaultLengthUnit=in)
sketch001 = startSketchOn(XZ)
|> startProfile(at = [-10, -10])
|> line(end = [20.0, 10.0])
|> tangentialArc(end = [5.49, 8.37])`
)
})
await homePage.goToModelingScene()
await toolbar.waitForFeatureTreeToBeBuilt()
await scene.settled(cmdBar)
await (await toolbar.getFeatureTreeOperation('Sketch', 0)).dblclick()
await page.waitForTimeout(1000)
await page.mouse.move(1200, 139)
await page.mouse.down()
await page.mouse.move(870, 250)
await page.mouse.up()
await editor.expectEditor.toContain(`tangentialArc(end=[-5.85,4.32])`, {
shouldNormalise: true,
})
await u.closeKclCodePanel()
// Undo the last change
await page.keyboard.down('Control')
await page.keyboard.press('KeyZ')
await page.keyboard.up('Control')
await u.openKclCodePanel()
await editor.expectEditor.toContain(`tangentialArc(end = [5.49, 8.37])`, {
shouldNormalise: true,
})
})
test('Can delete a single segment line with keyboard', async ({
page,
scene,

View File

@ -798,7 +798,7 @@ test('theme persists', async ({ page, context, homePage }) => {
await page.getByTestId('settings-close-button').click()
const networkToggle = page.getByTestId('network-toggle')
const networkToggle = page.getByTestId(/network-toggle/)
// simulate network down
await u.emulateNetworkConditions({

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -12,6 +12,7 @@ export const TEST_SETTINGS: DeepPartial<Settings> = {
},
onboarding_status: 'dismissed',
show_debug_panel: true,
fixed_size_grid: false,
},
modeling: {
enable_ssao: false,

View File

@ -24,16 +24,15 @@ test.describe('Test network related behaviors', () => {
await homePage.goToModelingScene()
const networkToggle = page.getByTestId('network-toggle')
const networkToggle = page.getByTestId(/network-toggle/)
// This is how we wait until the stream is online
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled({ timeout: 15000 })
const networkWidget = page.locator('[data-testid="network-toggle"]')
await expect(networkWidget).toBeVisible()
await networkWidget.hover()
await expect(networkToggle).toBeVisible()
await networkToggle.hover()
const networkPopover = page.locator('[data-testid="network-popover"]')
await expect(networkPopover).not.toBeVisible()
@ -44,7 +43,7 @@ test.describe('Test network related behaviors', () => {
).toBeVisible()
// Click the network widget
await networkWidget.click()
await networkToggle.click()
// Check the modal opened.
await expect(networkPopover).toBeVisible()
@ -65,8 +64,8 @@ test.describe('Test network related behaviors', () => {
// Expect the network to be down
await expect(networkToggle).toContainText('Network health (Offline)')
// Click the network widget
await networkWidget.click()
// Click the network toggle
await networkToggle.click()
// Check the modal opened.
await expect(networkPopover).toBeVisible()
@ -99,7 +98,7 @@ test.describe('Test network related behaviors', () => {
'Engine disconnect & reconnect in sketch mode',
{ tag: '@skipLocalEngine' },
async ({ page, homePage, toolbar, scene, cmdBar }) => {
const networkToggle = page.getByTestId('network-toggle')
const networkToggle = page.getByTestId(/network-toggle/)
const networkToggleConnectedText = page.getByText(
'Network health (Strong)'
)
@ -286,7 +285,7 @@ profile001 = startProfile(sketch001, at = [12.34, -12.34])
'Paused stream freezes view frame, unpause reconnect is seamless to user',
{ tag: ['@desktop', '@skipLocalEngine'] },
async ({ page, homePage, scene, cmdBar, toolbar, tronApp }) => {
const networkToggle = page.getByTestId('network-toggle')
const networkToggle = page.getByTestId(/network-toggle/)
const networkToggleConnectedText = page.getByText(
'Network health (Strong)'
)

View File

@ -22,6 +22,7 @@ export const token = process.env.token || ''
import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
import type { ElectronZoo } from '@e2e/playwright/fixtures/fixtureSetup'
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import { isErrorWhitelisted } from '@e2e/playwright/lib/console-error-whitelist'
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
import { test } from '@e2e/playwright/zoo-test'
@ -37,7 +38,7 @@ export const headerMasks = (page: Page) => [
]
export const lowerRightMasks = (page: Page) => [
page.getByTestId('network-toggle'),
page.getByTestId(/network-toggle/),
page.getByTestId('billing-remaining-bar'),
]
@ -737,6 +738,7 @@ export const doExport = async (
output: Models['OutputFormat3d_type'],
rootDir: string,
page: Page,
cmdBar: CmdBarFixture,
exportFrom: 'dropdown' | 'sidebarButton' | 'commandBar' = 'dropdown'
): Promise<Paths> => {
if (exportFrom === 'dropdown') {
@ -780,9 +782,7 @@ export const doExport = async (
.click()
await page.locator('#arg-form').waitFor({ state: 'detached' })
}
await expect(page.getByText('Confirm Export')).toBeVisible()
await page.getByRole('button', { name: 'Submit command' }).click()
await cmdBar.submit()
await expect(page.getByText('Exported successfully')).toBeVisible()
@ -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,

View File

@ -10,7 +10,7 @@ import {
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing constraints', () => {
test('Can constrain line length', async ({ page, homePage }) => {
test('Can constrain line length', async ({ page, homePage, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -50,11 +50,7 @@ test.describe('Testing constraints', () => {
await page.waitForTimeout(100)
await page.getByTestId('constraint-length').click()
await page.getByTestId('cmd-bar-arg-value').getByRole('textbox').fill('20')
await page
.getByRole('button', {
name: 'arrow right Continue',
})
.click()
await cmdBar.continue()
await expect(page.locator('.cm-content')).toHaveText(
`length001 = 20sketch001 = startSketchOn(XY) |> startProfile(at = [-10, -10]) |> line(end = [20, 0]) |> angledLine(angle = 90, length = length001) |> xLine(length = -20)`
@ -681,9 +677,6 @@ test.describe('Testing constraints', () => {
.getByRole('textbox')
const cmdBarKclVariableNameInput =
page.getByPlaceholder('Variable name')
const cmdBarSubmitButton = page.getByRole('button', {
name: 'arrow right Continue',
})
await page.addInitScript(async () => {
localStorage.setItem(
@ -736,7 +729,7 @@ part002 = startSketchOn(XZ)
await page.waitForTimeout(500)
const [ang, len] = value.split(', ')
const changedCode = `|> angledLine(angle = ${ang}, length = ${len})`
await cmdBarSubmitButton.click()
await cmdBar.continue()
await expect(page.locator('.cm-content')).toContainText(changedCode)
// checking active assures the cursor is where it should be
@ -1101,11 +1094,7 @@ part002 = startSketchOn(XZ)
await page.waitForTimeout(500)
await page.getByTestId('cmd-bar-arg-value').getByRole('textbox').fill('10')
await page
.getByRole('button', {
name: 'arrow right Continue',
})
.click()
await cmdBar.continue()
await pollEditorLinesSelectedLength(page, 1)
activeLinesContent = await page.locator('.cm-activeLine').all()

View File

@ -8,37 +8,37 @@ test.describe('Testing Gizmo', () => {
const cases = [
{
testDescription: 'top view',
clickPosition: { x: 951, y: 385 },
clickPosition: { x: 951, y: 402 },
expectedCameraPosition: { x: 800, y: -152, z: 4886.02 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'bottom view',
clickPosition: { x: 951, y: 429 },
clickPosition: { x: 951, y: 449 },
expectedCameraPosition: { x: 800, y: -152, z: -4834.02 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'right view',
clickPosition: { x: 929, y: 417 },
clickPosition: { x: 929, y: 435 },
expectedCameraPosition: { x: 5660.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'left view',
clickPosition: { x: 974, y: 397 },
clickPosition: { x: 974, y: 417 },
expectedCameraPosition: { x: -4060.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'back view',
clickPosition: { x: 967, y: 421 },
clickPosition: { x: 967, y: 441 },
expectedCameraPosition: { x: 800, y: 4708.02, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'front view',
clickPosition: { x: 935, y: 393 },
clickPosition: { x: 935, y: 413 },
expectedCameraPosition: { x: 800, y: -5012.02, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},

View File

@ -21,7 +21,7 @@ test.describe('Testing loading external models', () => {
// We have no more web tests
test.fail(
'Web: should overwrite current code, cannot create new file',
async ({ editor, context, page, homePage }) => {
async ({ editor, context, page, homePage, cmdBar }) => {
const u = await getUtils(page)
await test.step(`Test setup`, async () => {
await context.addInitScript((code) => {
@ -52,9 +52,6 @@ test.describe('Testing loading external models', () => {
name,
})
const warningText = page.getByText('Overwrite current file with sample?')
const confirmButton = page.getByRole('button', {
name: 'Submit command',
})
await test.step(`Precondition: check the initial code`, async () => {
await u.openKclCodePanel()
@ -70,7 +67,7 @@ test.describe('Testing loading external models', () => {
await expect(commandMethodOption('Create new file')).not.toBeVisible()
await commandMethodOption('Overwrite').click()
await expect(warningText).toBeVisible()
await confirmButton.click()
await cmdBar.submit()
await editor.expectEditor.toContain('// ' + newSample.title)
})

View File

@ -3,6 +3,7 @@ import type { LineInputsType } from '@src/lang/std/sketchcombos'
import { uuidv4 } from '@src/lib/utils'
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import { deg, getUtils, wiggleMove } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
@ -18,7 +19,7 @@ test.describe('Testing segment overlays', () => {
* @param {number} options.steps - The number of steps to perform
*/
const _clickConstrained =
(page: Page, editor: EditorFixture) =>
(page: Page, editor: EditorFixture, cmdBar: CmdBarFixture) =>
async ({
hoverPos,
constraintType,
@ -93,11 +94,7 @@ test.describe('Testing segment overlays', () => {
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await page.waitForTimeout(500)
await page
.getByRole('button', {
name: 'arrow right Continue',
})
.click()
await cmdBar.continue()
await editor.expectEditor.toContain(expectFinal, {
shouldNormalise: true,
})
@ -113,7 +110,7 @@ test.describe('Testing segment overlays', () => {
* @param {number} options.steps - The number of steps to perform
*/
const _clickUnconstrained =
(page: Page, editor: EditorFixture) =>
(page: Page, editor: EditorFixture, cmdBar: CmdBarFixture) =>
async ({
hoverPos,
constraintType,
@ -163,11 +160,7 @@ test.describe('Testing segment overlays', () => {
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await page.waitForTimeout(500)
await page
.getByRole('button', {
name: 'arrow right Continue',
})
.click()
await cmdBar.continue()
await editor.expectEditor.toContain(expectAfterUnconstrained, {
shouldNormalise: true,
})
@ -239,8 +232,8 @@ test.describe('Testing segment overlays', () => {
await expect(page.getByTestId('segment-overlay')).toHaveCount(14)
const clickUnconstrained = _clickUnconstrained(page, editor)
const clickConstrained = _clickConstrained(page, editor)
const clickUnconstrained = _clickUnconstrained(page, editor, cmdBar)
const clickConstrained = _clickConstrained(page, editor, cmdBar)
await u.openAndClearDebugPanel()
await u.sendCustomCmd({
@ -664,7 +657,7 @@ profile002 = circle(sketch001, center = [345, 0], radius = 238.38)
await expect(
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await page.getByRole('button', { name: 'arrow right Continue' }).click()
await cmdBar.continue()
// Verify the X constraint was added
await editor.expectEditor.toContain('center = [xAbs001, 0]', {
@ -682,7 +675,7 @@ profile002 = circle(sketch001, center = [345, 0], radius = 238.38)
await expect(
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await page.getByRole('button', { name: 'arrow right Continue' }).click()
await cmdBar.continue()
// Verify the Y constraint was added
await editor.expectEditor.toContain('center = [xAbs001, yAbs001]', {
@ -700,7 +693,7 @@ profile002 = circle(sketch001, center = [345, 0], radius = 238.38)
await expect(
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await page.getByRole('button', { name: 'arrow right Continue' }).click()
await cmdBar.continue()
// Verify all constraints were added
await editor.expectEditor.toContain(
@ -887,7 +880,7 @@ profile003 = startProfile(sketch001, at = [64.39, 35.16])
await expect(
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await page.getByRole('button', { name: 'arrow right Continue' }).click()
await cmdBar.continue()
// Verify the constraint was added
await editor.expectEditor.toContain(
@ -910,7 +903,7 @@ profile003 = startProfile(sketch001, at = [64.39, 35.16])
await expect(
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await page.getByRole('button', { name: 'arrow right Continue' }).click()
await cmdBar.continue()
// Verify both constraints were added
await editor.expectEditor.toContain(
@ -935,7 +928,7 @@ profile003 = startProfile(sketch001, at = [64.39, 35.16])
await expect(
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await page.getByRole('button', { name: 'arrow right Continue' }).click()
await cmdBar.continue()
// Verify the constraint was added
await editor.expectEditor.toContain('endAbsolute = [xAbs002, 84.07]', {
@ -955,7 +948,7 @@ profile003 = startProfile(sketch001, at = [64.39, 35.16])
await expect(
page.getByTestId('cmd-bar-arg-value').getByRole('textbox')
).toBeFocused()
await page.getByRole('button', { name: 'arrow right Continue' }).click()
await cmdBar.continue()
// Verify all constraints were added
await editor.expectEditor.toContain(

View File

@ -32,7 +32,7 @@ test('Units menu', async ({ page, homePage }) => {
test(
'Successful export shows a success toast',
{ tag: '@skipLocalEngine' },
async ({ page, homePage, tronApp }) => {
async ({ page, homePage, cmdBar, tronApp }) => {
// FYI this test doesn't work with only engine running locally
// And you will need to have the KittyCAD CLI installed
const u = await getUtils(page)
@ -94,7 +94,8 @@ part001 = startSketchOn(-XZ)
presentation: 'pretty',
},
tronApp?.projectDirName,
page
page,
cmdBar
)
}
)
@ -254,6 +255,7 @@ test('First escape in tool pops you out of tool, second exits sketch mode', asyn
test('Basic default modeling and sketch hotkeys work', async ({
page,
homePage,
cmdBar,
}) => {
const u = await getUtils(page)
await test.step(`Set up test`, async () => {
@ -397,11 +399,8 @@ test('Basic default modeling and sketch hotkeys work', async ({
await expect(page.getByRole('button', { name: 'Continue' })).toBeVisible({
timeout: 20_000,
})
await page.getByRole('button', { name: 'Continue' }).click()
await expect(
page.getByRole('button', { name: 'Submit command' })
).toBeVisible()
await page.getByRole('button', { name: 'Submit command' }).click()
await cmdBar.continue()
await cmdBar.submit()
await expect(page.locator('.cm-content')).toContainText('extrude(')
})
@ -575,8 +574,7 @@ profile001 = startProfile(sketch002, at = [-12.34, 12.34])
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await expect(page.getByText('Confirm Extrude')).toBeVisible()
await cmdBar.progressCmdBar()
await cmdBar.submit()
const result2 = result.genNext`
const sketch002 = extrude(sketch002, length = ${[5, 5]} + 7)`

View File

@ -111,7 +111,8 @@ commaSep1NoTrailingComma<term> { term ("," term)* }
PipeSubstitution { "%" }
identifier { (@asciiLetter | "_") (@asciiLetter | @digit | "_")* }
// Includes non-whitespace unicode characters.
identifier { $[a-zA-Z_\u{a1}-\u{167f}\u{1681}-\u{1fff}\u{200e}-\u{2027}\u{202a}-\u{202e}\u{2030}-\u{205e}\u{2061}-\u{2fff}\u{3001}-\u{fefe}\u{ff00}-\u{10ffff}] $[a-zA-Z0-9_\u{a1}-\u{167f}\u{1681}-\u{1fff}\u{200e}-\u{2027}\u{202a}-\u{202e}\u{2030}-\u{205e}\u{2061}-\u{2fff}\u{3001}-\u{fefe}\u{ff00}-\u{10ffff}]* }
AnnotationName { "@" identifier? }
PropertyName { identifier }
TagDeclarator { "$" identifier }

View File

@ -42,15 +42,15 @@ fn helicalGear(nTeeth, module, pressureAngle, helixAngle, gearHeight) {
helicalGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
startDiameter = baseDiameter,
endDiameter = tipDiameter,
angle = helixCalc,
tag = $seg01,
)
|> line(endAbsolute = polar(angle = 160 / nTeeth + helixCalc, length = tipDiameter / 2))
|> involuteCircular(
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
startDiameter = baseDiameter,
endDiameter = tipDiameter,
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)),
reverse = true,
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Some files were not shown because too many files have changed in this diff Show More