Compare commits

...

41 Commits

Author SHA1 Message Date
73045811b4 Merge branch 'main' into updater-test 2025-04-15 11:06:53 -04:00
d9be308c36 ~Maybe~ (Lee: ABSOLUTELY) use biome (#6327)
* maybe use biome

* import organising

* Removed unused new fmt commands; fix to not use linter

* Don't use fmt:generated - fmt is fast, but also use Makefile for this sort of thing

---------

Co-authored-by: lee-at-zoo-corp <lee@zoo.dev>
2025-04-15 10:11:25 -04:00
3cca4a30af [BUG] Grab bag of sketch mode bug fixes (#6229)
* use artifact id for sketch mode entry plane

* fix up re-eval as best as possible

* remove some async dodgyness

* fmt

* fix old sycronous re-execute shit

* add a test

* fix existing test

* add toast for error state

* spelling

* test stuff

* fmt

* fix toast

* test fix

* some other fix ups

* fix test
2025-04-15 09:27:50 -04:00
c51db5bd4a Make playwright:snapshots:ubuntu fail on mismatching image snapshots (#6322)
* pierremtb/adhoc/playwright-should-fail-on-mismatching-image-snapshots

* Add network-toggle to masks

* Add network masks

* :oops: tangentialArc snapshot update

* Update snaps

* Cleaner constants for masks

* Update snaps

* Clean up, updated README
2025-04-15 09:43:39 +00:00
7fce38b212 KCL: angledLineThatIntersects migrate to kwargs (#6296)
* KCL: Convert angledLineThatIntersects to use kwargs

* Update KCL tests and samples

* WIP

* Fix tsc and lint errors

* Fix missing cases

* Fix modifyAst unit tests

* Fix sketch unit tests

* Fix std unit tests

* Fix to not have extra docs

* Fix more unit tests

* Fix bench test

* Fix e2e tests to use new kw args

* tiny lint

* Fix adding constraint from UI to work

* Fix to use labeledArg constraints and use the correct order of args

* Fix selections e2e test

* Fix e2e test expectation

App was working as expected, but the e2e test was
expecting the old code, not the new code.

* Fix order of constraints in unit test

* Update docs

* Fix KCL formatting

* Update output

---------

Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-04-15 02:06:55 +00:00
d0e9b111af #5339 Add tangent snapping to straight segment tool (#5995)
* first draft of making segment snap to previous arc's last tangent

* ability to force/disable line snap, threshold in screen space

* mouseEvent refactor tsc errors fixed

* cleanups, extract getTanPreviousPoint function

* add snap line support when previous segment is ARC

* small cleanups

* remove unused planeNodePath param from onDragSegment

* renaming

* Enable snapping when placing the segment point in onClick

* refactor getSnappedDragPoint to include axis intersection

* handle snapping to both axis and tangent direction

* snap refinements

* small cleanups

* lint

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* generate tag for previous arc when snapping current straight segment

* using previous arc's tag in snapped angledLine

* angledLine uses object instead of array now

* use more general snap object instead

* snap tangent line visualized when snapping occurs

* remove unused scale param from createLine

* prettier

* fix bug where segment body is not drawn

* fix generated kcl error introduced in merge from main - modifiedAst needs to be passed to addNewSketchLn

* add support for snapping to negative tangent direction

* fix findTangentDirection for THREE_POINT_ARC_SEGMENT

* fix tsc error by introducing overrideExpr

* fix missing ccw for 3 point arc, fix tan_previous_point calculation for 3 point arcs

* resolve clippy until confirmation for circle radius

* fix runtime error when drawing a 3 point arc

* add unit tests to closestPointoOnRay

* unrelated react warning fixed

* add playwright test for tangent snapping

* better fix for tan_previous_point

* fix lint

* add simulation test for tangent_to_3_point_arc

* Fix simulation test output

* Add missing simulation test output files

* fix tangent snapping bug: use current group instead of last group in activeSegments

* make testcombos.test happy

* cleanup merge

* fix merge mistake, tsc error

* update tangent_to_3_point_arc simulation test

* fix angledLine related breaking tests

* minimum distance added before snapping to tangent

* circle is always ccw regardless of the order of points for tangential info calculation

* fix snapping when different unit is used other than mm

* update test: Straight line snapping to previous tangent

* update rust snapshot test

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-04-14 23:51:14 +02:00
add1b21503 Assemblies: Load outside files into project via point-and-click (#6217)
* WIP: Add point-and-click Import for geometry
Will eventually fix #6120
Right now the whole loop is there but the codemod doesn't work yet

* Better pathToNOde, log on non-working cm dispatch call

* Add workaround to updateModelingState not working

* Back to updateModelingState with a skip flag

* Better todo

* Change working from Import to Insert, cleanups

* Sister command in kclCommands to populate file options

* Improve path selector

* Unsure: move importAstMod to kclCommands onSubmit 😶

* Add e2e test

* Clean up for review

* Add native file menu entry and test

* No await yo lint said so

* WIP: UX improvements around foreign file imports
Fixes #6152

* @lrev-Dev's suggestion to remove a comment

Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>

* Update to scene.settled(cmdBar)

* Add partNNN default name for alias

* Lint

* Lint

* Fix unit tests

* Add sad path insert test
Thanks @Irev-Dev for the suggestion

* Add step insert test

* Lint

* Add test for second foreign import thru file tree click

* WIP: Add point-and-click Load to copy files from outside the project into the project
Towards #6210

* Move Insert button to modeling toolbar, update menus and toolbars

* Add default value for local name alias

* Aligning tests

* Fix tests

* Add padding for filenames starting with a digit

* Lint

* Lint

* Update snapshots

* Merge branch 'main' into pierremtb/issue6210-Add-point-and-click-Load-to-copy-files-from-outside-the-project-into-the-project

* Add disabled transform subbutton

* Merge kcl-samples and local disk load into one 'Load external model' command

* Fix em tests

* Fix test

* Add test for file pick import, better input

* Fix non .kcl loading

* Lint

* Update snapshots

* Fix issue leading to test failure

* Fix clone test

* Add note

* Fix nested clone issue

* Clean up for review

* Add valueSummary for path

* Fix test after path change

* Clean up for review

* Update src/lib/kclCommands.ts

Thanks @franknoirot!

Co-authored-by: Frank Noirot <frank@zoo.dev>

* Improve path input arg

* Fix tests

* Merge branch 'main' into pierremtb/issue6210-Add-point-and-click-Load-to-copy-files-from-outside-the-project-into-the-project

* Fix path header not showing and improve tests

* Clean up

---------

Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
Co-authored-by: Frank Noirot <frank@zoo.dev>
2025-04-14 18:53:01 +00:00
39af110ac1 Include test annotations for analysis (#6321) 2025-04-14 18:10:47 +00:00
bf7ec424a7 Add loading spinner back to stream just for engine connection, give it an error state (#6220)
* Add an engine error type for an "outage"

* Add a loading spinner back to the stream just for engine connection

* Refactor Loading spinner to account for early errors

* Add styling and state logic for unrecoverable errors in Loading

* Let engine error messages contain markdown

* Clarify 'too many connections' error message

* Add a "VeryLongLoadTime" error that suggests checking firewall

* Give the engine connection spinner a test ID and use it
2025-04-14 13:00:30 -04:00
6c7e42b541 Bump the patch group in /rust with 8 updates (#6312)
Bumps the patch group in /rust with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.97` | `1.0.98` |
| [clap](https://github.com/clap-rs/clap) | `4.5.32` | `4.5.36` |
| [kittycad-modeling-cmds](https://github.com/KittyCAD/modeling-api) | `0.2.113` | `0.2.114` |
| [once_cell](https://github.com/matklad/once_cell) | `1.21.1` | `1.21.3` |
| [log](https://github.com/rust-lang/log) | `0.4.26` | `0.4.27` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.1.0` | `1.1.1` |
| [time](https://github.com/time-rs/time) | `0.3.40` | `0.3.41` |
| [image](https://github.com/image-rs/image) | `0.25.5` | `0.25.6` |


Updates `anyhow` from 1.0.97 to 1.0.98
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.97...1.0.98)

Updates `clap` from 4.5.32 to 4.5.36
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.32...clap_complete-v4.5.36)

Updates `kittycad-modeling-cmds` from 0.2.113 to 0.2.114
- [Commits](https://github.com/KittyCAD/modeling-api/compare/kittycad-modeling-cmds-0.2.113...kittycad-modeling-cmds-0.2.114)

Updates `once_cell` from 1.21.1 to 1.21.3
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.21.1...v1.21.3)

Updates `log` from 0.4.26 to 0.4.27
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.26...0.4.27)

Updates `flate2` from 1.1.0 to 1.1.1
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.0...1.1.1)

Updates `time` from 0.3.40 to 0.3.41
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.3.40...v0.3.41)

Updates `image` from 0.25.5 to 0.25.6
- [Changelog](https://github.com/image-rs/image/blob/main/CHANGES.md)
- [Commits](https://github.com/image-rs/image/compare/v0.25.5...v0.25.6)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-version: 1.0.98
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: clap
  dependency-version: 4.5.36
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: kittycad-modeling-cmds
  dependency-version: 0.2.114
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: once_cell
  dependency-version: 1.21.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: log
  dependency-version: 0.4.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: flate2
  dependency-version: 1.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: time
  dependency-version: 0.3.41
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: image
  dependency-version: 0.25.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-14 09:48:43 -07:00
542a9a3f13 Fix to update prompt-to-edit snapshot (#6320)
* Fix to update prompt-to-edit snapshot

* Delete snapshot with no TS test file
2025-04-14 16:19:09 +00:00
264779a9d0 Follow up: Stream Idle PR (#6238)
* Use a dropdown for stream idle setting

* Add support for undefined values in dropdowns

* Move cache bust to the beginning of engine open for reconnections

* yarn tsc

* Don't setup model feature highlighters until the connection is ready

* Wait 2s to give engine time to serve video, then listen for modeling commands

* Undo teardown

* yarn fmt

* Fix circular module dependency; fmt & lint & tsc

* Fix editor-test waiting for 2 instead of 1

* Increment another 2 numbers ...

---------

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
2025-04-14 12:09:45 -04:00
22dd4a67dd Share file snapshots across platforms (#6282)
* Share file snapshots across platforms

* Always skip file snapshot tests on Windows
2025-04-14 13:26:52 +00:00
5c188664bd Remove step retries in build-apps after npm transition (#6310)
* Remove unecessary step retries from build-apps

* To revert: Test with IS_RELEASE

* To revert: CSC_FOR_PULL_REQUEST

* Revert for review
2025-04-14 09:24:15 -04:00
f6e23fe619 Include test tags for analysis (#6304) 2025-04-14 13:08:07 +00:00
160f55ede5 BREAKING: More units of measure work and keyword args (#6291)
* More units of measure work

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Update CSG output since engine change

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
2025-04-14 09:58:19 +00:00
7d7b153085 Add START and END constants to std (#6270)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-04-14 20:37:45 +12:00
8f487a441b fix text to code bug (#6308) 2025-04-14 04:02:17 +00:00
c8cee6a0dc Fix examples of how to run e2e tests with options (#6303) 2025-04-12 14:17:13 -04:00
167445ef8a WIP: migrate from yarn v1 to npm (#6274)
* WIP: migrate from yarn v1 to npm

* Add tsc mapping script

* More fixes

* Add playwright as script

* Fix more

* more and more people just want more

* Merge branch 'main' into pierremtb/adhoc/npm

* use workspaces and fix circular deps

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

* fmt

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

* fix

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

* New machine-api types

* better lock file

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

* ignore typos in machine-api generated files

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

* updates

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

* install from root

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

* fix tsc

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

* New machine-api types

* bettter install

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

* bettter install

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

* bettter install

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

* bettter install

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

* bettter install

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

* add comment

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

* add comment

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-04-12 02:49:49 +00:00
95b72d839b coerce [single, HomArray[single]] into flattened HomArray (#6299)
* dont prompt for message in git tag

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

* more tests

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

* updates

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

* updates

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

* updates

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-11 22:06:12 -04:00
9365186bed Change an IPC call to a fetch client-side. (#6294)
* Change an IPC call to a fetch client-side.

* fix fmt

* update
2025-04-11 23:59:27 +00:00
eea026f8e0 dont prompt for message in git tag (#6293)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-11 17:33:17 -04:00
3cd7a3533e Release create and edit parameter flows to the public (#6295)
I can't believe I didn't realize they never got marked as no longer in
development!
2025-04-11 21:12:36 +00:00
9e1f1152e3 Involute curve for sketch (#6258)
* WIP: Involute circles in KCL

* first pass involute end calculation

* fmt

* cleanup

* involute snapshot

* actually update markdown

* remove debug build stuff

* spacing

---------

Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>
2025-04-11 21:59:11 +01:00
60d2be9ff2 Fix angledLine error messages to recommend the right keyword args (#6290)
* Fix angledLine error messages to recommend the right keyword args

* Update generated docs
2025-04-11 20:03:57 +00:00
0f59894d66 Hide sweep artifacts after automatically (#6287)
* automatically hide the trajectory sketch agter a sweep

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

* updates

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

* more samples

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

* more samples

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

* updates

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-11 15:53:53 -04:00
74c07fc0eb Update onboarding bracket to be robust (#6099)
* update onboarding bracket to be robust

* update onboarding bracket with bends

* checking if asserts causing parse failure

* fun fact, it was not the asserts

* fix bracket loading

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

* updates

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2025-04-11 19:27:29 +00:00
67a8bf525d bump kcl friends (#6288)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-11 19:10:37 +00:00
4fa88396ad Merge branch 'main' into updater-test 2025-04-02 13:33:47 -04:00
1106ab50a5 WIP release notes 2025-01-07 16:11:57 -05:00
e518828b91 Remove ### 2025-01-07 16:04:32 -05:00
a3f2865a13 Merge branch 'main' into updater-test 2025-01-07 15:57:20 -05:00
08c5a3b499 Merge branch 'main' into updater-test 2024-10-28 07:15:47 -04:00
9f36478518 Merge branch 'main' into updater-test 2024-10-11 06:18:04 -04:00
71123915e8 Clean up for real 2024-10-09 05:05:36 -04:00
eb8cbfd770 Update from main and clean up branch 2024-10-09 05:04:52 -04:00
2121a6c364 Change to yaml conf 2024-10-07 07:58:50 -04:00
57c6d78c6d shell: bash fix attempt 2024-10-07 07:42:27 -04:00
7657b93a00 Dummy 0.255.255 push 2024-10-07 07:06:11 -04:00
af12a460df Generate and upload release notes for electron-builder 2024-10-07 07:03:11 -04:00
707 changed files with 117797 additions and 55629 deletions

View File

@ -1,3 +1,3 @@
[codespell] [codespell]
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall,ser,fromM,FromM ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall,ser,fromM,FromM
skip: **/target,node_modules,build,dist,./out,**/Cargo.lock,./docs/kcl/*.md,.yarn.lock,**/yarn.lock,./openapi/*.json,./packages/codemirror-lang-kcl/test/all.test.ts,./public/kcl-samples,./rust/kcl-lib/tests/kcl_samples,tsconfig.tsbuildinfo skip: **/target,node_modules,build,dist,./out,**/Cargo.lock,./docs/kcl/*.md,.package-lock.json,**/package-lock.json,./openapi/*.json,./packages/codemirror-lang-kcl/test/all.test.ts,./public/kcl-samples,./rust/kcl-lib/tests/kcl_samples,tsconfig.tsbuildinfo,./src/lib/machine-api.d.ts

View File

@ -7,11 +7,11 @@ if [[ ! -f "test-results/.last-run.json" ]]; then
# If no last run artifact, than run Playwright normally # If no last run artifact, than run Playwright normally
echo "run playwright normally" echo "run playwright normally"
if [[ "$3" == *ubuntu* ]]; then if [[ "$3" == *ubuntu* ]]; then
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn test:playwright:electron:ubuntu -- --shard=$1/$2 || true xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:playwright:electron:ubuntu -- --shard=$1/$2 || true
elif [[ "$3" == *windows* ]]; then elif [[ "$3" == *windows* ]]; then
yarn test:playwright:electron:windows -- --shard=$1/$2 || true npm run test:playwright:electron:windows -- --shard=$1/$2 || true
elif [[ "$3" == *macos* ]]; then elif [[ "$3" == *macos* ]]; then
yarn test:playwright:electron:macos -- --shard=$1/$2 || true npm run test:playwright:electron:macos -- --shard=$1/$2 || true
else else
echo "Do not run Playwright. Unable to detect os runtime." echo "Do not run Playwright. Unable to detect os runtime."
exit 1 exit 1
@ -31,11 +31,11 @@ while [[ $retry -le $max_retries ]]; do
echo "retried=true" >>$GITHUB_OUTPUT echo "retried=true" >>$GITHUB_OUTPUT
echo "run playwright with last failed tests and retry $retry" echo "run playwright with last failed tests and retry $retry"
if [[ "$3" == *ubuntu* ]]; then if [[ "$3" == *ubuntu* ]]; then
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn test:playwright:electron:ubuntu -- --last-failed || true xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:playwright:electron:ubuntu -- --last-failed || true
elif [[ "$3" == *windows* ]]; then elif [[ "$3" == *windows* ]]; then
yarn test:playwright:electron:windows -- --last-failed || true npm run test:playwright:electron:windows -- --last-failed || true
elif [[ "$3" == *macos* ]]; then elif [[ "$3" == *macos* ]]; then
yarn test:playwright:electron:macos -- --last-failed || true npm run test:playwright:electron:macos -- --last-failed || true
else else
echo "Do not run playwright. Unable to detect os runtime." echo "Do not run playwright. Unable to detect os runtime."
exit 1 exit 1

View File

@ -13,9 +13,9 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- name: Install dependencies - name: Install dependencies
run: yarn run: npm install
- name: Use correct Rust toolchain - name: Use correct Rust toolchain
shell: bash shell: bash
run: | run: |
@ -32,7 +32,7 @@ jobs:
with: with:
workspaces: rust workspaces: rust
- name: build wasm - name: build wasm
run: yarn build:wasm run: npm run build:wasm
# Upload the WASM bundle as an artifact # Upload the WASM bundle as an artifact

View File

@ -5,12 +5,14 @@ on:
push: push:
branches: branches:
- main - main
- updater-test
tags: tags:
- 'v[0-9]+.[0-9]+.[0-9]+' - 'v[0-9]+.[0-9]+.[0-9]+'
- 'nightly-v[0-9]+.[0-9]+.[0-9]+' - 'nightly-v[0-9]+.[0-9]+.[0-9]+'
env: env:
IS_RELEASE: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'v') }} # IS_RELEASE: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'v') }}
IS_RELEASE: true
IS_NIGHTLY: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'nightly-v') }} IS_NIGHTLY: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'nightly-v') }}
concurrency: concurrency:
@ -29,9 +31,9 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- run: yarn install - run: npm install
- id: filter - id: filter
name: Check for Rust changes name: Check for Rust changes
@ -90,20 +92,20 @@ jobs:
- name: Run build:wasm - name: Run build:wasm
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }} if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
run: "yarn build:wasm" run: "npm run build:wasm"
- name: Set nightly version, product name, release notes, and icons - name: Set nightly version, product name, release notes, and icons
if: ${{ env.IS_NIGHTLY == 'true' }} if: ${{ env.IS_NIGHTLY == 'true' }}
run: | run: |
export VERSION=${GITHUB_REF_NAME#nightly-v} export VERSION=${GITHUB_REF_NAME#nightly-v}
yarn files:set-version npm run files:set-version
yarn files:flip-to-nightly npm run files:flip-to-nightly
- name: Set release version # - name: Set release version
if: ${{ env.IS_RELEASE == 'true' }} # if: ${{ env.IS_RELEASE == 'true' }}
run: | # run: |
export VERSION=${GITHUB_REF_NAME#v} # export VERSION=${GITHUB_REF_NAME#v}
yarn files:set-version # npm run files:set-version
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
with: with:
@ -122,17 +124,17 @@ jobs:
- id: export_notes - id: export_notes
run: echo "notes=`cat release-notes.md`" >> "$GITHUB_OUTPUT" run: echo "notes=`cat release-notes.md`" >> "$GITHUB_OUTPUT"
- name: Prepare electron-builder.yml file for updater test # - name: Prepare electron-builder.yml file for updater test
if: ${{ env.IS_RELEASE == 'true' }} # if: ${{ env.IS_RELEASE == 'true' }}
run: | # run: |
yq -i '.publish[0].url = "https://dl.zoo.dev/releases/modeling-app/updater-test"' electron-builder.yml # yq -i '.publish[0].url = "https://dl.zoo.dev/releases/modeling-app/updater-test"' electron-builder.yml
- uses: actions/upload-artifact@v4 # - uses: actions/upload-artifact@v4
if: ${{ env.IS_RELEASE == 'true' }} # if: ${{ env.IS_RELEASE == 'true' }}
with: # with:
name: prepared-files-updater-test # name: prepared-files-updater-test
path: | # path: |
electron-builder.yml # electron-builder.yml
build-apps: build-apps:
@ -172,16 +174,9 @@ jobs:
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' # Set this to npm, yarn or pnpm. cache: 'npm' # Set this to npm, npm or pnpm.
- name: yarn install - run: npm install
# Windows is picky sometimes and fails on fetch. Step takes about ~30s
uses: nick-fields/retry@v3.0.2
with:
shell: bash
timeout_minutes: 2
max_attempts: 3
command: yarn install
- name: Prepare certificate and variables (Windows only) - name: Prepare certificate and variables (Windows only)
if: ${{ (env.IS_RELEASE == 'true' || env.IS_NIGHTLY == 'true') && matrix.os == 'windows-2022' }} if: ${{ (env.IS_RELEASE == 'true' || env.IS_NIGHTLY == 'true') && matrix.os == 'windows-2022' }}
@ -220,7 +215,7 @@ jobs:
if: ${{ env.IS_RELEASE == 'false' && env.IS_NIGHTLY == 'false' }} if: ${{ env.IS_RELEASE == 'false' && env.IS_NIGHTLY == 'false' }}
# electron-builder doesn't have a concept of release vs debug, # electron-builder doesn't have a concept of release vs debug,
# this is just not doing any codesign or release yml generation, and points to dev infra # this is just not doing any codesign or release yml generation, and points to dev infra
run: yarn tronb:package:dev run: npm run tronb:package:dev
- name: Build the app (release) - name: Build the app (release)
if: ${{ env.IS_RELEASE == 'true' || env.IS_NIGHTLY == 'true' }} if: ${{ env.IS_RELEASE == 'true' || env.IS_NIGHTLY == 'true' }}
@ -233,14 +228,7 @@ jobs:
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
CSC_KEYCHAIN: ${{ secrets.APPLE_SIGNING_IDENTITY }} CSC_KEYCHAIN: ${{ secrets.APPLE_SIGNING_IDENTITY }}
WINDOWS_CERTIFICATE_THUMBPRINT: ${{ secrets.WINDOWS_CERTIFICATE_THUMBPRINT }} WINDOWS_CERTIFICATE_THUMBPRINT: ${{ secrets.WINDOWS_CERTIFICATE_THUMBPRINT }}
DEBUG: "electron-notarize*" run: npm run tronb:package:prod
# TODO: Fix electron-notarize flakes. The logs above should help gather more data on failures
uses: nick-fields/retry@v3.0.2
with:
shell: bash
timeout_minutes: 10
max_attempts: 3
command: yarn tronb:package:prod
- name: List artifacts in out/ - name: List artifacts in out/
run: ls -R out run: ls -R out
@ -274,60 +262,53 @@ jobs:
# The steps below are for updater-test builds, only on release # The steps below are for updater-test builds, only on release
- uses: actions/download-artifact@v4 # - uses: actions/download-artifact@v4
if: ${{ env.IS_RELEASE == 'true' }} # if: ${{ env.IS_RELEASE == 'true' }}
name: prepared-files-updater-test # name: prepared-files-updater-test
- name: Copy updated electron-builder.yml file for updater test # - name: Copy updated electron-builder.yml file for updater test
if: ${{ env.IS_RELEASE == 'true' }} # if: ${{ env.IS_RELEASE == 'true' }}
run: | # run: |
ls -R prepared-files-updater-test # ls -R prepared-files-updater-test
cp prepared-files-updater-test/electron-builder.yml electron-builder.yml # cp prepared-files-updater-test/electron-builder.yml electron-builder.yml
- name: Build the app (updater-test) # - name: Build the app (updater-test)
if: ${{ env.IS_RELEASE == 'true' }} # if: ${{ env.IS_RELEASE == 'true' }}
env: # env:
APPLE_ID: ${{ secrets.APPLE_ID }} # APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} # APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }} # APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} # APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
CSC_LINK: ${{ secrets.APPLE_CERTIFICATE }} # CSC_LINK: ${{ secrets.APPLE_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} # CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
CSC_KEYCHAIN: ${{ secrets.APPLE_SIGNING_IDENTITY }} # CSC_KEYCHAIN: ${{ secrets.APPLE_SIGNING_IDENTITY }}
WINDOWS_CERTIFICATE_THUMBPRINT: ${{ secrets.WINDOWS_CERTIFICATE_THUMBPRINT }} # WINDOWS_CERTIFICATE_THUMBPRINT: ${{ secrets.WINDOWS_CERTIFICATE_THUMBPRINT }}
DEBUG: "electron-notarize*" # run: npm run tronb:package:prod
# TODO: Fix electron-notarize flakes. The logs above should help gather more data on failures
uses: nick-fields/retry@v3.0.2
with:
shell: bash
timeout_minutes: 10
max_attempts: 3
command: yarn tronb:package:prod
- uses: actions/upload-artifact@v4 # - uses: actions/upload-artifact@v4
if: ${{ env.IS_RELEASE == 'true' }} # if: ${{ env.IS_RELEASE == 'true' }}
with: # with:
name: updater-test-arm64-${{ matrix.platform }} # name: updater-test-arm64-${{ matrix.platform }}
path: | # path: |
out/*-arm64-win.exe # out/*-arm64-win.exe
out/*-arm64-mac.dmg # out/*-arm64-mac.dmg
out/*-arm64-linux.AppImage # out/*-arm64-linux.AppImage
- uses: actions/upload-artifact@v4 # - uses: actions/upload-artifact@v4
if: ${{ env.IS_RELEASE == 'true' }} # if: ${{ env.IS_RELEASE == 'true' }}
with: # with:
name: updater-test-x64-${{ matrix.platform }} # name: updater-test-x64-${{ matrix.platform }}
path: | # path: |
out/*-x64-win.exe # out/*-x64-win.exe
out/*-x64-mac.dmg # out/*-x64-mac.dmg
out/*-x86_64-linux.AppImage # out/*-x86_64-linux.AppImage
upload-apps-release: upload-apps-release:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
permissions: permissions:
contents: write contents: write
if: ${{ github.ref_type == 'tag' }} # if: ${{ github.ref_type == 'tag' }}
env: env:
VERSION_NO_V: ${{ needs.prepare-files.outputs.version }} VERSION_NO_V: ${{ needs.prepare-files.outputs.version }}
VERSION: ${{ format('v{0}', needs.prepare-files.outputs.version) }} VERSION: ${{ format('v{0}', needs.prepare-files.outputs.version) }}
@ -442,16 +423,16 @@ jobs:
export TAG="nightly-${VERSION}" export TAG="nightly-${VERSION}"
export PREVIOUS_TAG=$(git tag --list --sort=-committerdate "nightly-v[0-9]*" | head -n2 | tail -n1) export PREVIOUS_TAG=$(git tag --list --sort=-committerdate "nightly-v[0-9]*" | head -n2 | tail -n1)
export NOTES=$(./scripts/get-nightly-changelog.sh) export NOTES=$(./scripts/get-nightly-changelog.sh)
yarn files:set-notes npm run files:set-notes
- name: Authenticate to Google Cloud - name: Authenticate to Google Cloud
if: ${{ env.IS_NIGHTLY == 'true' }} # if: ${{ env.IS_NIGHTLY == 'true' }}
uses: 'google-github-actions/auth@v2.1.8' uses: 'google-github-actions/auth@v2.1.8'
with: with:
credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}' credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'
- name: Set up Google Cloud SDK - name: Set up Google Cloud SDK
if: ${{ env.IS_NIGHTLY == 'true' }} # if: ${{ env.IS_NIGHTLY == 'true' }}
uses: google-github-actions/setup-gcloud@v2.1.4 uses: google-github-actions/setup-gcloud@v2.1.4
with: with:
project_id: ${{ env.GOOGLE_CLOUD_PROJECT_ID }} project_id: ${{ env.GOOGLE_CLOUD_PROJECT_ID }}
@ -465,6 +446,14 @@ jobs:
parent: false parent: false
destination: 'dl.kittycad.io/releases/modeling-app/nightly' destination: 'dl.kittycad.io/releases/modeling-app/nightly'
- name: Upload updater-test files to public bucket
uses: google-github-actions/upload-cloud-storage@v2.2.1
with:
path: out
glob: '*'
parent: false
destination: 'dl.kittycad.io/releases/modeling-app/updater-test'
- name: Invalidate bucket cache on latest*.yml and last_download.json files - name: Invalidate bucket cache on latest*.yml and last_download.json files
if: ${{ env.IS_NIGHTLY == 'true' }} if: ${{ env.IS_NIGHTLY == 'true' }}
run: yarn files:invalidate-bucket:nightly run: npm run files:invalidate-bucket:nightly

View File

@ -5,6 +5,7 @@ on:
types: [opened, synchronize] types: [opened, synchronize]
paths: paths:
- 'src/lib/exampleKcl.ts' - 'src/lib/exampleKcl.ts'
- 'public/kcl-samples/bracket/main.kcl'
permissions: permissions:
contents: read contents: read
@ -22,7 +23,7 @@ jobs:
uses: actions/github-script@v7 uses: actions/github-script@v7
with: with:
script: | script: |
const message = '`src/lib/exampleKcl.ts` has been updated in this PR, please review and update the `src/routes/onboarding`, if needed.'; const message = '`public/kcl-samples/bracket/main.kcl` or `src/lib/exampleKcl.ts` has been updated in this PR, please review and update the `src/routes/onboarding`, if needed.';
const issue_number = context.payload.pull_request.number; const issue_number = context.payload.pull_request.number;
const owner = context.repo.owner; const owner = context.repo.owner;
const repo = context.repo.repo; const repo = context.repo.repo;

View File

@ -11,7 +11,7 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
yarn-unit-test: npm-unit-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -19,14 +19,11 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- run: yarn install - run: npm install
working-directory: packages/codemirror-lang-kcl
- run: yarn tsc - run: npm run tsc --workspace=packages/codemirror-lang-kcl
working-directory: packages/codemirror-lang-kcl
- name: run unit tests - name: run unit tests
run: yarn test run: npm run test --workspace=packages/codemirror-lang-kcl
working-directory: packages/codemirror-lang-kcl

View File

@ -97,11 +97,11 @@ jobs:
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- name: Install dependencies - name: Install dependencies
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
run: yarn run: npm install
- name: Download Wasm Cache - name: Download Wasm Cache
id: download-wasm id: download-wasm
@ -154,7 +154,7 @@ jobs:
- name: Build Wasm - name: Build Wasm
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }} if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
shell: bash shell: bash
run: yarn build:wasm run: npm run build:wasm
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
@ -197,12 +197,12 @@ jobs:
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- name: Install dependencies - name: Install dependencies
id: deps-install id: deps-install
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
run: yarn run: npm install
- name: Cache Playwright Browsers - name: Cache Playwright Browsers
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
@ -210,22 +210,22 @@ jobs:
with: with:
path: | path: |
~/.cache/ms-playwright/ ~/.cache/ms-playwright/
key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }} key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
- name: Install Playwright Browsers - name: Install Playwright Browsers
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
run: yarn playwright install --with-deps run: npm run playwright install --with-deps
- name: build web - name: build web
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
run: yarn tronb:vite:dev run: npm run tronb:vite:dev
- name: Run ubuntu/chrome snapshots - name: Run ubuntu/chrome snapshots
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
uses: nick-fields/retry@v3.0.2 uses: nick-fields/retry@v3.0.2
with: with:
shell: bash shell: bash
command: yarn test:snapshots command: npm run test:snapshots
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
env: env:
@ -321,12 +321,12 @@ jobs:
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- name: Install dependencies - name: Install dependencies
id: deps-install id: deps-install
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
run: yarn run: npm install
- name: Cache Playwright Browsers - name: Cache Playwright Browsers
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
@ -334,15 +334,15 @@ jobs:
with: with:
path: | path: |
~/.cache/ms-playwright/ ~/.cache/ms-playwright/
key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }} key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
- name: Install Playwright Browsers - name: Install Playwright Browsers
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
run: yarn playwright install --with-deps run: npm run playwright install --with-deps
- name: Build web - name: Build web
if: needs.conditions.outputs.should-run == 'true' if: needs.conditions.outputs.should-run == 'true'
run: yarn tronb:vite:dev run: npm run tronb:vite:dev
- name: Start Vector - name: Start Vector
if: ${{ needs.conditions.outputs.should-run == 'true' && !contains(matrix.os, 'windows') }} if: ${{ needs.conditions.outputs.should-run == 'true' && !contains(matrix.os, 'windows') }}

View File

@ -21,10 +21,10 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- run: yarn install - run: npm install
- run: yarn generate:machine-api - run: npm run generate:machine-api
- run: yarn fmt - run: npm run fmt || true
- name: check for changes - name: check for changes
id: git-check id: git-check
run: | run: |

View File

@ -56,21 +56,19 @@ jobs:
node-version-file: ".nvmrc" node-version-file: ".nvmrc"
- name: Install dependencies - name: Install dependencies
run: | run: |
yarn install npm install
cd rust/kcl-language-server
yarn install
- name: Run tests - name: Run tests
run: | run: |
cd rust/kcl-language-server cd rust/kcl-language-server
yarn build npm run build
yarn test-compile npm run test-compile
ls -la dist ls -la dist
xvfb-run -a yarn test xvfb-run -a npm run test
if: runner.os == 'Linux' if: runner.os == 'Linux'
- name: Run tests - name: Run tests
run: | run: |
cd rust/kcl-language-server cd rust/kcl-language-server
yarn test npm run test
if: runner.os != 'Linux' if: runner.os != 'Linux'
build-release: build-release:
strategy: strategy:
@ -183,19 +181,20 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
cd rust/kcl-language-server cd rust/kcl-language-server
# npm will symlink which will cause issues w tarballing later
yarn install yarn install
- name: Package Extension (release) - name: Package Extension (release)
if: startsWith(github.event.ref, 'refs/tags/') if: startsWith(github.event.ref, 'refs/tags/')
run: | run: |
cd rust/kcl-language-server cd rust/kcl-language-server
npx vsce package -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} npx vsce package --yarn -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }}
- name: Package Extension (nightly) - name: Package Extension (nightly)
if: startsWith(github.event.ref, 'refs/tags/') == false if: startsWith(github.event.ref, 'refs/tags/') == false
run: | run: |
cd rust/kcl-language-server cd rust/kcl-language-server
npx vsce package -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} --pre-release npx vsce package --yarn -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} --pre-release
- name: remove server - name: remove server
if: matrix.target == 'x86_64-unknown-linux-gnu' if: matrix.target == 'x86_64-unknown-linux-gnu'
@ -207,13 +206,13 @@ jobs:
if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/') if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/')
run: | run: |
cd rust/kcl-language-server cd rust/kcl-language-server
npx vsce package -o ../build/kcl-language-server-no-server.vsix npx vsce package --yarn -o ../build/kcl-language-server-no-server.vsix
- name: Package Extension (no server, nightly) - name: Package Extension (no server, nightly)
if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/') == false if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/') == false
run: | run: |
cd rust/kcl-language-server cd rust/kcl-language-server
npx vsce package -o ../build/kcl-language-server-no-server.vsix --pre-release npx vsce package --yarn -o ../build/kcl-language-server-no-server.vsix --pre-release
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@ -244,8 +243,8 @@ jobs:
lld \ lld \
musl-dev \ musl-dev \
nodejs \ nodejs \
yarn \ npm \
npm yarn
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -272,19 +271,20 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
cd rust/kcl-language-server cd rust/kcl-language-server
# npm will symlink which will cause issues w tarballing later
yarn install yarn install
- name: Package Extension (release) - name: Package Extension (release)
if: startsWith(github.event.ref, 'refs/tags/') if: startsWith(github.event.ref, 'refs/tags/')
run: | run: |
cd rust/kcl-language-server cd rust/kcl-language-server
npx vsce package -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64 npx vsce package --yarn -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64
- name: Package Extension (release) - name: Package Extension (release)
if: startsWith(github.event.ref, 'refs/tags/') == false if: startsWith(github.event.ref, 'refs/tags/') == false
run: | run: |
cd rust/kcl-language-server cd rust/kcl-language-server
npx vsce package -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64 --pre-release npx vsce package --yarn -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64 --pre-release
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4

View File

@ -19,7 +19,7 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- name: Find tag workflow id - name: Find tag workflow id
id: tag_workflow_id id: tag_workflow_id
@ -105,7 +105,7 @@ jobs:
- name: Override release notes - name: Override release notes
env: env:
NOTES: ${{ github.event.release.body }} NOTES: ${{ github.event.release.body }}
run: yarn files:set-notes run: npm run files:set-notes
- name: Authenticate to Google Cloud - name: Authenticate to Google Cloud
uses: 'google-github-actions/auth@v2.1.8' uses: 'google-github-actions/auth@v2.1.8'
@ -126,7 +126,7 @@ jobs:
destination: 'dl.kittycad.io/releases/modeling-app' destination: 'dl.kittycad.io/releases/modeling-app'
- name: Invalidate bucket cache on latest*.yml and last_download.json files - name: Invalidate bucket cache on latest*.yml and last_download.json files
run: yarn files:invalidate-bucket run: npm run files:invalidate-bucket
- name: Upload release files to Github - name: Upload release files to Github
if: ${{ github.event_name == 'release' }} if: ${{ github.event_name == 'release' }}

View File

@ -16,18 +16,18 @@ permissions:
actions: read actions: read
jobs: jobs:
yarn-fmt-check: npm-fmt-check:
runs-on: 'ubuntu-22.04' runs-on: 'ubuntu-22.04'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- run: yarn install - run: npm install
- run: yarn fmt-check - run: npm run fmt:check
yarn-build-wasm: npm-build-wasm:
# Build the wasm blob once on the fastest runner. # Build the wasm blob once on the fastest runner.
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64 runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
steps: steps:
@ -36,10 +36,10 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- name: Install dependencies - name: Install dependencies
run: yarn install run: npm install
- name: Use correct Rust toolchain - name: Use correct Rust toolchain
shell: bash shell: bash
@ -62,7 +62,7 @@ jobs:
- name: Build Wasm - name: Build Wasm
shell: bash shell: bash
run: yarn build:wasm run: npm run build:wasm
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
with: with:
@ -76,17 +76,17 @@ jobs:
path: | path: |
rust/kcl-lib/bindings/* rust/kcl-lib/bindings/*
yarn-tsc: npm-tsc:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: yarn-build-wasm needs: npm-build-wasm
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- run: yarn install - run: npm install
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@ -104,19 +104,19 @@ jobs:
mkdir rust/kcl-lib/bindings mkdir rust/kcl-lib/bindings
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/ cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
- run: yarn tsc - run: npm run tsc
yarn-lint: npm-lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: yarn-build-wasm needs: npm-build-wasm
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- run: yarn install - run: npm install
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@ -134,19 +134,19 @@ jobs:
mkdir rust/kcl-lib/bindings mkdir rust/kcl-lib/bindings
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/ cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
- run: yarn lint - run: npm run lint
yarn-circular-dependencies: npm-circular-dependencies:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: yarn-build-wasm needs: npm-build-wasm
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- run: yarn install - run: npm install
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@ -164,7 +164,7 @@ jobs:
mkdir rust/kcl-lib/bindings mkdir rust/kcl-lib/bindings
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/ cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
- run: yarn circular-deps:diff - run: npm run circular-deps:diff
python-codespell: python-codespell:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
@ -179,18 +179,18 @@ jobs:
- name: Run codespell - name: Run codespell
run: codespell --config .codespellrc # Edit this file to tweak the typo list and other configuration. run: codespell --config .codespellrc # Edit this file to tweak the typo list and other configuration.
yarn-unit-test-kcl-samples: npm-unit-test-kcl-samples:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: yarn-build-wasm needs: npm-build-wasm
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- run: yarn install - run: npm install
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc - uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
with: with:
tool: wasm-pack tool: wasm-pack
@ -211,31 +211,31 @@ jobs:
mkdir rust/kcl-lib/bindings mkdir rust/kcl-lib/bindings
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/ cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
- run: yarn simpleserver:bg - run: npm run simpleserver:bg
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
- name: Install Chromium Browser - name: Install Chromium Browser
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
run: yarn playwright install chromium --with-deps run: npm run playwright install chromium --with-deps
- name: run unit tests for kcl samples - name: run unit tests for kcl samples
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
run: yarn test:unit:kcl-samples run: npm run test:unit:kcl-samples
env: env:
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
yarn-unit-test: npm-unit-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: yarn-build-wasm needs: npm-build-wasm
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'npm'
- run: yarn install - run: npm install
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc - uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
with: with:
tool: wasm-pack tool: wasm-pack
@ -256,16 +256,16 @@ jobs:
mkdir rust/kcl-lib/bindings mkdir rust/kcl-lib/bindings
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/ cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
- run: yarn simpleserver:bg - run: npm run simpleserver:bg
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
- name: Install Chromium Browser - name: Install Chromium Browser
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
run: yarn playwright install chromium --with-deps run: npm run playwright install chromium --with-deps
- name: Run unit tests - name: Run unit tests
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
run: xvfb-run -a yarn test:unit run: xvfb-run -a npm run test:unit
env: env:
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}

View File

@ -27,7 +27,7 @@ jobs:
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
- run: yarn install - run: npm install
- name: Push tag - name: Push tag
run: | run: |

2
.gitignore vendored
View File

@ -31,6 +31,7 @@ result
# rust # rust
rust/target rust/target
rust/kcl-lib/bindings rust/kcl-lib/bindings
rust/kcl-language-server/server
public/kcl_wasm_lib_bg.wasm public/kcl_wasm_lib_bg.wasm
rust/lcov.info rust/lcov.info
rust/kcl-wasm-lib/pkg rust/kcl-wasm-lib/pkg
@ -83,3 +84,4 @@ dist
venv venv
.vscode-test .vscode-test
.biome/

View File

@ -1,4 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh" . "$(dirname -- "$0")/_/husky.sh"
yarn fmt-check npm run fmt-check

1
.npmrc Normal file
View File

@ -0,0 +1 @@
legacy-peer-deps=true

View File

@ -20,28 +20,23 @@ WASM_PACK ?= ~/.cargo/bin/wasm-pack
endif endif
.PHONY: install .PHONY: install
install: node_modules/.yarn-integrity $(CARGO) $(WASM_PACK) ## Install dependencies install: node_modules/.package-lock.json $(CARGO) $(WASM_PACK) ## Install dependencies
node_modules/.yarn-integrity: package.json yarn.lock node_modules/.package-lock.json: package.json package-lock.json
yarn install npm install
ifdef POWERSHELL
@ type nul > $@
else
@ touch $@
endif
$(CARGO): $(CARGO):
ifdef WINDOWS ifdef WINDOWS
yarn install:rust:windows npm run install:rust:windows
else else
yarn install:rust npm run install:rust
endif endif
$(WASM_PACK): $(WASM_PACK):
ifdef WINDOWS ifdef WINDOWS
yarn install:wasm-pack:cargo npm run install:wasm-pack:cargo
else else
yarn install:wasm-pack:sh npm run install:wasm-pack:sh
endif endif
############################################################################### ###############################################################################
@ -65,16 +60,16 @@ build-desktop: install public/kcl_wasm_lib_bg.wasm .vite/build/main.js
public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES) $(RUST_SOURCES) public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES) $(RUST_SOURCES)
ifdef WINDOWS ifdef WINDOWS
yarn build:wasm:dev:windows npm run build:wasm:dev:windows
else else
yarn build:wasm:dev npm run build:wasm:dev
endif endif
build/index.html: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES) build/index.html: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
yarn build:local npm run build:local
.vite/build/main.js: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES) .vite/build/main.js: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
yarn tronb:vite:dev npm run tronb:vite:dev
############################################################################### ###############################################################################
# CHECK # CHECK
@ -84,12 +79,12 @@ check: format lint
.PHONY: format .PHONY: format
format: install ## Format the code format: install ## Format the code
yarn fmt npm run fmt
.PHONY: lint .PHONY: lint
lint: install ## Lint the code lint: install ## Lint the code
yarn tsc npm run tsc
yarn lint npm run lint
############################################################################### ###############################################################################
# RUN # RUN
@ -101,11 +96,11 @@ run: run-$(TARGET)
.PHONY: run-web .PHONY: run-web
run-web: install build-web ## Start the web app run-web: install build-web ## Start the web app
yarn start npm run start
.PHONY: run-desktop .PHONY: run-desktop
run-desktop: install build-desktop ## Start the desktop app run-desktop: install build-desktop ## Start the desktop app
yarn tron:start npm run tron:start
############################################################################### ###############################################################################
# TEST # TEST
@ -120,7 +115,7 @@ test: test-unit test-e2e
.PHONY: test-unit .PHONY: test-unit
test-unit: install ## Run the unit tests test-unit: install ## Run the unit tests
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 ) @ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
yarn test:unit npm run test:unit
.PHONY: test-e2e .PHONY: test-e2e
test-e2e: test-e2e-$(TARGET) test-e2e: test-e2e-$(TARGET)
@ -129,17 +124,17 @@ test-e2e: test-e2e-$(TARGET)
test-e2e-web: install build-web ## Run the web e2e tests test-e2e-web: install build-web ## Run the web e2e tests
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 ) @ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
ifdef E2E_GREP ifdef E2E_GREP
yarn chrome:test --headed --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES) npm run chrome:test -- --headed --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES)
else else
yarn chrome:test --headed --workers='100%' npm run chrome:test -- --headed --workers='100%'
endif endif
.PHONY: test-e2e-desktop .PHONY: test-e2e-desktop
test-e2e-desktop: install build-desktop ## Run the desktop e2e tests test-e2e-desktop: install build-desktop ## Run the desktop e2e tests
ifdef E2E_GREP ifdef E2E_GREP
yarn test:playwright:electron --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES) npm run test:playwright:electron -- --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES)
else else
yarn test:playwright:electron --workers='100%' npm run test:playwright:electron -- --workers='100%'
endif endif
############################################################################### ###############################################################################
@ -174,5 +169,5 @@ endif
# It should work for you other Linux users. # It should work for you other Linux users.
lee-electron-test: lee-electron-test:
Xephyr -br -ac -noreset -screen 1200x500 :2 & Xephyr -br -ac -noreset -screen 1200x500 :2 &
DISPLAY=:2 NODE_ENV=development PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:4444/ yarn tron:test -g "when using the file tree" DISPLAY=:2 NODE_ENV=development PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:4444/ npm run tron:test -g "when using the file tree"
killall Xephyr killall Xephyr

124
README.md
View File

@ -62,39 +62,39 @@ fnm use
Install the NPM dependencies with: Install the NPM dependencies with:
``` ```
yarn install npm install
``` ```
This project uses a lot of Rust compiled to [WASM](https://webassembly.org/) within it. We have package scripts to run rustup, see `package.json` for reference: This project uses a lot of Rust compiled to [WASM](https://webassembly.org/) within it. We have package scripts to run rustup, see `package.json` for reference:
``` ```
# macOS/Linux # macOS/Linux
yarn install:rust npm run install:rust
yarn install:wasm-pack:sh npm run install:wasm-pack:sh
# Windows # Windows
yarn install:rust:windows npm run install:rust:windows
yarn install:wasm-pack:cargo npm run install:wasm-pack:cargo
``` ```
Then to build the WASM layer, run: Then to build the WASM layer, run:
``` ```
# macOS/Linux # macOS/Linux
yarn build:wasm npm run build:wasm
# Windows # Windows
yarn build:wasm:windows npm run build:wasm:windows
``` ```
Or if you have the `gh` cli installed and want to download the latest main wasm bundle. Note that on Windows, you need to associate .ps1 files with PowerShell, which can be done via the right click menu, selecting `C:\Program Files\PowerShell\7\pwsh.exe`, and you can install tools like `gh` via `yarn install:tools:windows`. Or if you have the `gh` cli installed and want to download the latest main wasm bundle. Note that on Windows, you need to associate .ps1 files with PowerShell, which can be done via the right click menu, selecting `C:\Program Files\PowerShell\7\pwsh.exe`, and you can install tools like `gh` via `npm run install:tools:windows`.
``` ```
# macOS/Linux # macOS/Linux
yarn fetch:wasm npm run fetch:wasm
# Windows # Windows
yarn fetch:wasm:windows npm run fetch:wasm:windows
``` ```
That will build the WASM binary and put in the `public` dir (though gitignored). That will build the WASM binary and put in the `public` dir (though gitignored).
@ -102,7 +102,7 @@ That will build the WASM binary and put in the `public` dir (though gitignored).
Finally, to run the web app only, run: Finally, to run the web app only, run:
``` ```
yarn start npm start
``` ```
If you're not a Zoo employee you won't be able to access the dev environment, you should copy everything from `.env.production` to `.env.development.local` to make it point to production instead, then when you navigate to `localhost:3000` the easiest way to sign in is to paste `localStorage.setItem('TOKEN_PERSIST_KEY', "your-token-from-https://zoo.dev/account/api-tokens")` replacing the with a real token from https://zoo.dev/account/api-tokens of course, then navigate to `localhost:3000` again. Note that navigating to `localhost:3000/signin` removes your token so you will need to set the token again. If you're not a Zoo employee you won't be able to access the dev environment, you should copy everything from `.env.production` to `.env.development.local` to make it point to production instead, then when you navigate to `localhost:3000` the easiest way to sign in is to paste `localStorage.setItem('TOKEN_PERSIST_KEY', "your-token-from-https://zoo.dev/account/api-tokens")` replacing the with a real token from https://zoo.dev/account/api-tokens of course, then navigate to `localhost:3000` again. Note that navigating to `localhost:3000/signin` removes your token so you will need to set the token again.
@ -122,17 +122,17 @@ Third-Party Cookies".
## Desktop ## Desktop
To spin up the desktop app, `yarn install` and `yarn build:wasm` need to have been done before hand then: To spin up the desktop app, `npm install` and `npm run build:wasm` need to have been done before hand then:
``` ```
yarn tron:start npm run tron:start
``` ```
This will start the application and hot-reload on changes. This will start the application and hot-reload on changes.
Devtools can be opened with the usual Command-Option-I (macOS) or Ctrl-Shift-I (Linux and Windows). Devtools can be opened with the usual Command-Option-I (macOS) or Ctrl-Shift-I (Linux and Windows).
To package the app for your platform with electron-builder, run `yarn tronb:package:dev` (or `yarn tronb:package:prod` to point to the .env.production variables). To package the app for your platform with electron-builder, run `npm run tronb:package:dev` (or `npm run tronb:package:prod` to point to the .env.production variables).
## Checking out commits / Bisecting ## Checking out commits / Bisecting
@ -141,9 +141,9 @@ Which commands from setup are one off vs. need to be run every time?
The following will need to be run when checking out a new commit and guarantees the build is not stale: The following will need to be run when checking out a new commit and guarantees the build is not stale:
```bash ```bash
yarn install npm install
yarn build:wasm npm run build:wasm
yarn start # or yarn build:local && yarn serve for slower but more production-like build npm start # or npm run build:local && npm run serve for slower but more production-like build
``` ```
## Before submitting a PR ## Before submitting a PR
@ -153,10 +153,10 @@ Before you submit a contribution PR to this repo, please ensure that:
- There is a corresponding issue for the changes you want to make, so that discussion of approach can be had before work begins. - There is a corresponding issue for the changes you want to make, so that discussion of approach can be had before work begins.
- You have separated out refactoring commits from feature commits as much as possible - You have separated out refactoring commits from feature commits as much as possible
- You have run all of the following commands locally: - You have run all of the following commands locally:
- `yarn fmt` - `npm run fmt`
- `yarn tsc` - `npm run tsc`
- `yarn test` - `npm run test`
- Here they are all together: `yarn fmt && yarn tsc && yarn test` - Here they are all together: `npm run fmt && npm run tsc && npm run test`
## Release a new version ## Release a new version
@ -250,55 +250,29 @@ You will need a `./e2e/playwright/playwright-secrets.env` file:
$ touch ./e2e/playwright/playwright-secrets.env $ touch ./e2e/playwright/playwright-secrets.env
$ cat ./e2e/playwright/playwright-secrets.env $ cat ./e2e/playwright/playwright-secrets.env
token=<dev.zoo.dev/account/api-tokens> token=<dev.zoo.dev/account/api-tokens>
snapshottoken=<your-snapshot-token> snapshottoken=<zoo.dev/account/api-tokens>
``` ```
or use `export` to set the environment variables `token` and `snapshottoken`.
For a portable way to run Playwright you'll need Docker. #### Snapshot tests (Google Chrome on Ubuntu only)
#### Generic example Only Ubunu and Google Chrome is supported for the set of tests evaluating screenshot snapshots.
If you don't run Ubuntu locally or in a VM, you may use a GitHub Codespace.
After that, open a terminal and run:
```bash
docker run --network host --rm --init -it playwright/chrome:playwright-x.xx.x
``` ```
npm run playwright -- install chrome
and in another terminal, run: npm run test:snapshots
```bash
PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:4444/ yarn playwright test --project="Google Chrome" <test suite>
``` ```
You may use `-- --update-snapshots` as needed.
#### Specific example #### Electron flow tests (Chromium on Ubuntu, macOS, Windows)
open a terminal and run:
```bash
docker run --network host --rm --init -it playwright/chrome:playwright-1.46.0
```
and in another terminal, run:
```bash
PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:4444/ yarn playwright test --project="Google Chrome" e2e/playwright/command-bar-tests.spec.ts
```
run a specific test change the test from `test('...` to `test.only('...`
(note if you commit this, the tests will instantly fail without running any of the tests)
**Gotcha**: running the docker container with a mismatched image against your `./node_modules/playwright` will cause a failure. Make sure the versions are matched and up to date.
run headed
``` ```
yarn playwright test --headed npm run playwright -- install chromium
npm run test:playwright:electron:local
``` ```
You may use `-- -g "my test"` to match specific test titles, or `-- path/to/file.spec.ts` for a test file.
run with step through debugger #### Debugger
```
PWDEBUG=1 yarn playwright test
```
However, if you want a debugger I recommend using VSCode and the `playwright` extension, as the above command is a cruder debugger that steps into every function call which is annoying. However, if you want a debugger I recommend using VSCode and the `playwright` extension, as the above command is a cruder debugger that steps into every function call which is annoying.
With the extension you can set a breakpoint after `waitForDefaultPlanesVisibilityChange` in order to skip app loading, then the vscode debugger's "step over" is much better for being able to stay at the right level of abstraction as you debug the code. With the extension you can set a breakpoint after `waitForDefaultPlanesVisibilityChange` in order to skip app loading, then the vscode debugger's "step over" is much better for being able to stay at the right level of abstraction as you debug the code.
@ -308,7 +282,7 @@ Or comment out browsers in `playwright.config.ts`.
note chromium has encoder compat issues which is why were testing against the branded 'Google Chrome' note chromium has encoder compat issues which is why were testing against the branded 'Google Chrome'
You may consider using the VSCode extension, it's useful for running individual threads, but some some reason the "record a test" is locked to chromium with we can't use. A work around is to us the CI `yarn playwright codegen -b wk --load-storage ./store localhost:3000` You may consider using the VSCode extension, it's useful for running individual threads, but some some reason the "record a test" is locked to chromium with we can't use. A work around is to us the CI `npm run playwright codegen -b wk --load-storage ./store localhost:3000`
<details> <details>
<summary> <summary>
@ -351,21 +325,21 @@ However because much of our tests involve clicking in the stream at specific loc
If you already haven't, run the following: If you already haven't, run the following:
``` ```
yarn npm
yarn build:wasm npm run build:wasm
yarn start npm start
``` ```
and finally: and finally:
``` ```
yarn test:unit npm run test:unit
``` ```
For individual testing: For individual testing:
``` ```
yarn test abstractSyntaxTree -t "unexpected closed curly brace" --silent=false npm run test abstractSyntaxTree -t "unexpected closed curly brace" --silent=false
``` ```
Which will run our suite of [Vitest unit](https://vitest.dev/) and [React Testing Library E2E](https://testing-library.com/docs/react-testing-library/intro) tests, in interactive mode by default. Which will run our suite of [Vitest unit](https://vitest.dev/) and [React Testing Library E2E](https://testing-library.com/docs/react-testing-library/intro) tests, in interactive mode by default.
@ -439,16 +413,16 @@ Part of the CI CD pipeline performs static analysis on the code. Use the followi
The following set of commands should get us closer to one and done commands to instantly retest issues. The following set of commands should get us closer to one and done commands to instantly retest issues.
``` ```
yarn test-setup npm run test-setup
``` ```
> Gotcha, are packages up to date and is the wasm built? > Gotcha, are packages up to date and is the wasm built?
``` ```
yarn tsc npm run tsc
yarn fmt-check npm run fmt:check
yarn lint npm run lint
yarn test:unit:local npm run test:unit:local
``` ```
> Gotcha: Our unit tests have integration tests in them. You need to run a localhost server to run the unit tests. > Gotcha: Our unit tests have integration tests in them. You need to run a localhost server to run the unit tests.
@ -460,10 +434,10 @@ yarn test:unit:local
These E2E tests run in electron. There are tests that are skipped if they are ran in a windows, linux, or macos environment. We can use playwright tags to implement test skipping. These E2E tests run in electron. There are tests that are skipped if they are ran in a windows, linux, or macos environment. We can use playwright tags to implement test skipping.
``` ```
yarn test:playwright:electron:local npm run test:playwright:electron:local
yarn test:playwright:electron:windows:local npm run test:playwright:electron:windows:local
yarn test:playwright:electron:macos:local npm run test:playwright:electron:macos:local
yarn test:playwright:electron:ubuntu:local npm run test:playwright:electron:ubuntu:local
``` ```
> Why does it say local? The CI CD commands that run in the pipeline cannot be ran locally. A single command will not properly setup the testing environment locally. > Why does it say local? The CI CD commands that run in the pipeline cannot be ran locally. A single command will not properly setup the testing environment locally.

48
biome.json Normal file
View File

@ -0,0 +1,48 @@
{
"$schema": "https://biomejs.dev/schemas/1.6.0/schema.json",
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedVariables": "error"
},
"suspicious": {
"noExplicitAny": "warn"
},
"style": {
"useBlockStatements": "error",
"useShorthandArrayType": "error"
}
}
},
"formatter": {
"enabled": true,
"indentWidth": 2,
"indentStyle": "space",
"lineWidth": 80,
"formatWithErrors": true
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"trailingCommas": "es5",
"semicolons": "asNeeded"
},
"parser": {
"unsafeParameterDecoratorsEnabled": true
}
},
"css": {
"parser": {
"cssModules": true
}
},
"files": {
"ignore": ["**/*.json"]
}
}

View File

@ -28,11 +28,11 @@ angledLine(
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | Which sketch should this path be added to? | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | Which sketch should this path be added to? | Yes |
| `angle` | [`number`](/docs/kcl/types/number) | Which angle should the line be drawn at? | Yes | | `angle` | [`number`](/docs/kcl/types/number) | Which angle should the line be drawn at? | Yes |
| `length` | [`number`](/docs/kcl/types/number) | Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `lengthAbsoluteEndX`, `lengthAbsoluteEndY` can be given. | No | | `length` | [`number`](/docs/kcl/types/number) | Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `lengthX` | [`number`](/docs/kcl/types/number) | Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `lengthAbsoluteEndX`, `lengthAbsoluteEndY` can be given. | No | | `lengthX` | [`number`](/docs/kcl/types/number) | Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `lengthY` | [`number`](/docs/kcl/types/number) | Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `lengthAbsoluteEndX`, `lengthAbsoluteEndY` can be given. | No | | `lengthY` | [`number`](/docs/kcl/types/number) | Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `endAbsoluteX` | [`number`](/docs/kcl/types/number) | Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `lengthAbsoluteEndX`, `lengthAbsoluteEndY` can be given. | No | | `endAbsoluteX` | [`number`](/docs/kcl/types/number) | Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| `endAbsoluteY` | [`number`](/docs/kcl/types/number) | Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `lengthAbsoluteEndX`, `lengthAbsoluteEndY` can be given. | No | | `endAbsoluteY` | [`number`](/docs/kcl/types/number) | Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
| [`tag`](/docs/kcl/types/tag) | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | Create a new tag which refers to this line | No | | [`tag`](/docs/kcl/types/tag) | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | Create a new tag which refers to this line | No |
### Returns ### Returns

View File

@ -10,8 +10,10 @@ Draw an angled line from the current origin, constructing a line segment such th
```js ```js
angledLineThatIntersects( angledLineThatIntersects(
data: AngledLineThatIntersectsData,
sketch: Sketch, sketch: Sketch,
angle: number,
intersectTag: TagIdentifier,
offset?: number,
tag?: TagDeclarator, tag?: TagDeclarator,
): Sketch ): Sketch
``` ```
@ -21,9 +23,11 @@ angledLineThatIntersects(
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`AngledLineThatIntersectsData`](/docs/kcl/types/AngledLineThatIntersectsData) | Data for drawing an angled line that intersects with a given line. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | Which sketch should this path be added to? | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | | Yes | | `angle` | [`number`](/docs/kcl/types/number) | Which angle should the line be drawn at? | Yes |
| [`tag`](/docs/kcl/types/tag) | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No | | `intersectTag` | [`TagIdentifier`](/docs/kcl/types#tag-identifier) | The tag of the line to intersect with | Yes |
| `offset` | [`number`](/docs/kcl/types/number) | The offset from the intersecting line. Defaults to 0. | No |
| [`tag`](/docs/kcl/types/tag) | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | Create a new tag which refers to this line | No |
### Returns ### Returns
@ -38,11 +42,7 @@ exampleSketch = startSketchOn(XZ)
|> line(endAbsolute = [5, 10]) |> line(endAbsolute = [5, 10])
|> line(endAbsolute = [-10, 10], tag = $lineToIntersect) |> line(endAbsolute = [-10, 10], tag = $lineToIntersect)
|> line(endAbsolute = [0, 20]) |> line(endAbsolute = [0, 20])
|> angledLineThatIntersects({ |> angledLineThatIntersects(angle = 80, intersectTag = lineToIntersect, offset = 10)
angle = 80,
intersectTag = lineToIntersect,
offset = 10
}, %)
|> close() |> close()
example = extrude(exampleSketch, length = 10) example = extrude(exampleSketch, length = 10)

File diff suppressed because one or more lines are too long

View File

@ -24,8 +24,8 @@ atan2(
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `y` | [`number`](/docs/kcl/types/number) | | Yes | | `y` | [`number`](/docs/kcl/types/number) | Y | Yes |
| `x` | [`number`](/docs/kcl/types/number) | | Yes | | `x` | [`number`](/docs/kcl/types/number) | X | Yes |
### Returns ### Returns
@ -37,7 +37,7 @@ atan2(
```js ```js
sketch001 = startSketchOn(XZ) sketch001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> angledLine(angle = toDegrees(atan2(1.25, 2)), length = 20) |> angledLine(angle = toDegrees(atan2(y = 1.25, x = 2)), length = 20)
|> yLine(endAbsolute = 0) |> yLine(endAbsolute = 0)
|> close() |> close()

View File

@ -80,7 +80,7 @@ part001 = cube([0, 0], 20)
// We tag the chamfer to reference it later. // We tag the chamfer to reference it later.
|> chamfer(length = 10, tags = [getOppositeEdge(line1)], tag = $chamfer1) |> chamfer(length = 10, tags = [getOppositeEdge(line1)], tag = $chamfer1)
sketch001 = startSketchOn(part001, chamfer1) sketch001 = startSketchOn(part001, face = chamfer1)
|> startProfileAt([10, 10], %) |> startProfileAt([10, 10], %)
|> line(end = [2, 0]) |> line(end = [2, 0])
|> line(end = [0, 2]) |> line(end = [0, 2])

View File

@ -9,6 +9,8 @@ layout: manual
### `std` ### `std`
- [`END`](/docs/kcl/consts/std-END)
- [`START`](/docs/kcl/consts/std-START)
- [`X`](/docs/kcl/consts/std-X) - [`X`](/docs/kcl/consts/std-X)
- [`XY`](/docs/kcl/consts/std-XY) - [`XY`](/docs/kcl/consts/std-XY)
- [`XZ`](/docs/kcl/consts/std-XZ) - [`XZ`](/docs/kcl/consts/std-XZ)

View File

@ -0,0 +1,15 @@
---
title: "std::END"
excerpt: "Identifies the ending face of an extrusion. I.e., the new face created by an extrusion."
layout: manual
---
Identifies the ending face of an extrusion. I.e., the new face created by an extrusion.
```js
std::END: string = 'end'
```

View File

@ -0,0 +1,15 @@
---
title: "std::START"
excerpt: "Identifies the starting face of an extrusion. I.e., the face which is extruded."
layout: manual
---
Identifies the starting face of an extrusion. I.e., the face which is extruded.
```js
std::START: string = 'start'
```

View File

@ -69,11 +69,11 @@ case = startSketchOn(-XZ)
|> close() |> close()
|> extrude(length = 65) |> extrude(length = 65)
thing1 = startSketchOn(case, 'end') thing1 = startSketchOn(case, face = END)
|> circle(center = [-size / 2, -size / 2], radius = 25) |> circle(center = [-size / 2, -size / 2], radius = 25)
|> extrude(length = 50) |> extrude(length = 50)
thing2 = startSketchOn(case, 'end') thing2 = startSketchOn(case, face = END)
|> circle(center = [size / 2, -size / 2], radius = 25) |> circle(center = [size / 2, -size / 2], radius = 25)
|> extrude(length = 50) |> extrude(length = 50)

View File

@ -24,12 +24,14 @@ layout: manual
* **std** * **std**
* [`Axis2d`](kcl/types/Axis2d) * [`Axis2d`](kcl/types/Axis2d)
* [`Axis3d`](kcl/types/Axis3d) * [`Axis3d`](kcl/types/Axis3d)
* [`END`](kcl/consts/std-END)
* [`Edge`](kcl/types/Edge) * [`Edge`](kcl/types/Edge)
* [`Face`](kcl/types/Face) * [`Face`](kcl/types/Face)
* [`Helix`](kcl/types/Helix) * [`Helix`](kcl/types/Helix)
* [`Plane`](kcl/types/Plane) * [`Plane`](kcl/types/Plane)
* [`Point2d`](kcl/types/Point2d) * [`Point2d`](kcl/types/Point2d)
* [`Point3d`](kcl/types/Point3d) * [`Point3d`](kcl/types/Point3d)
* [`START`](kcl/consts/std-START)
* [`Sketch`](kcl/types/Sketch) * [`Sketch`](kcl/types/Sketch)
* [`Solid`](kcl/types/Solid) * [`Solid`](kcl/types/Solid)
* [`X`](kcl/consts/std-X) * [`X`](kcl/consts/std-X)
@ -78,6 +80,7 @@ layout: manual
* [`hole`](kcl/hole) * [`hole`](kcl/hole)
* [`hollow`](kcl/hollow) * [`hollow`](kcl/hollow)
* [`intersect`](kcl/intersect) * [`intersect`](kcl/intersect)
* [`involuteCircular`](kcl/involuteCircular)
* [`lastSegX`](kcl/lastSegX) * [`lastSegX`](kcl/lastSegX)
* [`lastSegY`](kcl/lastSegY) * [`lastSegY`](kcl/lastSegY)
* [`legAngX`](kcl/legAngX) * [`legAngX`](kcl/legAngX)

File diff suppressed because one or more lines are too long

View File

@ -37,7 +37,7 @@ line(
```js ```js
triangle = startSketchOn(XZ) triangle = startSketchOn(XZ)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
// The 'end' argument means it ends at exactly [10, 0]. // The END argument means it ends at exactly [10, 0].
// This is an absolute measurement, it is NOT relative to // This is an absolute measurement, it is NOT relative to
// the start of the sketch. // the start of the sketch.
|> line(endAbsolute = [10, 0]) |> line(endAbsolute = [10, 0])

View File

@ -20,7 +20,7 @@ offsetPlane(
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `plane` | [`PlaneData`](/docs/kcl/types/PlaneData) | The plane (e.g. 'XY') which this new plane is created from. | Yes | | `plane` | [`PlaneData`](/docs/kcl/types/PlaneData) | The plane (e.g. XY) which this new plane is created from. | Yes |
| `offset` | [`number`](/docs/kcl/types/number) | Distance from the standard plane this new plane will be created at. | Yes | | `offset` | [`number`](/docs/kcl/types/number) | Distance from the standard plane this new plane will be created at. | Yes |
### Returns ### Returns

View File

@ -61,11 +61,11 @@ case = startSketchOn(XY)
|> close(%) |> close(%)
|> extrude(length = 65) |> extrude(length = 65)
thing1 = startSketchOn(case, 'end') thing1 = startSketchOn(case, face = END)
|> circle(center = [-size / 2, -size / 2], radius = 25) |> circle(center = [-size / 2, -size / 2], radius = 25)
|> extrude(length = 50) |> extrude(length = 50)
thing2 = startSketchOn(case, 'end') thing2 = startSketchOn(case, face = END)
|> circle(center = [size / 2, -size / 2], radius = 25) |> circle(center = [size / 2, -size / 2], radius = 25)
|> extrude(length = 50) |> extrude(length = 50)
@ -92,7 +92,7 @@ case = startSketchOn(XY)
|> close(%) |> close(%)
|> extrude(length = 65) |> extrude(length = 65)
thing1 = startSketchOn(case, 'end') thing1 = startSketchOn(case, face = END)
|> circle(center = [-size / 2, -size / 2], radius = 25) |> circle(center = [-size / 2, -size / 2], radius = 25)
|> extrude(length = 50) |> extrude(length = 50)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,8 +18,8 @@ The point is if you want to export the result of a sketch on a face, you only ne
```js ```js
startSketchOn( startSketchOn(
data: SketchData, planeOrSolid: SketchData,
tag?: FaceTag, face?: FaceTag,
): SketchSurface ): SketchSurface
``` ```
@ -28,8 +28,8 @@ startSketchOn(
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`SketchData`](/docs/kcl/types/SketchData) | Data for start sketch on. You can start a sketch on a plane or an solid. | Yes | | `planeOrSolid` | [`SketchData`](/docs/kcl/types/SketchData) | The plane or solid to sketch on | Yes |
| [`tag`](/docs/kcl/types/tag) | [`FaceTag`](/docs/kcl/types/FaceTag) | A tag for a face. | No | | `face` | [`FaceTag`](/docs/kcl/types/FaceTag) | Identify a face of a solid if a solid is specified as the input argument (`plane_or_solid`) | No |
### Returns ### Returns
@ -48,7 +48,7 @@ exampleSketch = startSketchOn(XY)
example = extrude(exampleSketch, length = 5) example = extrude(exampleSketch, length = 5)
exampleSketch002 = startSketchOn(example, 'end') exampleSketch002 = startSketchOn(example, face = END)
|> startProfileAt([1, 1], %) |> startProfileAt([1, 1], %)
|> line(end = [8, 0]) |> line(end = [8, 0])
|> line(end = [0, 8]) |> line(end = [0, 8])
@ -57,7 +57,7 @@ exampleSketch002 = startSketchOn(example, 'end')
example002 = extrude(exampleSketch002, length = 5) example002 = extrude(exampleSketch002, length = 5)
exampleSketch003 = startSketchOn(example002, 'end') exampleSketch003 = startSketchOn(example002, face = END)
|> startProfileAt([2, 2], %) |> startProfileAt([2, 2], %)
|> line(end = [6, 0]) |> line(end = [6, 0])
|> line(end = [0, 6]) |> line(end = [0, 6])
@ -82,7 +82,7 @@ exampleSketch = startSketchOn(XY)
example = extrude(exampleSketch, length = 5, tagEnd = $end01) example = extrude(exampleSketch, length = 5, tagEnd = $end01)
exampleSketch002 = startSketchOn(example, end01) exampleSketch002 = startSketchOn(example, face = end01)
|> startProfileAt([1, 1], %) |> startProfileAt([1, 1], %)
|> line(end = [8, 0]) |> line(end = [8, 0])
|> line(end = [0, 8]) |> line(end = [0, 8])
@ -91,7 +91,7 @@ exampleSketch002 = startSketchOn(example, end01)
example002 = extrude(exampleSketch002, length = 5, tagEnd = $end02) example002 = extrude(exampleSketch002, length = 5, tagEnd = $end02)
exampleSketch003 = startSketchOn(example002, end02) exampleSketch003 = startSketchOn(example002, face = end02)
|> startProfileAt([2, 2], %) |> startProfileAt([2, 2], %)
|> line(end = [6, 0]) |> line(end = [6, 0])
|> line(end = [0, 6]) |> line(end = [0, 6])
@ -113,7 +113,7 @@ exampleSketch = startSketchOn(XY)
example = extrude(exampleSketch, length = 10) example = extrude(exampleSketch, length = 10)
exampleSketch002 = startSketchOn(example, sketchingFace) exampleSketch002 = startSketchOn(example, face = sketchingFace)
|> startProfileAt([1, 1], %) |> startProfileAt([1, 1], %)
|> line(end = [8, 0]) |> line(end = [8, 0])
|> line(end = [0, 8]) |> line(end = [0, 8])
@ -122,7 +122,7 @@ exampleSketch002 = startSketchOn(example, sketchingFace)
example002 = extrude(exampleSketch002, length = 10) example002 = extrude(exampleSketch002, length = 10)
exampleSketch003 = startSketchOn(example002, sketchingFace002) exampleSketch003 = startSketchOn(example002, face = sketchingFace002)
|> startProfileAt([-8, 12], %) |> startProfileAt([-8, 12], %)
|> line(end = [0, 6]) |> line(end = [0, 6])
|> line(end = [6, 0]) |> line(end = [6, 0])
@ -148,7 +148,7 @@ exampleSketch = startSketchOn(XY)
example = revolve(exampleSketch, axis = Y, angle = 180) example = revolve(exampleSketch, axis = Y, angle = 180)
exampleSketch002 = startSketchOn(example, 'end') exampleSketch002 = startSketchOn(example, face = END)
|> startProfileAt([4.5, -5], %) |> startProfileAt([4.5, -5], %)
|> line(end = [0, 5]) |> line(end = [0, 5])
|> line(end = [5, 0]) |> line(end = [5, 0])
@ -182,7 +182,7 @@ example = revolve(
tagEnd = $end01, tagEnd = $end01,
) )
exampleSketch002 = startSketchOn(example, end01) exampleSketch002 = startSketchOn(example, face = end01)
|> startProfileAt([4.5, -5], %) |> startProfileAt([4.5, -5], %)
|> line(end = [0, 5]) |> line(end = [0, 5])
|> line(end = [5, 0]) |> line(end = [5, 0])
@ -196,12 +196,10 @@ example002 = extrude(exampleSketch002, length = 5)
```js ```js
a1 = startSketchOn({ a1 = startSketchOn({
plane = { origin = { x = 0, y = 0, z = 0 },
origin = { x = 0, y = 0, z = 0 }, xAxis = { x = 1, y = 0, z = 0 },
xAxis = { x = 1, y = 0, z = 0 }, yAxis = { x = 0, y = 1, z = 0 },
yAxis = { x = 0, y = 1, z = 0 }, zAxis = { x = 0, y = 0, z = 1 }
zAxis = { x = 0, y = 0, z = 1 }
}
}) })
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [100.0, 0]) |> line(end = [100.0, 0])

View File

@ -11,11 +11,11 @@ Create a helix.
```js ```js
helix( helix(
revolutions: number(_), revolutions: number(_),
angleStart: number(deg), angleStart: number(Angle),
ccw?: bool, ccw?: bool,
radius?: number(mm), radius?: number(Length),
axis?: Axis3d | Edge, axis?: Axis3d | Edge,
length?: number(mm), length?: number(Length),
cylinder?: Solid, cylinder?: Solid,
): Helix ): Helix
``` ```
@ -26,11 +26,11 @@ helix(
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `revolutions` | `number(_)` | Number of revolutions. | Yes | | `revolutions` | `number(_)` | Number of revolutions. | Yes |
| `angleStart` | `number(deg)` | Start angle (in degrees). | Yes | | `angleStart` | `number(Angle)` | Start angle (in degrees). | Yes |
| `ccw` | [`bool`](/docs/kcl/types/bool) | Is the helix rotation counter clockwise? The default is `false`. | No | | `ccw` | [`bool`](/docs/kcl/types/bool) | Is the helix rotation counter clockwise? The default is `false`. | No |
| `radius` | `number(mm)` | Radius of the helix. | No | | `radius` | `number(Length)` | Radius of the helix. | No |
| `axis` | `Axis3d | Edge` | Axis to use for the helix. | No | | `axis` | `Axis3d | Edge` | Axis to use for the helix. | No |
| `length` | `number(mm)` | Length of the helix. This is not necessary if the helix is created around an edge. If not given the length of the edge is used. | No | | `length` | `number(Length)` | Length of the helix. This is not necessary if the helix is created around an edge. If not given the length of the edge is used. | No |
| `cylinder` | [`Solid`](/docs/kcl/types/Solid) | Cylinder to create the helix on. | No | | `cylinder` | [`Solid`](/docs/kcl/types/Solid) | Cylinder to create the helix on. | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Compute the cosine of a number (in radians).
```js ```js
cos(@num: number(rad)): number(_) cos(@num: number(Angle)): number(_)
``` ```
@ -17,7 +17,7 @@ cos(@num: number(rad)): number(_)
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `num` | `number(rad)` | | Yes | | `num` | `number(Angle)` | | Yes |
### Returns ### Returns

View File

@ -11,9 +11,9 @@ cartesian (x/y/z grid) coordinates.
```js ```js
polar( polar(
angle: number(deg), angle: number(Angle),
length: number(mm), length: number(Length),
): [number(mm); 2] ): Point2d
``` ```
@ -21,12 +21,12 @@ polar(
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `angle` | `number(deg)` | | Yes | | `angle` | `number(Angle)` | | Yes |
| `length` | `number(mm)` | | Yes | | `length` | `number(Length)` | | Yes |
### Returns ### Returns
`[number(mm); 2]` [`Point2d`](/docs/kcl/types/Point2d)
### Examples ### Examples

View File

@ -9,7 +9,7 @@ Compute the sine of a number (in radians).
```js ```js
sin(@num: number(rad)): number(_) sin(@num: number(Angle)): number(_)
``` ```
@ -17,7 +17,7 @@ sin(@num: number(rad)): number(_)
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `num` | `number(rad)` | | Yes | | `num` | `number(Angle)` | | Yes |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Compute the tangent of a number (in radians).
```js ```js
tan(@num: number(rad)): number(_) tan(@num: number(Angle)): number(_)
``` ```
@ -17,7 +17,7 @@ tan(@num: number(rad)): number(_)
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `num` | `number(rad)` | | Yes | | `num` | `number(Angle)` | | Yes |
### Returns ### Returns

View File

@ -21,10 +21,10 @@ revolved around the same axis.
revolve( revolve(
@sketches: [Sketch; 1+], @sketches: [Sketch; 1+],
axis: Axis2d | Edge, axis: Axis2d | Edge,
angle?: number(deg), angle?: number(Angle),
tolerance?: number(mm), tolerance?: number(Length),
symmetric?: bool, symmetric?: bool,
bidirectionalAngle?: number(deg), bidirectionalAngle?: number(Angle),
tagStart?: tag, tagStart?: tag,
tagEnd?: tag, tagEnd?: tag,
): Solid ): Solid
@ -37,10 +37,10 @@ revolve(
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `sketches` | `[Sketch; 1+]` | The sketch or set of sketches that should be revolved | Yes | | `sketches` | `[Sketch; 1+]` | The sketch or set of sketches that should be revolved | Yes |
| `axis` | `Axis2d | Edge` | Axis of revolution. | Yes | | `axis` | `Axis2d | Edge` | Axis of revolution. | Yes |
| `angle` | `number(deg)` | Angle to revolve (in degrees). Default is 360. | No | | `angle` | `number(Angle)` | Angle to revolve (in degrees). Default is 360. | No |
| `tolerance` | `number(mm)` | Tolerance for the revolve operation. | No | | `tolerance` | `number(Length)` | Tolerance for the revolve operation. | No |
| `symmetric` | [`bool`](/docs/kcl/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 | | `symmetric` | [`bool`](/docs/kcl/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(deg)` | If specified, will also revolve in the opposite direction to 'angle' to the specified angle. If 'symmetric' is true, this value is ignored. | No | | `bidirectionalAngle` | `number(Angle)` | 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` | [`tag`](/docs/kcl/types/tag) | A named tag for the face at the start of the revolve, i.e. the original sketch. | No | | `tagStart` | [`tag`](/docs/kcl/types/tag) | A named tag for the face at the start of the revolve, i.e. the original sketch. | No |
| `tagEnd` | [`tag`](/docs/kcl/types/tag) | A named tag for the face at the end of the revolve. | No | | `tagEnd` | [`tag`](/docs/kcl/types/tag) | A named tag for the face at the end of the revolve. | No |
@ -108,7 +108,7 @@ part001 = startSketchOn(XY)
|> close() |> close()
|> revolve(axis = Y, angle = 180) |> revolve(axis = Y, angle = 180)
part002 = startSketchOn(part001, 'end') part002 = startSketchOn(part001, face = END)
|> startProfileAt([4.5, -5], %) |> startProfileAt([4.5, -5], %)
|> line(end = [0, 5]) |> line(end = [0, 5])
|> line(end = [5, 0]) |> line(end = [5, 0])
@ -128,7 +128,7 @@ box = startSketchOn(XY)
|> close() |> close()
|> extrude(length = 20) |> extrude(length = 20)
sketch001 = startSketchOn(box, "END") sketch001 = startSketchOn(box, face = END)
|> circle( center = [10,10], radius = 4 ) |> circle( center = [10,10], radius = 4 )
|> revolve( |> revolve(
angle = -90, angle = -90,
@ -147,7 +147,7 @@ box = startSketchOn(XY)
|> close() |> close()
|> extrude(length = 20) |> extrude(length = 20)
sketch001 = startSketchOn(box, "END") sketch001 = startSketchOn(box, face = END)
|> circle( center = [10,10], radius = 4 ) |> circle( center = [10,10], radius = 4 )
|> revolve( |> revolve(
angle = 90, angle = 90,
@ -166,7 +166,7 @@ box = startSketchOn(XY)
|> close() |> close()
|> extrude(length = 20) |> extrude(length = 20)
sketch001 = startSketchOn(box, "END") sketch001 = startSketchOn(box, face = END)
|> circle( center = [10,10], radius = 4 ) |> circle( center = [10,10], radius = 4 )
|> revolve( |> revolve(
angle = 90, angle = 90,

View File

@ -13,7 +13,7 @@ the provided (x, y) origin point.
circle( circle(
@sketch_or_surface: Sketch | Plane | Face, @sketch_or_surface: Sketch | Plane | Face,
center: Point2d, center: Point2d,
radius: number, radius: number(Length),
tag?: tag, tag?: tag,
): Sketch ): Sketch
``` ```
@ -25,7 +25,7 @@ circle(
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `sketch_or_surface` | [`Sketch`](/docs/kcl/types/Sketch) OR [`Plane`](/docs/kcl/types/Plane) OR [`Face`](/docs/kcl/types/Face) | Sketch to extend, or plane or surface to sketch on. | Yes | | `sketch_or_surface` | [`Sketch`](/docs/kcl/types/Sketch) OR [`Plane`](/docs/kcl/types/Plane) OR [`Face`](/docs/kcl/types/Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
| `center` | [`Point2d`](/docs/kcl/types/Point2d) | The center of the circle. | Yes | | `center` | [`Point2d`](/docs/kcl/types/Point2d) | The center of the circle. | Yes |
| `radius` | [`number`](/docs/kcl/types/number) | The radius of the circle. | Yes | | `radius` | `number(Length)` | The radius of the circle. | Yes |
| [`tag`](/docs/kcl/types/tag) | [`tag`](/docs/kcl/types/tag) | Create a new tag which refers to this circle. | No | | [`tag`](/docs/kcl/types/tag) | [`tag`](/docs/kcl/types/tag) | Create a new tag which refers to this circle. | No |
### Returns ### Returns

View File

@ -110,7 +110,7 @@ sketch0011 = startSketchOn(XY)
|> mirror2d( axis = X ) |> mirror2d( axis = X )
|> extrude(length = 10) |> extrude(length = 10)
sketch002 = startSketchOn(sketch0011, 'END') sketch002 = startSketchOn(sketch0011, face = END)
|> circle( center = [-0.01, 1.58], radius = 1.2 ) |> circle( center = [-0.01, 1.58], radius = 1.2 )
|> extrude(length = 1.2) |> extrude(length = 1.2)

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,46 +0,0 @@
---
title: "AngledLineData"
excerpt: "Data to draw an angled line."
layout: manual
---
Data to draw an angled line.
**This schema accepts any of the following:**
An angle and length with explicitly named parameters
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `angle` |[`number`](/docs/kcl/types/number)| The angle of the line (in degrees). | No |
| `length` |[`number`](/docs/kcl/types/number)| The length of the line. | No |
----
An angle and length given as a pair
**Type:** `array`
`[number, number]`
----

View File

@ -16,8 +16,8 @@ Data for drawing an angled line that intersects with a given line.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `angle` |[`number`](/docs/kcl/types/number)| The angle of the line. | No | | `angle` |`TyF64`| The angle of the line. | No |
| `intersectTag` |[`TagIdentifier`](/docs/kcl/types#tag-identifier)| The tag of the line to intersect with. | No | | `intersectTag` |[`TagIdentifier`](/docs/kcl/types#tag-identifier)| The tag of the line to intersect with. | No |
| `offset` |[`number`](/docs/kcl/types/number)| The offset from the intersecting line. | No | | `offset` |`TyF64`| The offset from the intersecting line. | No |

View File

@ -1,22 +0,0 @@
---
title: "AngledLineToData"
excerpt: "Data to draw an angled line to a point."
layout: manual
---
Data to draw an angled line to a point.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `angle` |[`number`](/docs/kcl/types/number)| The angle of the line. | No |
| `to` |[`number`](/docs/kcl/types/number)| The point to draw to. | No |

View File

@ -23,9 +23,9 @@ Angles and radius with an optional tag.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `angleStart` |[`number`](/docs/kcl/types/number) (**maximum:** 360.0) (**minimum:** -360.0)| The start angle. | No | | `angleStart` |`TyF64`| The start angle. | No |
| `angleEnd` |[`number`](/docs/kcl/types/number) (**maximum:** 360.0) (**minimum:** -360.0)| The end angle. | No | | `angleEnd` |`TyF64`| The end angle. | No |
| `radius` |[`number`](/docs/kcl/types/number)| The radius. | No | | `radius` |`TyF64`| The radius. | No |
---- ----
@ -41,9 +41,9 @@ Center, to and radius with an optional tag.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `center` |`[number, number]`| The center. | No | | `center` |`[, `TyF64`, `TyF64`]`| The center. | No |
| `to` |`[number, number]`| The to point. | No | | `to` |`[, `TyF64`, `TyF64`]`| The to point. | No |
| `radius` |[`number`](/docs/kcl/types/number)| The radius. | No | | `radius` |`TyF64`| The radius. | No |
---- ----

View File

@ -16,7 +16,7 @@ Data to draw a three point arc (arcTo).
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `end` |`[number, number]`| End point of the arc. A point in 3D space | No | | `end` |`[, `TyF64`, `TyF64`]`| End point of the arc. A point in 3D space | No |
| `interior` |`[number, number]`| Interior point of the arc. A point in 3D space | No | | `interior` |`[, `TyF64`, `TyF64`]`| Interior point of the arc. A point in 3D space | No |

View File

@ -16,8 +16,8 @@ Data to draw a bezier curve.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `to` |`[number, number]`| The to point. | No | | `to` |`[, `TyF64`, `TyF64`]`| The to point. | No |
| `control1` |`[number, number]`| The first control point. | No | | `control1` |`[, `TyF64`, `TyF64`]`| The first control point. | No |
| `control2` |`[number, number]`| The second control point. | No | | `control2` |`[, `TyF64`, `TyF64`]`| The second control point. | No |

View File

@ -26,7 +26,7 @@ A fillet.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `fillet`| | No | | `type` |enum: `fillet`| | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the engine command that called this fillet. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the engine command that called this fillet. | No |
| `radius` |[`number`](/docs/kcl/types/number)| | No | | `radius` |`TyF64`| | No |
| `edgeId` |[`string`](/docs/kcl/types/string)| The engine id of the edge to fillet. | No | | `edgeId` |[`string`](/docs/kcl/types/string)| The engine id of the edge to fillet. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| | No | | [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| | No |
@ -46,7 +46,7 @@ A chamfer.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `chamfer`| | No | | `type` |enum: `chamfer`| | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the engine command that called this chamfer. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the engine command that called this chamfer. | No |
| `length` |[`number`](/docs/kcl/types/number)| | No | | `length` |`TyF64`| | No |
| `edgeId` |[`string`](/docs/kcl/types/string)| The engine id of the edge to chamfer. | No | | `edgeId` |[`string`](/docs/kcl/types/string)| The engine id of the edge to chamfer. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| | No | | [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| | No |

View File

@ -130,6 +130,21 @@ A unit of length.
| `type` |enum: `Yards`| | No | | `type` |enum: `Yards`| | No |
----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Unknown`| | No |
---- ----
@ -178,6 +193,21 @@ A unit of angle.
| `type` |enum: `Radians`| | No | | `type` |enum: `Radians`| | No |
----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Unknown`| | No |
---- ----

View File

@ -7,7 +7,7 @@ layout: manual
A point in two dimensional space. A point in two dimensional space.
```kcl ```kcl
type Point2d = [number; 2] type Point2d = [number(Length); 2]
``` ```
[`Point2d`](/docs/kcl/types/Point2d) is an alias for a two-element array of [number](/docs/kcl/types/number)s. To write a value [`Point2d`](/docs/kcl/types/Point2d) is an alias for a two-element array of [number](/docs/kcl/types/number)s. To write a value

View File

@ -7,7 +7,7 @@ layout: manual
A point in three dimensional space. A point in three dimensional space.
```kcl ```kcl
type Point3d = [number; 3] type Point3d = [number(Length); 3]
``` ```
[`Point3d`](/docs/kcl/types/Point3d) is an alias for a three-element array of [number](/docs/kcl/types/number)s. To write a value [`Point3d`](/docs/kcl/types/Point3d) is an alias for a three-element array of [number](/docs/kcl/types/number)s. To write a value

View File

@ -16,9 +16,9 @@ Data for drawing a polygon
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `radius` |[`number`](/docs/kcl/types/number)| The radius of the polygon | No | | `radius` |`TyF64`| The radius of the polygon | No |
| `numSides` |`integer`| The number of sides in the polygon | No | | `numSides` |`integer`| The number of sides in the polygon | No |
| `center` |`[number, number]`| The center point of the polygon | No | | `center` |`[, `TyF64`, `TyF64`]`| The center point of the polygon | No |
| `inscribed` |`boolean`| Whether the polygon is inscribed (true) or circumscribed (false) about a circle with the specified radius | No | | `inscribed` |`boolean`| Whether the polygon is inscribed (true) or circumscribed (false) about a circle with the specified radius | No |

View File

@ -16,7 +16,7 @@ Data to draw a tangential arc.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `radius` |[`number`](/docs/kcl/types/number)| Radius of the arc. Not to be confused with Raiders of the Lost Ark. | No | | `radius` |`TyF64`| Radius of the arc. Not to be confused with Raiders of the Lost Ark. | No |
| `offset` |[`number`](/docs/kcl/types/number)| Offset of the arc, in degrees. | No | | `offset` |`TyF64`| Offset of the arc, in degrees. | No |

View File

@ -43,6 +43,21 @@ A unit of angle.
---- ----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Unknown`| | No |
----

View File

@ -103,6 +103,21 @@ A unit of length.
---- ----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Unknown`| | No |
----

View File

@ -66,15 +66,17 @@ async function doBasicSketch(
await page.waitForTimeout(500) await page.waitForTimeout(500)
if (openPanes.includes('code')) { if (openPanes.includes('code')) {
await expect(u.codeLocator) await expect(
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001) u.codeLocator
).toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)
|> xLine(length = ${commonPoints.num1})`) |> xLine(length = ${commonPoints.num1})`)
} }
await page.waitForTimeout(500) await page.waitForTimeout(500)
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20) await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
if (openPanes.includes('code')) { if (openPanes.includes('code')) {
await expect(u.codeLocator) await expect(
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ u.codeLocator
).toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}) |> xLine(length = ${commonPoints.num1})
@ -85,8 +87,9 @@ async function doBasicSketch(
await page.waitForTimeout(200) await page.waitForTimeout(200)
await page.mouse.click(startXPx, 500 - PUR * 20) await page.mouse.click(startXPx, 500 - PUR * 20)
if (openPanes.includes('code')) { if (openPanes.includes('code')) {
await expect(u.codeLocator) await expect(
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ u.codeLocator
).toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}) |> xLine(length = ${commonPoints.num1})
@ -142,8 +145,9 @@ async function doBasicSketch(
// Open the code pane. // Open the code pane.
await u.openKclCodePanel() await u.openKclCodePanel()
await expect(u.codeLocator) await expect(
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ u.codeLocator
).toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}, tag = $seg01) |> xLine(length = ${commonPoints.num1}, tag = $seg01)

View File

@ -1,6 +1,6 @@
import { bracket } from '@src/lib/exampleKcl'
import fsp from 'fs/promises'
import { join } from 'path' import { join } from 'path'
import { bracket } from '@e2e/playwright/fixtures/bracket'
import fsp from 'fs/promises'
import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from '@e2e/playwright/storageStates' import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from '@e2e/playwright/storageStates'
import { import {

View File

@ -1,6 +1,6 @@
import path, { join } from 'path'
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants' import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import path, { join } from 'path'
import { import {
executorInputPath, executorInputPath,

View File

@ -1,5 +1,5 @@
import fsp from 'fs/promises'
import path from 'path' import path from 'path'
import fsp from 'fs/promises'
import { import {
executorInputPath, executorInputPath,

View File

@ -1,6 +1,6 @@
import { join } from 'path'
import { uuidv4 } from '@src/lib/utils' import { uuidv4 } from '@src/lib/utils'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import { join } from 'path'
import { import {
TEST_COLORS, TEST_COLORS,
@ -82,7 +82,7 @@ sketch001 = startSketchOn(XY)
.poll(() => .poll(() =>
page.locator('[data-receive-command-type="scene_clear_all"]').count() page.locator('[data-receive-command-type="scene_clear_all"]').count()
) )
.toBe(1) .toBe(2)
await expect await expect
.poll(() => page.locator('[data-message-type="execution-done"]').count()) .poll(() => page.locator('[data-message-type="execution-done"]').count())
.toBe(2) .toBe(2)
@ -106,7 +106,7 @@ sketch001 = startSketchOn(XY)
).toHaveCount(3) ).toHaveCount(3)
await expect( await expect(
page.locator('[data-receive-command-type="scene_clear_all"]') page.locator('[data-receive-command-type="scene_clear_all"]')
).toHaveCount(1) ).toHaveCount(2)
}) })
test('ensure we use the cache, and do not clear on append', async ({ test('ensure we use the cache, and do not clear on append', async ({
@ -133,7 +133,7 @@ sketch001 = startSketchOn(XY)
await u.openDebugPanel() await u.openDebugPanel()
await expect( await expect(
page.locator('[data-receive-command-type="scene_clear_all"]') page.locator('[data-receive-command-type="scene_clear_all"]')
).toHaveCount(1) ).toHaveCount(2)
await expect( await expect(
page.locator('[data-message-type="execution-done"]') page.locator('[data-message-type="execution-done"]')
).toHaveCount(2) ).toHaveCount(2)
@ -161,7 +161,7 @@ sketch001 = startSketchOn(XY)
).toHaveCount(3) ).toHaveCount(3)
await expect( await expect(
page.locator('[data-receive-command-type="scene_clear_all"]') page.locator('[data-receive-command-type="scene_clear_all"]')
).toHaveCount(1) ).toHaveCount(2)
}) })
test('if you click the format button it formats your code', async ({ test('if you click the format button it formats your code', async ({
@ -409,8 +409,9 @@ sketch_001 = startSketchOn(XY)
// Hit alt+shift+f to format the code // Hit alt+shift+f to format the code
await page.keyboard.press('Alt+Shift+KeyF') await page.keyboard.press('Alt+Shift+KeyF')
await expect(page.locator('.cm-content')) await expect(
.toHaveText(`sketch001 = startSketchOn(XY) page.locator('.cm-content')
).toHaveText(`sketch001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
@ -462,8 +463,9 @@ sketch_001 = startSketchOn(XY)
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel() await u.closeDebugPanel()
await expect(page.locator('.cm-content')) await expect(
.toHaveText(`sketch_001 = startSketchOn(XY) page.locator('.cm-content')
).toHaveText(`sketch_001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
@ -731,7 +733,7 @@ sketch_001 = startSketchOn(XY)
|> close() |> close()
|> extrude(length = 10) |> extrude(length = 10)
sketch001 = startSketchOn(box, revolveAxis) sketch001 = startSketchOn(box, face = revolveAxis)
|> startProfileAt([5, 10], %) |> startProfileAt([5, 10], %)
|> line(end = [0, -10]) |> line(end = [0, -10])
|> line(end = [2, 0]) |> line(end = [2, 0])
@ -978,8 +980,9 @@ sketch001 = startSketchOn(XZ)
await page.keyboard.up('Control') await page.keyboard.up('Control')
await page.waitForTimeout(100) await page.waitForTimeout(100)
await expect(page.locator('.cm-content')) await expect(
.toHaveText(`sketch001 = startSketchOn(XZ) page.locator('.cm-content')
).toHaveText(`sketch001 = startSketchOn(XZ)
|> startProfileAt([4.61, -14.01], %) |> startProfileAt([4.61, -14.01], %)
|> line(end = [12.73, -0.09]) |> line(end = [12.73, -0.09])
|> tangentialArc(endAbsolute = [24.95, -5.38]) |> tangentialArc(endAbsolute = [24.95, -5.38])

View File

@ -1,5 +1,5 @@
import * as fsp from 'fs/promises'
import { join } from 'path' import { join } from 'path'
import * as fsp from 'fs/promises'
import { expect, test } from '@e2e/playwright/zoo-test' import { expect, test } from '@e2e/playwright/zoo-test'
@ -44,7 +44,7 @@ const FEATURE_TREE_SKETCH_CODE = `sketch001 = startSketchOn(XZ)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close(%) |> close(%)
extrude001 = extrude(sketch001, length = 10) extrude001 = extrude(sketch001, length = 10)
sketch002 = startSketchOn(extrude001, rectangleSegmentB001) sketch002 = startSketchOn(extrude001, face = rectangleSegmentB001)
|> circle( |> circle(
center = [-1, 2], center = [-1, 2],
radius = .5 radius = .5
@ -194,7 +194,7 @@ test.describe('Feature Tree pane', () => {
highlightedCode: '', highlightedCode: '',
diagnostics: [], diagnostics: [],
activeLines: [ activeLines: [
'sketch002=startSketchOn(extrude001,rectangleSegmentB001)', 'sketch002=startSketchOn(extrude001,face=rectangleSegmentB001)',
], ],
}) })
await toolbar.exitSketchBtn.click() await toolbar.exitSketchBtn.click()

View File

@ -1,7 +1,7 @@
import { FILE_EXT } from '@src/lib/constants'
import * as fs from 'fs' import * as fs from 'fs'
import * as fsp from 'fs/promises'
import { join } from 'path' import { join } from 'path'
import { FILE_EXT } from '@src/lib/constants'
import * as fsp from 'fs/promises'
import { import {
createProject, createProject,

View File

@ -0,0 +1,16 @@
import fs from 'fs'
import path from 'path'
export const bracket = fs.readFileSync(
path.resolve(
__dirname,
'..',
'..',
'..',
'public',
'kcl-samples',
'bracket',
'main.kcl'
),
'utf8'
)

View File

@ -1,9 +1,9 @@
import type { Locator, Page, Request, Route, TestInfo } from '@playwright/test'
import { expect } from '@playwright/test'
import * as fs from 'fs' import * as fs from 'fs'
import * as path from 'path' import * as path from 'path'
import type { Locator, Page, Request, Route, TestInfo } from '@playwright/test'
import { expect } from '@playwright/test'
type CmdBarSerialised = export type CmdBarSerialised =
| { | {
stage: 'commandBarClosed' stage: 'commandBarClosed'
} }

View File

@ -7,11 +7,11 @@ import type {
} from '@playwright/test' } from '@playwright/test'
import { _electron as electron } from '@playwright/test' import { _electron as electron } from '@playwright/test'
import fs from 'node:fs'
import path from 'path'
import { SETTINGS_FILE_NAME } from '@src/lib/constants' import { SETTINGS_FILE_NAME } from '@src/lib/constants'
import type { DeepPartial } from '@src/lib/types' import type { DeepPartial } from '@src/lib/types'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import fs from 'node:fs'
import path from 'path'
import type { Settings } from '@rust/kcl-lib/bindings/Settings' import type { Settings } from '@rust/kcl-lib/bindings/Settings'

View File

@ -44,6 +44,7 @@ export class SceneFixture {
public page: Page public page: Page
public streamWrapper!: Locator public streamWrapper!: Locator
public networkToggleConnected!: Locator public networkToggleConnected!: Locator
public engineConnectionsSpinner!: Locator
public startEditSketchBtn!: Locator public startEditSketchBtn!: Locator
constructor(page: Page) { constructor(page: Page) {
@ -52,6 +53,7 @@ export class SceneFixture {
this.networkToggleConnected = page this.networkToggleConnected = page
.getByTestId('network-toggle-ok') .getByTestId('network-toggle-ok')
.or(page.getByTestId('network-toggle-other')) .or(page.getByTestId('network-toggle-other'))
this.engineConnectionsSpinner = page.getByTestId(`loading-engine`)
this.startEditSketchBtn = page this.startEditSketchBtn = page
.getByRole('button', { name: 'Start Sketch' }) .getByRole('button', { name: 'Start Sketch' })
.or(page.getByRole('button', { name: 'Edit Sketch' })) .or(page.getByRole('button', { name: 'Edit Sketch' }))
@ -228,6 +230,7 @@ export class SceneFixture {
connectionEstablished = async () => { connectionEstablished = async () => {
const timeout = 30000 const timeout = 30000
await expect(this.networkToggleConnected).toBeVisible({ timeout }) await expect(this.networkToggleConnected).toBeVisible({ timeout })
await expect(this.engineConnectionsSpinner).not.toBeVisible()
} }
settled = async (cmdBar: CmdBarFixture) => { settled = async (cmdBar: CmdBarFixture) => {
@ -235,6 +238,7 @@ export class SceneFixture {
await expect(this.startEditSketchBtn).not.toBeDisabled({ timeout: 15_000 }) await expect(this.startEditSketchBtn).not.toBeDisabled({ timeout: 15_000 })
await expect(this.startEditSketchBtn).toBeVisible() await expect(this.startEditSketchBtn).toBeVisible()
await expect(this.engineConnectionsSpinner).not.toBeVisible()
await cmdBar.openCmdBar() await cmdBar.openCmdBar()
await cmdBar.chooseCommand('Settings · app · show debug panel') await cmdBar.chooseCommand('Settings · app · show debug panel')

View File

@ -27,6 +27,7 @@ export class ToolbarFixture {
offsetPlaneButton!: Locator offsetPlaneButton!: Locator
helixButton!: Locator helixButton!: Locator
startSketchBtn!: Locator startSketchBtn!: Locator
insertButton!: Locator
lineBtn!: Locator lineBtn!: Locator
tangentialArcBtn!: Locator tangentialArcBtn!: Locator
circleBtn!: Locator circleBtn!: Locator
@ -44,7 +45,7 @@ export class ToolbarFixture {
featureTreePane!: Locator featureTreePane!: Locator
gizmo!: Locator gizmo!: Locator
gizmoDisabled!: Locator gizmoDisabled!: Locator
insertButton!: Locator loadButton!: Locator
constructor(page: Page) { constructor(page: Page) {
this.page = page this.page = page
@ -59,6 +60,7 @@ export class ToolbarFixture {
this.offsetPlaneButton = page.getByTestId('plane-offset') this.offsetPlaneButton = page.getByTestId('plane-offset')
this.helixButton = page.getByTestId('helix') this.helixButton = page.getByTestId('helix')
this.startSketchBtn = page.getByTestId('sketch') this.startSketchBtn = page.getByTestId('sketch')
this.insertButton = page.getByTestId('insert')
this.lineBtn = page.getByTestId('line') this.lineBtn = page.getByTestId('line')
this.tangentialArcBtn = page.getByTestId('tangential-arc') this.tangentialArcBtn = page.getByTestId('tangential-arc')
this.circleBtn = page.getByTestId('circle-center') this.circleBtn = page.getByTestId('circle-center')
@ -68,6 +70,7 @@ export class ToolbarFixture {
this.fileTreeBtn = page.locator('[id="files-button-holder"]') this.fileTreeBtn = page.locator('[id="files-button-holder"]')
this.createFileBtn = page.getByTestId('create-file-button') this.createFileBtn = page.getByTestId('create-file-button')
this.treeInputField = page.getByTestId('tree-input-field') this.treeInputField = page.getByTestId('tree-input-field')
this.loadButton = page.getByTestId('load-external-model-pane-button')
this.filePane = page.locator('#files-pane') this.filePane = page.locator('#files-pane')
this.featureTreePane = page.locator('#feature-tree-pane') this.featureTreePane = page.locator('#feature-tree-pane')
@ -79,8 +82,6 @@ export class ToolbarFixture {
// element or two different elements can represent these states. // element or two different elements can represent these states.
this.gizmo = page.getByTestId('gizmo') this.gizmo = page.getByTestId('gizmo')
this.gizmoDisabled = page.getByTestId('gizmo-disabled') this.gizmoDisabled = page.getByTestId('gizmo-disabled')
this.insertButton = page.getByTestId('insert-pane-button')
} }
get logoLink() { get logoLink() {
@ -204,6 +205,11 @@ export class ToolbarFixture {
).toBeVisible() ).toBeVisible()
await this.page.getByTestId('dropdown-three-point-arc').click() await this.page.getByTestId('dropdown-three-point-arc').click()
} }
selectLine = async () => {
await this.page
.getByRole('button', { name: 'line Line', exact: true })
.click()
}
async closePane(paneId: SidebarType) { async closePane(paneId: SidebarType) {
return closePane(this.page, paneId + SIDEBAR_BUTTON_SUFFIX) return closePane(this.page, paneId + SIDEBAR_BUTTON_SUFFIX)

View File

@ -1,9 +1,9 @@
import path from 'path'
import { expect, test } from '@e2e/playwright/zoo-test' import { expect, test } from '@e2e/playwright/zoo-test'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import path from 'path'
test.describe('Import UI tests', () => { test.describe('Import UI tests', () => {
test('shows toast when trying to sketch on imported face', async ({ test('shows toast when trying to sketch on imported face, and hovering over imported geometry should NOT highlight any code', async ({
context, context,
page, page,
homePage, homePage,
@ -44,8 +44,8 @@ profile001 = startProfileAt([-134.53, -56.17], sketch001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02) |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|> close() |> close()
extrude001 = extrude(profile001, length = 100) extrude001 = extrude(profile001, length = 100)
sketch003 = startSketchOn(extrude001, seg02) sketch003 = startSketchOn(extrude001, face = seg02)
sketch002 = startSketchOn(extrude001, seg01)` sketch002 = startSketchOn(extrude001, face = seg01)`
) )
}) })
@ -93,7 +93,6 @@ sketch002 = startSketchOn(extrude001, seg01)`
await toolbar.startSketchPlaneSelection() await toolbar.startSketchPlaneSelection()
// Click on a face from the imported model // Click on a face from the imported model
// await new Promise(() => {})
await importedFaceClick() await importedFaceClick()
// Verify toast appears with correct content // Verify toast appears with correct content

View File

@ -19,8 +19,9 @@ class MyAPIReporter implements Reporter {
target: process.env.TARGET || null, target: process.env.TARGET || null,
platform: process.env.RUNNER_OS || process.platform, platform: process.env.RUNNER_OS || process.platform,
// Extra test and result data // Extra test and result data
annotations: test.annotations.map((a) => a.type), annotations: test.annotations.map((a) => a.type), // e.g. 'fail' or 'fixme'
retries: result.retry, retry: result.retry,
tags: test.tags, // e.g. '@snapshot' or '@skipWin'
// Extra environment variables // Extra environment variables
CI_COMMIT_SHA: process.env.CI_COMMIT_SHA || null, CI_COMMIT_SHA: process.env.CI_COMMIT_SHA || null,
CI_PR_NUMBER: process.env.CI_PR_NUMBER || null, CI_PR_NUMBER: process.env.CI_PR_NUMBER || null,

View File

@ -1,5 +1,5 @@
import fsp from 'fs/promises'
import { join } from 'path' import { join } from 'path'
import fsp from 'fs/promises'
import { executorInputPath } from '@e2e/playwright/test-utils' import { executorInputPath } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test' import { expect, test } from '@e2e/playwright/zoo-test'

View File

@ -1,14 +1,13 @@
import { join } from 'path'
import { PROJECT_SETTINGS_FILE_NAME } from '@src/lib/constants' import { PROJECT_SETTINGS_FILE_NAME } from '@src/lib/constants'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import { join } from 'path'
import type { NamedView } from '@rust/kcl-lib/bindings/NamedView' import type { NamedView } from '@rust/kcl-lib/bindings/NamedView'
import { import {
createProject, createProject,
orRunWhenFullSuiteEnabled,
perProjectSettingsToToml, perProjectSettingsToToml,
runningOnMac, runningOnWindows,
tomlToPerProjectSettings, tomlToPerProjectSettings,
} from '@e2e/playwright/test-utils' } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test' import { expect, test } from '@e2e/playwright/zoo-test'
@ -63,9 +62,7 @@ function tomlStringOverWriteNamedViewUuids(toml: string): string {
} }
test.describe('Named view tests', () => { test.describe('Named view tests', () => {
if (runningOnMac()) { test.skip(runningOnWindows(), 'Windows line endings break snapshot matching')
test.fixme(orRunWhenFullSuiteEnabled())
}
test('Verify project.toml is not created', async ({ page }, testInfo) => { test('Verify project.toml is not created', async ({ page }, testInfo) => {
// Create project and load it // Create project and load it
const projectName = 'named-views' const projectName = 'named-views'
@ -127,7 +124,7 @@ test.describe('Named view tests', () => {
// Write the entire tomlString to a snapshot. // Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match. // There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created') expect(tomlString).toMatchSnapshot('verify-named-view-gets-created.toml')
}).toPass() }).toPass()
}) })
test('Verify named view gets deleted', async ({ test('Verify named view gets deleted', async ({
@ -173,7 +170,7 @@ test.describe('Named view tests', () => {
// Write the entire tomlString to a snapshot. // Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match. // There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created') expect(tomlString).toMatchSnapshot('verify-named-view-gets-created.toml')
}).toPass() }).toPass()
// Delete a named view // Delete a named view
@ -193,7 +190,7 @@ test.describe('Named view tests', () => {
// Write the entire tomlString to a snapshot. // Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match. // There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-deleted') expect(tomlString).toMatchSnapshot('verify-named-view-gets-deleted.toml')
}).toPass() }).toPass()
}) })
test('Verify named view gets loaded', async ({ test('Verify named view gets loaded', async ({
@ -239,7 +236,7 @@ test.describe('Named view tests', () => {
// Write the entire tomlString to a snapshot. // Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match. // There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created') expect(tomlString).toMatchSnapshot('verify-named-view-gets-created.toml')
}).toPass() }).toPass()
// Create a load a named view // Create a load a named view
@ -308,7 +305,9 @@ test.describe('Named view tests', () => {
// Write the entire tomlString to a snapshot. // Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match. // There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-two-named-view-gets-created') expect(tomlString).toMatchSnapshot(
'verify-two-named-view-gets-created.toml'
)
}).toPass() }).toPass()
}) })
}) })

View File

@ -1,16 +0,0 @@
[settings]
modeling = { }
text_editor = { }
command_bar = { }
[settings.app.named_views.0656fb1a-9640-473e-b334-591dc70c0138]
name = "uuid1"
eye_offset = 1_378.0059
fov_y = 45
is_ortho = false
ortho_scale_enabled = true
ortho_scale_factor = 1.6
pivot_position = [ 0, 0, 0 ]
pivot_rotation = [ 0.5380994, 0.0, 0.0, 0.8428814 ]
world_coord_system = "right_handed_up_z"
version = 1

View File

@ -1,28 +0,0 @@
[settings]
modeling = { }
text_editor = { }
command_bar = { }
[settings.app.named_views.0656fb1a-9640-473e-b334-591dc70c0138]
name = "uuid1"
eye_offset = 1_378.0059
fov_y = 45
is_ortho = false
ortho_scale_enabled = true
ortho_scale_factor = 1.6
pivot_position = [ 0, 0, 0 ]
pivot_rotation = [ 0.5380994, 0.0, 0.0, 0.8428814 ]
world_coord_system = "right_handed_up_z"
version = 1
[settings.app.named_views.c810cf04-c6cc-4a4a-8b11-17bf445dcab7]
name = "uuid2"
eye_offset = 1_378.0059
fov_y = 45
is_ortho = false
ortho_scale_enabled = true
ortho_scale_factor = 1.6
pivot_position = [ 1_826.5239, 0.0, 0.0 ]
pivot_rotation = [ 0.5380994, 0.0, 0.0, 0.8428814 ]
world_coord_system = "right_handed_up_z"
version = 1

View File

@ -534,7 +534,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
const expected = 'Open project' const expected = 'Open project'
expect(actual).toBe(expected) expect(actual).toBe(expected)
}) })
test('Modeling.File.Load a sample model', async ({ test('Modeling.File.Load external model', async ({
tronApp, tronApp,
cmdBar, cmdBar,
page, page,
@ -555,10 +555,10 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
throw new Error('app or app.applicationMenu is missing') throw new Error('app or app.applicationMenu is missing')
} }
const openProject = app.applicationMenu.getMenuItemById( const openProject = app.applicationMenu.getMenuItemById(
'File.Load a sample model' 'File.Load external model'
) )
if (!openProject) { if (!openProject) {
throw new Error('File.Load a sample model') throw new Error('File.Load external model')
} }
openProject.click() openProject.click()
}) })
@ -568,44 +568,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
const actual = await cmdBar.cmdBarElement const actual = await cmdBar.cmdBarElement
.getByTestId('command-name') .getByTestId('command-name')
.textContent() .textContent()
const expected = 'Open sample' const expected = 'Load external model'
expect(actual).toBe(expected)
})
test('Modeling.File.Insert from project file', async ({
tronApp,
cmdBar,
page,
homePage,
scene,
}) => {
if (!tronApp) {
throwTronAppMissing()
return
}
await homePage.goToModelingScene()
await scene.settled(cmdBar)
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
throw new Error('app or app.applicationMenu is missing')
}
const openProject = app.applicationMenu.getMenuItemById(
'File.Insert from project file'
)
if (!openProject) {
throw new Error('File.Insert from project file')
}
openProject.click()
})
// Check that the command bar is opened
await expect(cmdBar.cmdBarElement).toBeVisible()
// Check the placeholder project name exists
const actual = await cmdBar.cmdBarElement
.getByTestId('command-name')
.textContent()
const expected = 'Insert'
expect(actual).toBe(expected) expect(actual).toBe(expected)
}) })
test('Modeling.File.Export current part', async ({ test('Modeling.File.Export current part', async ({
@ -2159,6 +2122,44 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
expect(actual).toBe(expected) expect(actual).toBe(expected)
}) })
test('Modeling.Design.Insert from project file', async ({
tronApp,
cmdBar,
page,
homePage,
scene,
}) => {
if (!tronApp) {
throwTronAppMissing()
return
}
await homePage.goToModelingScene()
await scene.settled(cmdBar)
// Run electron snippet to find the Menu!
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
await tronApp.electron.evaluate(async ({ app }) => {
if (!app || !app.applicationMenu) {
throw new Error('app or app.applicationMenu is missing')
}
const openProject = app.applicationMenu.getMenuItemById(
'Design.Insert from project file'
)
if (!openProject) {
throw new Error('Design.Insert from project file')
}
openProject.click()
})
// Check that the command bar is opened
await expect(cmdBar.cmdBarElement).toBeVisible()
// Check the placeholder project name exists
const actual = await cmdBar.cmdBarElement
.getByTestId('command-name')
.textContent()
const expected = 'Insert'
expect(actual).toBe(expected)
})
test('Modeling.Design.Create with Zoo Text-To-CAD', async ({ test('Modeling.Design.Create with Zoo Text-To-CAD', async ({
tronApp, tronApp,
cmdBar, cmdBar,

View File

@ -1,7 +1,7 @@
import { bracket } from '@src/lib/exampleKcl' import { join } from 'path'
import { bracket } from '@e2e/playwright/fixtures/bracket'
import { onboardingPaths } from '@src/routes/Onboarding/paths' import { onboardingPaths } from '@src/routes/Onboarding/paths'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import { join } from 'path'
import { expectPixelColor } from '@e2e/playwright/fixtures/sceneFixture' import { expectPixelColor } from '@e2e/playwright/fixtures/sceneFixture'
import { import {
@ -15,6 +15,7 @@ import {
executorInputPath, executorInputPath,
getUtils, getUtils,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
runningOnWindows,
settingsToToml, settingsToToml,
} from '@e2e/playwright/test-utils' } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test' import { expect, test } from '@e2e/playwright/zoo-test'
@ -279,6 +280,9 @@ test.describe('Onboarding tests', () => {
if (!tronApp) { if (!tronApp) {
fail() fail()
} }
if (runningOnWindows()) {
test.fixme(orRunWhenFullSuiteEnabled())
}
await tronApp.cleanProjectDir({ await tronApp.cleanProjectDir({
app: { app: {
onboarding_status: '/parametric-modeling', onboarding_status: '/parametric-modeling',

View File

@ -1,5 +1,5 @@
import * as fsp from 'fs/promises'
import path from 'path' import path from 'path'
import * as fsp from 'fs/promises'
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture' import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture' import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'

View File

@ -1,6 +1,6 @@
import type { Locator, Page } from '@playwright/test'
import fs from 'node:fs/promises' import fs from 'node:fs/promises'
import path from 'node:path' import path from 'node:path'
import type { Locator, Page } from '@playwright/test'
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture' import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture' import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
@ -220,7 +220,7 @@ test.describe('Point-and-click tests', () => {
)`, )`,
afterChamferSelectSnippet: afterChamferSelectSnippet:
'sketch002 = startSketchOn(extrude001, seg03)', 'sketch002 = startSketchOn(extrude001, face = seg03)',
afterRectangle1stClickSnippet: afterRectangle1stClickSnippet:
'startProfileAt([205.96, 254.59], sketch002)', 'startProfileAt([205.96, 254.59], sketch002)',
afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.39,tag=$rectangleSegmentA002) afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.39,tag=$rectangleSegmentA002)
@ -244,7 +244,7 @@ test.describe('Point-and-click tests', () => {
)`, )`,
afterChamferSelectSnippet: afterChamferSelectSnippet:
'sketch003 = startSketchOn(extrude001, seg04)', 'sketch003 = startSketchOn(extrude001, face = seg04)',
afterRectangle1stClickSnippet: afterRectangle1stClickSnippet:
'startProfileAt([-209.64, 255.28], sketch003)', 'startProfileAt([-209.64, 255.28], sketch003)',
afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.56,tag=$rectangleSegmentA003) afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.56,tag=$rectangleSegmentA003)
@ -266,7 +266,7 @@ test.describe('Point-and-click tests', () => {
] ]
)`, )`,
afterChamferSelectSnippet: afterChamferSelectSnippet:
'sketch004 = startSketchOn(extrude001, seg05)', 'sketch004 = startSketchOn(extrude001, face = seg05)',
afterRectangle1stClickSnippet: afterRectangle1stClickSnippet:
'startProfileAt([82.57, 322.96], sketch004)', 'startProfileAt([82.57, 322.96], sketch004)',
afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.16,tag=$rectangleSegmentA004) afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.16,tag=$rectangleSegmentA004)
@ -284,7 +284,7 @@ test.describe('Point-and-click tests', () => {
beforeChamferSnippetEnd: beforeChamferSnippetEnd:
'|> chamfer(length = 30, tags = [getNextAdjacentEdge(yo)])', '|> chamfer(length = 30, tags = [getNextAdjacentEdge(yo)])',
afterChamferSelectSnippet: afterChamferSelectSnippet:
'sketch005 = startSketchOn(extrude001, seg06)', 'sketch005 = startSketchOn(extrude001, face = seg06)',
afterRectangle1stClickSnippet: afterRectangle1stClickSnippet:
'startProfileAt([-23.43, 19.69], sketch005)', 'startProfileAt([-23.43, 19.69], sketch005)',
afterRectangle2ndClickSnippet: `angledLine(angle=0,length=9.1,tag=$rectangleSegmentA005) afterRectangle2ndClickSnippet: `angledLine(angle=0,length=9.1,tag=$rectangleSegmentA005)
@ -309,28 +309,28 @@ extrude001 = extrude(sketch001, length = 100)
|> chamfer(length = 30, tags = [seg01], tag = $seg04) |> chamfer(length = 30, tags = [seg01], tag = $seg04)
|> chamfer(length = 30, tags = [getNextAdjacentEdge(seg02)], tag = $seg05) |> chamfer(length = 30, tags = [getNextAdjacentEdge(seg02)], tag = $seg05)
|> chamfer(length = 30, tags = [getNextAdjacentEdge(yo)], tag = $seg06) |> chamfer(length = 30, tags = [getNextAdjacentEdge(yo)], tag = $seg06)
sketch005 = startSketchOn(extrude001, seg06) sketch005 = startSketchOn(extrude001, face = seg06)
profile004=startProfileAt([-23.43,19.69], sketch005) profile004=startProfileAt([-23.43,19.69], sketch005)
|> angledLine(angle = 0, length = 9.1, tag = $rectangleSegmentA005) |> angledLine(angle = 0, length = 9.1, tag = $rectangleSegmentA005)
|> angledLine(angle = segAng(rectangleSegmentA005) - 90, length = 84.07) |> angledLine(angle = segAng(rectangleSegmentA005) - 90, length = 84.07)
|> angledLine(angle = segAng(rectangleSegmentA005), length = -segLen(rectangleSegmentA005)) |> angledLine(angle = segAng(rectangleSegmentA005), length = -segLen(rectangleSegmentA005))
|> line(endAbsolute=[profileStartX(%), profileStartY(%)]) |> line(endAbsolute=[profileStartX(%), profileStartY(%)])
|> close() |> close()
sketch004 = startSketchOn(extrude001, seg05) sketch004 = startSketchOn(extrude001, face = seg05)
profile003 = startProfileAt([82.57, 322.96], sketch004) profile003 = startProfileAt([82.57, 322.96], sketch004)
|> angledLine(angle = 0, length = 11.16, tag = $rectangleSegmentA004) |> angledLine(angle = 0, length = 11.16, tag = $rectangleSegmentA004)
|> angledLine(angle = segAng(rectangleSegmentA004) - 90, length = 103.07) |> angledLine(angle = segAng(rectangleSegmentA004) - 90, length = 103.07)
|> angledLine(angle = segAng(rectangleSegmentA004), length = -segLen(rectangleSegmentA004)) |> angledLine(angle = segAng(rectangleSegmentA004), length = -segLen(rectangleSegmentA004))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
sketch003 = startSketchOn(extrude001, seg04) sketch003 = startSketchOn(extrude001, face = seg04)
profile002 = startProfileAt([-209.64, 255.28], sketch003) profile002 = startProfileAt([-209.64, 255.28], sketch003)
|> angledLine(angle = 0, length = 11.56, tag = $rectangleSegmentA003) |> angledLine(angle = 0, length = 11.56, tag = $rectangleSegmentA003)
|> angledLine(angle = segAng(rectangleSegmentA003) - 90, length = 106.84) |> angledLine(angle = segAng(rectangleSegmentA003) - 90, length = 106.84)
|> angledLine(angle = segAng(rectangleSegmentA003), length = -segLen(rectangleSegmentA003)) |> angledLine(angle = segAng(rectangleSegmentA003), length = -segLen(rectangleSegmentA003))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
sketch002 = startSketchOn(extrude001, seg03) sketch002 = startSketchOn(extrude001, face = seg03)
profile001 = startProfileAt([205.96, 254.59], sketch002) profile001 = startProfileAt([205.96, 254.59], sketch002)
|> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002) |> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002)
|> angledLine(angle = segAng(rectangleSegmentA002) - 90, length = 105.26) |> angledLine(angle = segAng(rectangleSegmentA002) - 90, length = 105.26)
@ -383,7 +383,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
])`, ])`,
beforeChamferSnippetEnd: ')', beforeChamferSnippetEnd: ')',
afterChamferSelectSnippet: afterChamferSelectSnippet:
'sketch002 = startSketchOn(extrude001, seg03)', 'sketch002 = startSketchOn(extrude001, face = seg03)',
afterRectangle1stClickSnippet: afterRectangle1stClickSnippet:
'startProfileAt([205.96, 254.59], sketch002)', 'startProfileAt([205.96, 254.59], sketch002)',
afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.39,tag=$rectangleSegmentA002) afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.39,tag=$rectangleSegmentA002)
@ -416,7 +416,7 @@ chamf = chamfer(
getNextAdjacentEdge(seg02) getNextAdjacentEdge(seg02)
], ],
) )
sketch002 = startSketchOn(extrude001, seg03) sketch002 = startSketchOn(extrude001, face = seg03)
profile001 = startProfileAt([205.96, 254.59], sketch002) profile001 = startProfileAt([205.96, 254.59], sketch002)
|> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002) |> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002)
|> angledLine(angle = segAng(rectangleSegmentA002) - 90, length = 105.26) |> angledLine(angle = segAng(rectangleSegmentA002) - 90, length = 105.26)
@ -2935,9 +2935,9 @@ extrude001 = extrude(sketch001, length = 30)
const testPoint = { x: 575, y: 200 } const testPoint = { x: 575, y: 200 }
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y) const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
const shellDeclaration = const shellDeclaration =
"shell001 = shell(extrude001, faces = ['end'], thickness = 5)" 'shell001 = shell(extrude001, faces = [END], thickness = 5)'
const editedShellDeclaration = const editedShellDeclaration =
"shell001 = shell(extrude001, faces = ['end'], thickness = 2)" 'shell001 = shell(extrude001, faces = [END], thickness = 2)'
await test.step(`Look for the grey of the shape`, async () => { await test.step(`Look for the grey of the shape`, async () => {
await scene.expectPixelColor([127, 127, 127], testPoint, 15) await scene.expectPixelColor([127, 127, 127], testPoint, 15)
@ -3079,9 +3079,9 @@ extrude001 = extrude(sketch001, length = 40)
const [clickOnWall] = scene.makeMouseHelpers(testPoint.x, testPoint.y + 70) const [clickOnWall] = scene.makeMouseHelpers(testPoint.x, testPoint.y + 70)
const mutatedCode = 'xLine(length = -40, tag = $seg01)' const mutatedCode = 'xLine(length = -40, tag = $seg01)'
const shellDeclaration = const shellDeclaration =
"shell001 = shell(extrude001, faces = ['end', seg01], thickness = 5)" 'shell001 = shell(extrude001, faces = [END, seg01], thickness = 5)'
const editedShellDeclaration = const editedShellDeclaration =
"shell001 = shell(extrude001, faces = ['end', seg01], thickness = 1)" 'shell001 = shell(extrude001, faces = [END, seg01], thickness = 1)'
await test.step(`Look for the grey of the shape`, async () => { await test.step(`Look for the grey of the shape`, async () => {
await scene.expectPixelColor([99, 99, 99], testPoint, 15) await scene.expectPixelColor([99, 99, 99], testPoint, 15)
@ -3188,7 +3188,7 @@ sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 100) |> circle(center = [0, 0], radius = 100)
|> extrude(length = 100) |> extrude(length = 100)
sketch002 = startSketchOn(sketch001, 'END') sketch002 = startSketchOn(sketch001, face = 'END')
|> circle(center = [0, 0], radius = 50) |> circle(center = [0, 0], radius = 50)
|> extrude(length = 50) |> extrude(length = 50)
`, `,
@ -3197,7 +3197,7 @@ sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 100) |> circle(center = [0, 0], radius = 100)
extrude001 = extrude(sketch001, length = 100) extrude001 = extrude(sketch001, length = 100)
sketch002 = startSketchOn(extrude001, 'END') sketch002 = startSketchOn(extrude001, face = 'END')
|> circle(center = [0, 0], radius = 50) |> circle(center = [0, 0], radius = 50)
extrude002 = extrude(sketch002, length = 50) extrude002 = extrude(sketch002, length = 50)
`, `,
@ -3224,7 +3224,7 @@ extrude002 = extrude(sketch002, length = 50)
const testPoint = { x: 580, y: 320 } const testPoint = { x: 580, y: 320 }
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y) const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
const shellTarget = hasExtrudesInPipe ? 'sketch002' : 'extrude002' const shellTarget = hasExtrudesInPipe ? 'sketch002' : 'extrude002'
const shellDeclaration = `shell001 = shell(${shellTarget}, faces = ['end'], thickness = 5)` const shellDeclaration = `shell001 = shell(${shellTarget}, faces = [END], thickness = 5)`
await test.step(`Look for the grey of the shape`, async () => { await test.step(`Look for the grey of the shape`, async () => {
await scene.expectPixelColor([113, 113, 113], testPoint, 15) await scene.expectPixelColor([113, 113, 113], testPoint, 15)
@ -3299,7 +3299,7 @@ profile001 = startProfileAt([-20, 20], sketch001)
` `
const extrudeCode = `extrude001 = extrude(profile001, length = 40) const extrudeCode = `extrude001 = extrude(profile001, length = 40)
` `
const shellCode = `shell001 = shell(extrude001, faces = ['end'], thickness = 5) const shellCode = `shell001 = shell(extrude001, faces = [END], thickness = 5)
` `
const initialCode = sketchCode + extrudeCode + shellCode const initialCode = sketchCode + extrudeCode + shellCode
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
@ -3447,7 +3447,7 @@ tag=$rectangleSegmentC001,
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
extrude001 = extrude(sketch001, length = 200) extrude001 = extrude(sketch001, length = 200)
sketch002 = startSketchOn(extrude001, rectangleSegmentA001) sketch002 = startSketchOn(extrude001, face = rectangleSegmentA001)
|> startProfileAt([-66.77, 84.81], %) |> startProfileAt([-66.77, 84.81], %)
|> angledLine(angle = 180, length = 27.08, tag = $rectangleSegmentA002) |> angledLine(angle = 180, length = 27.08, tag = $rectangleSegmentA002)
|> angledLine( |> angledLine(
@ -3535,7 +3535,7 @@ tag=$rectangleSegmentC002,
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
extrude001 = extrude(sketch001, length = 50) extrude001 = extrude(sketch001, length = 50)
sketch002 = startSketchOn(extrude001, rectangleSegmentA001) sketch002 = startSketchOn(extrude001, face = rectangleSegmentA001)
|> circle(center = [-11.34, 10.0], radius = 8.69) |> circle(center = [-11.34, 10.0], radius = 8.69)
` `
@ -3623,7 +3623,7 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
extrude001 = extrude(sketch001, length = 5) extrude001 = extrude(sketch001, length = 5)
sketch003 = startSketchOn(extrude001, 'START') sketch003 = startSketchOn(extrude001, face = 'START')
|> circle( |> circle(
center = [-0.69, 0.56], center = [-0.69, 0.56],
radius = 0.28 radius = 0.28

View File

@ -1,7 +1,7 @@
import { DEFAULT_PROJECT_KCL_FILE } from '@src/lib/constants'
import fs from 'fs' import fs from 'fs'
import fsp from 'fs/promises'
import path from 'path' import path from 'path'
import { DEFAULT_PROJECT_KCL_FILE } from '@src/lib/constants'
import fsp from 'fs/promises'
import type { Paths } from '@e2e/playwright/test-utils' import type { Paths } from '@e2e/playwright/test-utils'
import { import {

View File

@ -1,8 +1,8 @@
import path from 'path'
import { bracket } from '@e2e/playwright/fixtures/bracket'
import type { Page } from '@playwright/test' import type { Page } from '@playwright/test'
import { bracket } from '@src/lib/exampleKcl'
import { reportRejection } from '@src/lib/trap' import { reportRejection } from '@src/lib/trap'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import path from 'path'
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from '@e2e/playwright/storageStates' import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from '@e2e/playwright/storageStates'
import type { TestColor } from '@e2e/playwright/test-utils' import type { TestColor } from '@e2e/playwright/test-utils'
@ -304,8 +304,9 @@ extrude001 = extrude(sketch001, length = 50)
await page.keyboard.press('Enter') await page.keyboard.press('Enter')
await page.keyboard.press('ArrowLeft') await page.keyboard.press('ArrowLeft')
await expect(page.locator('.cm-content')) await expect(
.toContainText(`exampleSketch = startSketchOn("XZ") page.locator('.cm-content')
).toContainText(`exampleSketch = startSketchOn("XZ")
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> angledLine(angle = 50, length = 45 ) |> angledLine(angle = 50, length = 45 )
|> yLine(endAbsolute = 0) |> yLine(endAbsolute = 0)

View File

@ -1,7 +1,7 @@
import type { Page } from '@playwright/test'
import { roundOff, uuidv4 } from '@src/lib/utils'
import fs from 'node:fs/promises' import fs from 'node:fs/promises'
import path from 'node:path' import path from 'node:path'
import type { Page } from '@playwright/test'
import { roundOff, uuidv4 } from '@src/lib/utils'
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture' import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture' import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
@ -161,7 +161,8 @@ sketch001 = startSketchOn(XZ)
// click to add segment // click to add segment
await page.mouse.click(700, 200) await page.mouse.click(700, 200)
await expect.poll(u.normalisedEditorCode, { timeout: 1000 }) await expect
.poll(u.normalisedEditorCode, { timeout: 1000 })
.toBe(`@settings(defaultLengthUnit = in) .toBe(`@settings(defaultLengthUnit = in)
@ -403,8 +404,9 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
await u.openKclCodePanel() await u.openKclCodePanel()
// expect the code to have changed // expect the code to have changed
await expect(page.locator('.cm-content')) await expect(
.toHaveText(`sketch001 = startSketchOn(XZ) page.locator('.cm-content')
).toHaveText(`sketch001 = startSketchOn(XZ)
|> startProfileAt([6.44, -12.07], %) |> startProfileAt([6.44, -12.07], %)
|> line(end = [14.72, 1.97]) |> line(end = [14.72, 1.97])
|> tangentialArc(endAbsolute = [26.92, -3.32]) |> tangentialArc(endAbsolute = [26.92, -3.32])
@ -1077,7 +1079,7 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
// The click should generate a new sketch starting on the end face of extrude001 // The click should generate a new sketch starting on the end face of extrude001
// signified by the implicit 'END' tag for that solid. // signified by the implicit 'END' tag for that solid.
await page.waitForTimeout(800) await page.waitForTimeout(800)
await page.getByText(`END')`).click() await page.getByText(`END)`).click()
await page.keyboard.press('End') await page.keyboard.press('End')
await page.keyboard.press('Enter') await page.keyboard.press('Enter')
await page.keyboard.type(' |>', { delay: 100 }) await page.keyboard.type(' |>', { delay: 100 })
@ -1099,7 +1101,7 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
extrude001 = extrude(sketch001, length = 5) extrude001 = extrude(sketch001, length = 5)
sketch002 = startSketchOn(extrude001, 'END') sketch002 = startSketchOn(extrude001, face = END)
|> |>
`.replace(/\s/g, '') `.replace(/\s/g, '')
) )
@ -1363,73 +1365,6 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
}) })
}) })
test.describe('Sketch mode should be toleratant to syntax errors', () => {
test(
'adding a syntax error, recovers after fixing',
{ tag: ['@skipWin'] },
async ({ page, homePage, context, scene, editor, toolbar }) => {
const file = await fs.readFile(
path.resolve(
__dirname,
'../../',
'./rust/kcl-lib/e2e/executor/inputs/e2e-can-sketch-on-chamfer.kcl'
),
'utf-8'
)
await context.addInitScript((file) => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
const [objClick] = scene.makeMouseHelpers(600, 250)
const arrowHeadLocation = { x: 706, y: 129 } as const
const arrowHeadWhite = TEST_COLORS.WHITE
const backgroundGray: [number, number, number] = [28, 28, 28]
const verifyArrowHeadColor = async (c: [number, number, number]) =>
scene.expectPixelColor(c, arrowHeadLocation, 15)
await test.step('check chamfer selection changes cursor positon', async () => {
await expect(async () => {
// sometimes initial click doesn't register
await objClick()
await editor.expectActiveLinesToBe([
'|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]',
])
}).toPass({ timeout: 15_000, intervals: [500] })
})
await test.step('enter sketch and sanity check segments have been drawn', async () => {
await toolbar.editSketch()
// this checks sketch segments have been drawn
await verifyArrowHeadColor(arrowHeadWhite)
})
await test.step('Make typo and check the segments have Disappeared and there is a syntax error', async () => {
await editor.replaceCode('line(endAbsolute = [pro', 'badBadBadFn([pro')
await editor.expectState({
activeLines: [],
diagnostics: ['memoryitemkey`badBadBadFn`isnotdefined'],
highlightedCode: '',
})
// this checks sketch segments have failed to be drawn
await verifyArrowHeadColor(backgroundGray)
})
await test.step('', async () => {
await editor.replaceCode('badBadBadFn([pro', 'line(endAbsolute = [pro')
await editor.expectState({
activeLines: [],
diagnostics: [],
highlightedCode: '',
})
// this checks sketch segments have been drawn
await verifyArrowHeadColor(arrowHeadWhite)
})
await page.waitForTimeout(100)
}
)
})
test.describe(`Sketching with offset planes`, () => { test.describe(`Sketching with offset planes`, () => {
test(`Can select an offset plane to sketch on`, async ({ test(`Can select an offset plane to sketch on`, async ({
context, context,
@ -1623,6 +1558,7 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `@settings(defaultLengthUnit = in)
sketch001 = startSketchOn(XZ) sketch001 = startSketchOn(XZ)
profile002 = startProfileAt([40.68, 87.67], sketch001) profile002 = startProfileAt([40.68, 87.67], sketch001)
|> xLine(length = 239.17) |> xLine(length = 239.17)
@ -2634,7 +2570,7 @@ profile001 = startProfileAt([6.71, -3.66], sketch001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
extrude001 = extrude(profile001, length = 20) extrude001 = extrude(profile001, length = 20)
sketch002 = startSketchOn(extrude001, seg01) sketch002 = startSketchOn(extrude001, face = seg01)
profile002 = startProfileAt([0.75, 13.46], sketch002) profile002 = startProfileAt([0.75, 13.46], sketch002)
|> line(end = [4.52, 3.79]) |> line(end = [4.52, 3.79])
|> line(end = [5.98, -2.81]) |> line(end = [5.98, -2.81])
@ -3034,4 +2970,387 @@ test.describe('Redirecting to home page and back to the original file should cle
await homePage.openProject('testDefault') await homePage.openProject('testDefault')
await expect(page.getByText('323.49')).not.toBeVisible() await expect(page.getByText('323.49')).not.toBeVisible()
}) })
test('Straight line snapping to previous tangent', async ({
page,
homePage,
toolbar,
scene,
cmdBar,
context,
editor,
}) => {
await context.addInitScript(() => {
localStorage.setItem('persistCode', `@settings(defaultLengthUnit = mm)`)
})
const viewportSize = { width: 1200, height: 900 }
await page.setBodyDimensions(viewportSize)
await homePage.goToModelingScene()
// wait until scene is ready to be interacted with
await scene.connectionEstablished()
await scene.settled(cmdBar)
await page.getByRole('button', { name: 'Start Sketch' }).click()
// select an axis plane
await page.mouse.click(700, 200)
// Needed as we don't yet have a way to get a signal from the engine that the camera has animated to the sketch plane
await page.waitForTimeout(3000)
const center = { x: viewportSize.width / 2, y: viewportSize.height / 2 }
const { click00r } = getMovementUtils({ center, page })
// Draw line
await click00r(0, 0)
await click00r(200, -200)
// Draw arc
await toolbar.tangentialArcBtn.click()
await click00r(0, 0)
await click00r(100, 100)
// Switch back to line
await toolbar.selectLine()
await click00r(0, 0)
await click00r(-100, 100)
// Draw a 3 point arc
await toolbar.selectThreePointArc()
await click00r(0, 0)
await click00r(0, 100)
await click00r(100, 0)
// draw a line to opposite tangnet direction of previous arc
await toolbar.selectLine()
await click00r(0, 0)
await click00r(-200, 200)
await editor.expectEditor.toContain(
`@settings(defaultLengthUnit = mm)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([0, 0], sketch001)
|> line(end = [191.39, 191.39])
|> tangentialArc(endAbsolute = [287.08, 95.69], tag = $seg01)
|> angledLine(angle = tangentToEnd(seg01), length = 135.34)
|> arcTo({
interior = [191.39, -95.69],
end = [287.08, -95.69]
}, %, $seg02)
|> angledLine(angle = tangentToEnd(seg02) + turns::HALF_TURN, length = 270.67)
`.replaceAll('\n', '')
)
})
})
test.describe('manual edits during sketch mode', () => {
test('Can edit sketch through feature tree with variable modifications', async ({
page,
context,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `myVar1 = 5
myVar2 = 6
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([106.68, 89.77], sketch001)
|> line(end = [132.34, 157.8])
|> line(end = [67.65, -460.55], tag = $seg01)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude001 = extrude(profile001, length = 500)
sketch002 = startSketchOn(extrude001, face = seg01)
profile002 = startProfileAt([83.39, 329.15], sketch002)
|> angledLine(angle = 0, length = 119.61, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 156.54, angle = -28)
|> angledLine(
angle = segAng(rectangleSegmentA001),
length = -segLen(rectangleSegmentA001),
angle = -151,
length = 116.27,
)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
profile003 = startProfileAt([-201.08, 254.17], sketch002)
|> line(end = [103.55, 33.32])
|> line(end = [48.8, -153.54])`
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await homePage.goToModelingScene()
await scene.connectionEstablished()
await scene.settled(cmdBar)
const expectSketchOriginToBeDrawn = async () => {
await scene.expectPixelColor(TEST_COLORS.WHITE, { x: 672, y: 193 }, 15)
}
await test.step('Open feature tree and edit second sketch', async () => {
await toolbar.openFeatureTreePane()
const sketchButton = await toolbar.getFeatureTreeOperation('Sketch', 1)
await sketchButton.dblclick()
await page.waitForTimeout(700) // Wait for engine animation
await expectSketchOriginToBeDrawn()
})
await test.step('Add new variable and wait for re-execution', async () => {
await page.waitForTimeout(500) // wait for deferred execution
await editor.replaceCode('myVar2 = 6', 'myVar2 = 6\nmyVar3 = 7')
await page.waitForTimeout(2000) // wait for deferred execution
await expectSketchOriginToBeDrawn()
})
const handle1Location = { x: 843, y: 235 }
await test.step('Edit sketch by dragging handle', async () => {
await page.waitForTimeout(500)
await editor.expectEditor.toContain('length = 156.54, angle = -28')
await page.mouse.move(handle1Location.x, handle1Location.y)
await page.mouse.down()
await page.mouse.move(handle1Location.x + 50, handle1Location.y + 50, {
steps: 5,
})
await page.mouse.up()
await editor.expectEditor.toContain('length = 231.59, angle = -34')
// await page.waitForTimeout(1000) // Wait for update
})
await test.step('Delete variables and wait for re-execution', async () => {
await page.waitForTimeout(500)
await editor.replaceCode('myVar3 = 7', '')
await page.waitForTimeout(50)
await editor.replaceCode('myVar2 = 6', '')
await page.waitForTimeout(2000) // Wait for deferred execution
await expectSketchOriginToBeDrawn()
})
const handle2Location = { x: 872, y: 273 }
await test.step('Edit sketch again', async () => {
await editor.expectEditor.toContain('length = 231.59, angle = -34')
await page.waitForTimeout(500)
await page.mouse.move(handle2Location.x, handle2Location.y)
await page.mouse.down()
await page.mouse.move(handle2Location.x, handle2Location.y - 50, {
steps: 5,
})
await page.mouse.up()
await editor.expectEditor.toContain('length = 167.36, angle = -14')
})
await test.step('add whole other sketch before current sketch', async () => {
await page.waitForTimeout(500)
await editor.replaceCode(
`myVar1 = 5`,
`myVar1 = 5
sketch003 = startSketchOn(XY)
profile004 = circle(sketch003, center = [143.91, 136.89], radius = 71.63)`
)
await page.waitForTimeout(2000) // Wait for deferred execution
await expectSketchOriginToBeDrawn()
})
const handle3Location = { x: 844, y: 212 }
await test.step('edit sketch again', async () => {
await editor.expectEditor.toContain('length = 167.36, angle = -14')
await page.mouse.move(handle3Location.x, handle3Location.y)
await page.mouse.down()
await page.mouse.move(handle3Location.x, handle3Location.y + 110, {
steps: 5,
})
await page.mouse.up()
await editor.expectEditor.toContain('length = 219.2, angle = -56')
})
// exit sketch and assert whole code
await test.step('Exit sketch and assert code', async () => {
await toolbar.exitSketch()
await editor.expectEditor.toContain(
`myVar1 = 5
sketch003 = startSketchOn(XY)
profile004 = circle(sketch003, center = [143.91, 136.89], radius = 71.63)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([106.68, 89.77], sketch001)
|> line(end = [132.34, 157.8])
|> line(end = [67.65, -460.55], tag = $seg01)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude001 = extrude(profile001, length = 500)
sketch002 = startSketchOn(extrude001, face = seg01)
profile002 = startProfileAt([83.39, 329.15], sketch002)
|> angledLine(angle = 0, length = 119.61, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 219.2, angle = -56)
|> angledLine(
angle = segAng(rectangleSegmentA001),
length = -segLen(rectangleSegmentA001),
angle = -151,
length = 116.27,
)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
profile003 = startProfileAt([-201.08, 254.17], sketch002)
|> line(end = [103.55, 33.32])
|> line(end = [48.8, -153.54])
`,
{ shouldNormalise: true }
)
await editor.expectState({
activeLines: [],
diagnostics: [],
highlightedCode: '',
})
})
})
test('Will exit out of sketch mode for some incompatible edits', async ({
page,
context,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `myVar1 = 5
myVar2 = 6
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([106.68, 89.77], sketch001)
|> line(end = [132.34, 157.8])
|> line(end = [67.65, -460.55], tag = $seg01)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude001 = extrude(profile001, length = 500)
sketch002 = startSketchOn(extrude001, face = seg01)
profile002 = startProfileAt([83.39, 329.15], sketch002)
|> angledLine(angle = 0, length = 119.61, tag = $rectangleSegmentA001)
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 156.54, angle = -28)
|> angledLine(
angle = segAng(rectangleSegmentA001),
length = -segLen(rectangleSegmentA001),
angle = -151,
length = 116.27,
)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
profile003 = startProfileAt([-201.08, 254.17], sketch002)
|> line(end = [103.55, 33.32])
|> line(end = [48.8, -153.54])`
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await homePage.goToModelingScene()
await scene.connectionEstablished()
await scene.settled(cmdBar)
const expectSketchOriginToBeDrawn = async () => {
await scene.expectPixelColor(TEST_COLORS.WHITE, { x: 672, y: 193 }, 15)
}
await test.step('Open feature tree and edit second sketch', async () => {
await toolbar.openFeatureTreePane()
const sketchButton = await toolbar.getFeatureTreeOperation('Sketch', 1)
await sketchButton.dblclick()
await page.waitForTimeout(700) // Wait for engine animation
await expectSketchOriginToBeDrawn()
})
await test.step('rename variable of current sketch, sketch002 to changeSketchNamePartWayThrough', async () => {
await editor.replaceCode('sketch002', 'changeSketchNamePartWayThrough')
await page.waitForTimeout(100)
// three times to rename the declaration and it's use
await editor.replaceCode('sketch002', 'changeSketchNamePartWayThrough')
await page.waitForTimeout(100)
await editor.replaceCode('sketch002', 'changeSketchNamePartWayThrough')
await expect(
page.getByText('Unable to maintain sketch mode')
).toBeVisible()
})
})
test(
'adding a syntax error, recovers after fixing',
{ tag: ['@skipWin'] },
async ({ page, homePage, context, scene, editor, toolbar, cmdBar }) => {
const file = await fs.readFile(
path.resolve(
__dirname,
'../../',
'./rust/kcl-lib/e2e/executor/inputs/e2e-can-sketch-on-chamfer.kcl'
),
'utf-8'
)
await context.addInitScript((file) => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
const [objClick] = scene.makeMouseHelpers(600, 250)
const arrowHeadLocation = { x: 706, y: 129 } as const
const arrowHeadWhite = TEST_COLORS.WHITE
const backgroundGray: [number, number, number] = [28, 28, 28]
const verifyArrowHeadColor = async (c: [number, number, number]) =>
scene.expectPixelColor(c, arrowHeadLocation, 15)
// wait for scene to load
await scene.settled(cmdBar)
await test.step('check chamfer selection changes cursor positon', async () => {
await expect(async () => {
// sometimes initial click doesn't register
await objClick()
await editor.expectActiveLinesToBe([
'|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]',
])
}).toPass({ timeout: 15_000, intervals: [500] })
})
await test.step('enter sketch and sanity check segments have been drawn', async () => {
await toolbar.editSketch()
// this checks sketch segments have been drawn
await verifyArrowHeadColor(arrowHeadWhite)
})
await test.step('Make typo and check the segments have Disappeared and there is a syntax error', async () => {
await editor.replaceCode(
'line(endAbsolute = [pro',
'badBadBadFn(endAbsolute = [pro'
)
await editor.expectState({
activeLines: [],
diagnostics: ['memoryitemkey`badBadBadFn`isnotdefined'],
highlightedCode: '',
})
await expect(
page.getByText(
"Error in kcl script, sketch cannot be drawn until it's fixed"
)
).toBeVisible()
// this checks sketch segments have failed to be drawn
await verifyArrowHeadColor(backgroundGray)
})
await test.step('', async () => {
await editor.replaceCode(
'badBadBadFn(endAbsolute = [pro',
'line(endAbsolute = [pro'
)
await editor.expectState({
activeLines: [],
diagnostics: [],
highlightedCode: '',
})
// this checks sketch segments have been drawn
await verifyArrowHeadColor(arrowHeadWhite)
})
await page.waitForTimeout(100)
}
)
}) })

View File

@ -1,9 +1,9 @@
import { spawn } from 'child_process'
import path from 'path'
import type { Models } from '@kittycad/lib' import type { Models } from '@kittycad/lib'
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants' import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
import { spawn } from 'child_process'
import fsp from 'fs/promises' import fsp from 'fs/promises'
import JSZip from 'jszip' import JSZip from 'jszip'
import path from 'path'
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture' import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture' import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
@ -13,6 +13,8 @@ import type { Paths } from '@e2e/playwright/test-utils'
import { import {
doExport, doExport,
getUtils, getUtils,
headerMasks,
networkingMasks,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
settingsToToml, settingsToToml,
} from '@e2e/playwright/test-utils' } from '@e2e/playwright/test-utils'
@ -77,11 +79,7 @@ part001 = startSketchOn(-XZ)
) )
|> xLine(endAbsolute = totalLen, tag = $seg03) |> xLine(endAbsolute = totalLen, tag = $seg03)
|> yLine(length = -armThick, tag = $seg01) |> yLine(length = -armThick, tag = $seg01)
|> angledLineThatIntersects({ |> angledLineThatIntersects(angle = turns::HALF_TURN, offset = -armThick, intersectTag = seg04)
angle = turns::HALF_TURN,
offset = -armThick,
intersectTag = seg04
}, %)
|> angledLine(angle = segAng(seg04, %) + 180, endAbsoluteY = turns::ZERO) |> angledLine(angle = segAng(seg04, %) + 180, endAbsoluteY = turns::ZERO)
|> angledLine( |> angledLine(
angle = -bottomAng, angle = -bottomAng,
@ -90,11 +88,7 @@ part001 = startSketchOn(-XZ)
) )
|> xLine(length = endAbsolute = segEndX(seg03) + 0) |> xLine(length = endAbsolute = segEndX(seg03) + 0)
|> yLine(length = -segLen(seg01, %)) |> yLine(length = -segLen(seg01, %))
|> angledLineThatIntersects({ |> angledLineThatIntersects(angle = turns::HALF_TURN, offset = -armThick, intersectTag = seg02)
angle = turns::HALF_TURN,
offset = -armThick,
intersectTag = seg02
}, %)
|> angledLine(angle = segAng(seg02, %) + 180, endAbsoluteY = -baseHeight) |> angledLine(angle = segAng(seg02, %) + 180, endAbsoluteY = -baseHeight)
|> xLine(endAbsolute = turns::ZERO) |> xLine(endAbsolute = turns::ZERO)
|> close() |> close()
@ -374,7 +368,7 @@ const extrudeDefaultPlane = async (
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
await u.openKclCodePanel() await u.openKclCodePanel()
} }
@ -462,7 +456,7 @@ test(
await page.waitForTimeout(500) await page.waitForTimeout(500)
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
const lineEndClick = () => const lineEndClick = () =>
@ -491,7 +485,7 @@ test(
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
await endOfTangentClk() await endOfTangentClk()
@ -501,7 +495,7 @@ test(
await threePointArcMidPointMv() await threePointArcMidPointMv()
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
await threePointArcMidPointClk() await threePointArcMidPointClk()
await page.waitForTimeout(100) await page.waitForTimeout(100)
@ -510,7 +504,7 @@ test(
await page.waitForTimeout(500) await page.waitForTimeout(500)
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
await threePointArcEndPointClk() await threePointArcEndPointClk()
@ -530,7 +524,7 @@ test(
await page.waitForTimeout(500) await page.waitForTimeout(500)
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
await arcEndClk() await arcEndClk()
} }
@ -580,7 +574,7 @@ test(
// Ensure the draft rectangle looks the same as it usually does // Ensure the draft rectangle looks the same as it usually does
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
} }
) )
@ -623,7 +617,7 @@ test(
// Ensure the draft rectangle looks the same as it usually does // Ensure the draft rectangle looks the same as it usually does
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content')).toHaveText(
`sketch001 = startSketchOn(XZ)profile001 = circle(sketch001, center = [366.89, -62.01], radius = 1)` `sketch001 = startSketchOn(XZ)profile001 = circle(sketch001, center = [366.89, -62.01], radius = 1)`
@ -696,7 +690,7 @@ test.describe(
// screen shot should show the sketch // screen shot should show the sketch
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
await u.doAndWaitForImageDiff( await u.doAndWaitForImageDiff(
@ -709,7 +703,7 @@ test.describe(
// second screen shot should look almost identical, i.e. scale should be the same. // second screen shot should look almost identical, i.e. scale should be the same.
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
}) })
@ -789,6 +783,7 @@ test.describe(
// screen shot should show the sketch // screen shot should show the sketch
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: networkingMasks(page),
}) })
// exit sketch // exit sketch
@ -802,6 +797,7 @@ test.describe(
// second screen shot should look almost identical, i.e. scale should be the same. // second screen shot should look almost identical, i.e. scale should be the same.
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: networkingMasks(page),
}) })
}) })
} }
@ -824,7 +820,7 @@ test(
|> line(end = [11.91, -10.42]) |> line(end = [11.91, -10.42])
|> close() |> close()
|> extrude(length = ${KCL_DEFAULT_LENGTH}) |> extrude(length = ${KCL_DEFAULT_LENGTH})
part002 = startSketchOn(part001, seg01) part002 = startSketchOn(part001, face = seg01)
|> startProfileAt([8, 8], %) |> startProfileAt([8, 8], %)
|> line(end = [4.68, 3.05]) |> line(end = [4.68, 3.05])
|> line(end = [0, -7.79]) |> line(end = [0, -7.79])
@ -863,7 +859,7 @@ part002 = startSketchOn(part001, seg01)
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
} }
) )
@ -902,7 +898,7 @@ test(
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
} }
) )
@ -942,7 +938,7 @@ test(
await expect(page).toHaveScreenshot({ await expect(page).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
} }
) )
@ -955,11 +951,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
const stream = page.getByTestId('stream') const stream = page.getByTestId('stream')
const mask = [
page.locator('#app-header'),
page.locator('#sidebar-top-ribbon'),
page.locator('#sidebar-bottom-ribbon'),
]
await page.setViewportSize({ width: 1200, height: 500 }) await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('/') await page.goto('/')
@ -1012,18 +1003,13 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await expect(stream).toHaveScreenshot({ await expect(stream).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask, mask: [...headerMasks(page), ...networkingMasks(page)],
}) })
}) })
test('Grid turned off', async ({ page, cmdBar, scene }) => { test('Grid turned off', async ({ page, cmdBar, scene }) => {
const u = await getUtils(page) const u = await getUtils(page)
const stream = page.getByTestId('stream') const stream = page.getByTestId('stream')
const mask = [
page.locator('#app-header'),
page.locator('#sidebar-top-ribbon'),
page.locator('#sidebar-bottom-ribbon'),
]
await page.setViewportSize({ width: 1200, height: 500 }) await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('/') await page.goto('/')
@ -1038,7 +1024,7 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await expect(stream).toHaveScreenshot({ await expect(stream).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask, mask: [...headerMasks(page), ...networkingMasks(page)],
}) })
}) })
@ -1063,11 +1049,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
const u = await getUtils(page) const u = await getUtils(page)
const stream = page.getByTestId('stream') const stream = page.getByTestId('stream')
const mask = [
page.locator('#app-header'),
page.locator('#sidebar-top-ribbon'),
page.locator('#sidebar-bottom-ribbon'),
]
await page.setViewportSize({ width: 1200, height: 500 }) await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('/') await page.goto('/')
@ -1082,7 +1063,7 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await expect(stream).toHaveScreenshot({ await expect(stream).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask, mask: [...headerMasks(page), ...networkingMasks(page)],
}) })
}) })
}) })
@ -1151,6 +1132,7 @@ test('theme persists', async ({ page, context }) => {
await expect(page, 'expect screenshot to have light theme').toHaveScreenshot({ await expect(page, 'expect screenshot to have light theme').toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: networkingMasks(page),
}) })
}) })
@ -1166,9 +1148,9 @@ test.describe('code color goober', { tag: '@snapshot' }, () => {
sweepPath = startSketchOn(XZ) sweepPath = startSketchOn(XZ)
|> startProfileAt([0.05, 0.05], %) |> startProfileAt([0.05, 0.05], %)
|> line(end = [0, 7]) |> line(end = [0, 7])
|> tangentialArc({ offset = 90, radius = 5 }, %) |> tangentialArc(angle = 90, radius = 5)
|> line(end = [-3, 0]) |> line(end = [-3, 0])
|> tangentialArc({ offset = -90, radius = 5 }, %) |> tangentialArc(angle = -90, radius = 5)
|> line(end = [0, 7]) |> line(end = [0, 7])
sweepSketch = startSketchOn(XY) sweepSketch = startSketchOn(XY)
@ -1195,7 +1177,7 @@ sweepSketch = startSketchOn(XY)
await expect(page, 'expect small color widget').toHaveScreenshot({ await expect(page, 'expect small color widget').toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
}) })
@ -1215,9 +1197,9 @@ sweepSketch = startSketchOn(XY)
sweepPath = startSketchOn(XZ) sweepPath = startSketchOn(XZ)
|> startProfileAt([0.05, 0.05], %) |> startProfileAt([0.05, 0.05], %)
|> line(end = [0, 7]) |> line(end = [0, 7])
|> tangentialArc({ offset = 90, radius = 5 }, %) |> tangentialArc(angle = 90, radius = 5)
|> line(end = [-3, 0]) |> line(end = [-3, 0])
|> tangentialArc({ offset = -90, radius = 5 }, %) |> tangentialArc(angle = -90, radius = 5)
|> line(end = [0, 7]) |> line(end = [0, 7])
sweepSketch = startSketchOn(XY) sweepSketch = startSketchOn(XY)
@ -1252,7 +1234,7 @@ sweepSketch = startSketchOn(XY)
'expect small color widget to have window open' 'expect small color widget to have window open'
).toHaveScreenshot({ ).toHaveScreenshot({
maxDiffPixels: 100, maxDiffPixels: 100,
mask: [page.getByTestId('model-state-indicator')], mask: networkingMasks(page),
}) })
}) })
}) })

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 52 KiB

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