Compare commits
169 Commits
update-sna
...
v0.22.3
Author | SHA1 | Date | |
---|---|---|---|
1beb6b5186 | |||
17978ab1d7 | |||
a1bcad9dfb | |||
2e7bdf02cf | |||
6f76196b72 | |||
e7af064518 | |||
674d49e2ae | |||
4cb48674c6 | |||
82daec2aff | |||
f1ef9d5200 | |||
dc226d3270 | |||
7bf50d8fe0 | |||
b26764bc9a | |||
1b0c6298d7 | |||
fe9a483726 | |||
bd42ea037b | |||
fdb1b21af3 | |||
630ef316b8 | |||
e322926be9 | |||
a9e61da8b5 | |||
e2a835a437 | |||
c61273085f | |||
a79e365c0f | |||
2386ba24e5 | |||
e42a891df8 | |||
98200565bf | |||
570fd827ed | |||
0add26cf61 | |||
b54fc534c2 | |||
c66f851a3f | |||
13b8ab71d8 | |||
bdeab4f87d | |||
05ccf5e2f4 | |||
7ab015d783 | |||
3d6cfa980f | |||
9f5f1eb8c3 | |||
50fcdff879 | |||
efaae2b193 | |||
7e4ebacb72 | |||
72482506c3 | |||
a51b5b09a3 | |||
53ccc1ed6c | |||
8106749ccf | |||
081e34a600 | |||
541400f4be | |||
39d249030d | |||
f8a69fac73 | |||
24f4bf160f | |||
8011594e24 | |||
0e09affb8f | |||
197a47346a | |||
9d083710e0 | |||
afa7c1dc4e | |||
c74b695a71 | |||
d0c244e05e | |||
a315b77f02 | |||
15c854ff18 | |||
acd3a5717d | |||
8a2555550f | |||
62e75c852a | |||
dd3601ea7b | |||
a5e7782d9a | |||
79b0b70688 | |||
1d134c1be0 | |||
1c58572234 | |||
ecee51e82b | |||
978ac42f1c | |||
893996430e | |||
41e65fc4e9 | |||
99aa74ceba | |||
0bcf33ed00 | |||
d0a9b5ecab | |||
a569f818cf | |||
f73556ba7b | |||
29cdc66b34 | |||
c9800a58d0 | |||
e46aca4992 | |||
9564890b29 | |||
f8a1f40f20 | |||
c551d88db4 | |||
8eee3e1c58 | |||
b02529cae0 | |||
cf03021366 | |||
f52d2d55f1 | |||
59b1319e50 | |||
b07bbda20b | |||
3c01924184 | |||
bd16902f02 | |||
8c3af1a72a | |||
33f5d7740d | |||
b388f60648 | |||
8f4380be74 | |||
9ae8042a57 | |||
4b676d47da | |||
e6641e68f3 | |||
450afb1605 | |||
04433fecad | |||
6567e2ff92 | |||
91c32a7fe2 | |||
f735cdc22e | |||
1b72c7df85 | |||
062abd148f | |||
c93ed0f306 | |||
27e2518dde | |||
dc6505acaf | |||
6ff3284eca | |||
4cb6ceb043 | |||
1db3e1b5e4 | |||
d797d20d50 | |||
cf52e151fb | |||
87c551b869 | |||
2001262494 | |||
777b225066 | |||
ae6373e4f5 | |||
87979b17cf | |||
4be63e7331 | |||
56d930c4f2 | |||
d48eb0c66c | |||
a69d7d03d0 | |||
00a8273173 | |||
51868f892b | |||
8e9286a747 | |||
023ed1a687 | |||
5b7d707b26 | |||
5b95194aa7 | |||
6080a99e73 | |||
5106c49e21 | |||
25f18845c7 | |||
0a7f1a41fc | |||
1625b58577 | |||
ab6115c4e2 | |||
fe621240c3 | |||
97faf5ae2b | |||
e3b9a6e5d8 | |||
e94b1bc12a | |||
c0eff5bc14 | |||
b0f92c2f6d | |||
718873b3bb | |||
9f815eecc1 | |||
0384e5e6c6 | |||
48ef0885b7 | |||
3b2731f924 | |||
bf4e04f9f1 | |||
24475bbcdf | |||
bcca736a8d | |||
440eb2636a | |||
344e72d7ec | |||
ec7b733a0d | |||
63159c1cb8 | |||
df62a995b5 | |||
fa762c1c4d | |||
82b03a9d47 | |||
793b7407f6 | |||
040bcc2c09 | |||
ae2e219394 | |||
a83f549257 | |||
3871d2858f | |||
3effb87f8e | |||
3f2f035a9b | |||
4735eaef8c | |||
69f8da058a | |||
93ebf13621 | |||
20c4d44b8b | |||
8ea8f80e32 | |||
d73339fd8d | |||
031b230690 | |||
1125d74f12 | |||
5c7a2822d0 | |||
d44b1f8e54 |
@ -1,3 +1,3 @@
|
|||||||
[codespell]
|
[codespell]
|
||||||
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,absolutey,atleast
|
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,absolutey,atleast,ue
|
||||||
skip: **/target,node_modules,build,**/Cargo.lock,./docs/kcl/*.md,./src-tauri/gen/schemas
|
skip: **/target,node_modules,build,**/Cargo.lock,./docs/kcl/*.md,./src-tauri/gen/schemas
|
||||||
|
40
.github/workflows/cargo-check.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- '**/Cargo.toml'
|
||||||
|
- '**/Cargo.lock'
|
||||||
|
- '**/rust-toolchain.toml'
|
||||||
|
- '**.rs'
|
||||||
|
- .github/workflows/cargo-check.yml
|
||||||
|
pull_request:
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
name: cargo check
|
||||||
|
jobs:
|
||||||
|
cargocheck:
|
||||||
|
name: cargo check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
dir: ['src/wasm-lib']
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install latest rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
|
||||||
|
- name: Rust Cache
|
||||||
|
uses: Swatinem/rust-cache@v2.6.1
|
||||||
|
|
||||||
|
- name: Run check
|
||||||
|
run: |
|
||||||
|
cd "${{ matrix.dir }}"
|
||||||
|
# We specifically want to test the disable-println feature
|
||||||
|
# Since it is not enabled by default, we need to specify it
|
||||||
|
# This is used in kcl-lsp
|
||||||
|
cargo check --all --features disable-println --features pyo3
|
11
.github/workflows/cargo-clippy.yml
vendored
@ -9,6 +9,12 @@ on:
|
|||||||
- '**.rs'
|
- '**.rs'
|
||||||
- .github/workflows/cargo-clippy.yml
|
- .github/workflows/cargo-clippy.yml
|
||||||
pull_request:
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '**/Cargo.toml'
|
||||||
|
- '**/Cargo.lock'
|
||||||
|
- '**/rust-toolchain.toml'
|
||||||
|
- '**.rs'
|
||||||
|
- .github/workflows/cargo-clippy.yml
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
@ -54,3 +60,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd "${{ matrix.dir }}"
|
cd "${{ matrix.dir }}"
|
||||||
cargo clippy --all --tests --benches -- -D warnings
|
cargo clippy --all --tests --benches -- -D warnings
|
||||||
|
# If this fails, run "cargo check" to update Cargo.lock,
|
||||||
|
# then add Cargo.lock to the PR.
|
||||||
|
- name: Check Cargo.lock doesn't need updating
|
||||||
|
run: |
|
||||||
|
cargo check --locked || echo "Pls run cargo check and commit the changed Cargo.lock"
|
||||||
|
21
.github/workflows/ci.yml
vendored
@ -147,6 +147,14 @@ jobs:
|
|||||||
cp artifact/src-tauri/tauri.conf.json src-tauri/tauri.conf.json
|
cp artifact/src-tauri/tauri.conf.json src-tauri/tauri.conf.json
|
||||||
cp artifact/src-tauri/tauri.release.conf.json src-tauri/tauri.release.conf.json
|
cp artifact/src-tauri/tauri.release.conf.json src-tauri/tauri.release.conf.json
|
||||||
|
|
||||||
|
- name: Update WebView2 on Windows
|
||||||
|
if: matrix.os == 'windows-latest'
|
||||||
|
# Workaround needed to build the tauri windows app with matching edge version.
|
||||||
|
# From https://github.com/actions/runner-images/issues/9538
|
||||||
|
run: |
|
||||||
|
Invoke-WebRequest -Uri 'https://go.microsoft.com/fwlink/p/?LinkId=2124703' -OutFile 'setup.exe'
|
||||||
|
Start-Process -FilePath setup.exe -Verb RunAs -Wait
|
||||||
|
|
||||||
- name: Install ubuntu system dependencies
|
- name: Install ubuntu system dependencies
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
run: |
|
run: |
|
||||||
@ -172,9 +180,7 @@ jobs:
|
|||||||
- name: Setup Rust
|
- name: Setup Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
||||||
# TODO: re-enable for Windows builds, see https://github.com/tauri-apps/tauri/issues/9045
|
|
||||||
- name: Setup Rust cache
|
- name: Setup Rust cache
|
||||||
if: matrix.os != 'windows-latest'
|
|
||||||
uses: swatinem/rust-cache@v2
|
uses: swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
workspaces: './src-tauri -> target'
|
workspaces: './src-tauri -> target'
|
||||||
@ -364,6 +370,17 @@ jobs:
|
|||||||
E2E_APPLICATION: "./src-tauri/target/${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}/zoo-modeling-app"
|
E2E_APPLICATION: "./src-tauri/target/${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}/zoo-modeling-app"
|
||||||
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
|
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
|
||||||
|
- name: Run e2e tests (windows only)
|
||||||
|
if: ${{ matrix.os == 'windows-latest' && github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
run: |
|
||||||
|
cargo install tauri-driver --force
|
||||||
|
yarn wdio run wdio.conf.ts
|
||||||
|
env:
|
||||||
|
E2E_APPLICATION: ".\\src-tauri\\target\\${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}\\Zoo Modeling App.exe"
|
||||||
|
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
VITE_KC_API_BASE_URL: ${{ env.BUILD_RELEASE == 'true' && 'https://api.zoo.dev' || 'https://api.dev.zoo.dev' }}
|
||||||
|
E2E_TAURI_ENABLED: true
|
||||||
|
TS_NODE_COMPILER_OPTIONS: '{"module": "commonjs"}'
|
||||||
|
|
||||||
publish-apps-release:
|
publish-apps-release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
26
.github/workflows/playwright.yml
vendored
@ -46,12 +46,18 @@ jobs:
|
|||||||
- uses: KittyCAD/action-install-cli@main
|
- uses: KittyCAD/action-install-cli@main
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn
|
run: yarn
|
||||||
|
- name: Cache Playwright Browsers
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/ms-playwright/
|
||||||
|
key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }}
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
run: yarn playwright install --with-deps
|
run: yarn playwright install --with-deps
|
||||||
- name: Download Wasm Cache
|
- name: Download Wasm Cache
|
||||||
id: download-wasm
|
id: download-wasm
|
||||||
if: needs.check-rust-changes.outputs.rust-changed == 'false'
|
if: needs.check-rust-changes.outputs.rust-changed == 'false'
|
||||||
uses: dawidd6/action-download-artifact@v3
|
uses: dawidd6/action-download-artifact@v6
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||||
@ -115,7 +121,7 @@ jobs:
|
|||||||
git fetch origin
|
git fetch origin
|
||||||
echo ${{ github.head_ref }}
|
echo ${{ github.head_ref }}
|
||||||
git checkout ${{ github.head_ref }}
|
git checkout ${{ github.head_ref }}
|
||||||
# TODO when safari works on ubuntu remove the os part of the commit message
|
# TODO when webkit works on ubuntu remove the os part of the commit message
|
||||||
git commit -am "A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)" || true
|
git commit -am "A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)" || true
|
||||||
git push
|
git push
|
||||||
git push origin ${{ github.head_ref }}
|
git push origin ${{ github.head_ref }}
|
||||||
@ -127,7 +133,7 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: playwright-report
|
name: playwright-report-ubuntu
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
@ -143,12 +149,20 @@ jobs:
|
|||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn
|
run: yarn
|
||||||
|
- name: Cache Playwright Browsers
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/ms-playwright
|
||||||
|
key: ${{ runner.os }}-playwright-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-playwright-
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
run: yarn playwright install --with-deps
|
run: yarn playwright install --with-deps
|
||||||
- name: Download Wasm Cache
|
- name: Download Wasm Cache
|
||||||
id: download-wasm
|
id: download-wasm
|
||||||
if: needs.check-rust-changes.outputs.rust-changed == 'false'
|
if: needs.check-rust-changes.outputs.rust-changed == 'false'
|
||||||
uses: dawidd6/action-download-artifact@v3
|
uses: dawidd6/action-download-artifact@v6
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||||
@ -181,7 +195,7 @@ jobs:
|
|||||||
- name: build web
|
- name: build web
|
||||||
run: yarn build:local
|
run: yarn build:local
|
||||||
- name: Run macos/safari flow
|
- name: Run macos/safari flow
|
||||||
# safari doesn't work on Ubuntu because of the same reason tauri doesn't (webRTC issues)
|
# webkit doesn't work on Ubuntu because of the same reason tauri doesn't (webRTC issues)
|
||||||
# TODO remove this and the matrix and run all tests on ubuntu when this is fixed
|
# TODO remove this and the matrix and run all tests on ubuntu when this is fixed
|
||||||
run: yarn playwright test --project="webkit" e2e/playwright/flow-tests.spec.ts
|
run: yarn playwright test --project="webkit" e2e/playwright/flow-tests.spec.ts
|
||||||
env:
|
env:
|
||||||
@ -190,6 +204,6 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: playwright-report
|
name: playwright-report-macos
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
1
.gitignore
vendored
@ -17,6 +17,7 @@
|
|||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
.env.production.local
|
.env.production.local
|
||||||
|
.direnv
|
||||||
|
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
|
14
Makefile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
.PHONY: dev
|
||||||
|
|
||||||
|
WASM_LIB_FILES := $(wildcard src/wasm-lib/**/*.rs)
|
||||||
|
|
||||||
|
dev: node_modules public/wasm_lib_bg.wasm
|
||||||
|
yarn start
|
||||||
|
|
||||||
|
public/wasm_lib_bg.wasm: $(WASM_LIB_FILES)
|
||||||
|
yarn build:wasm-dev
|
||||||
|
|
||||||
|
node_modules: package.json
|
||||||
|
|
||||||
|
package.json:
|
||||||
|
yarn install
|
68
README.md
@ -59,7 +59,9 @@ followed by:
|
|||||||
```
|
```
|
||||||
yarn build:wasm-dev
|
yarn build:wasm-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
or if you have the gh cli installed
|
or if you have the gh cli installed
|
||||||
|
|
||||||
```
|
```
|
||||||
./get-latest-wasm-bundle.sh # this will download the latest main wasm bundle
|
./get-latest-wasm-bundle.sh # this will download the latest main wasm bundle
|
||||||
```
|
```
|
||||||
@ -100,6 +102,7 @@ yarn test
|
|||||||
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.
|
||||||
|
|
||||||
For running the rust (not tauri rust though) only, you can
|
For running the rust (not tauri rust though) only, you can
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd src/wasm-lib
|
cd src/wasm-lib
|
||||||
cargo test
|
cargo test
|
||||||
@ -162,6 +165,7 @@ console.log(
|
|||||||
- `)
|
- `)
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
grab the md list and delete any that are older than the last bump
|
grab the md list and delete any that are older than the last bump
|
||||||
|
|
||||||
2. Merge the PR
|
2. Merge the PR
|
||||||
@ -191,39 +195,49 @@ $ cargo +nightly fuzz run parser
|
|||||||
For more information on fuzzing you can check out
|
For more information on fuzzing you can check out
|
||||||
[this guide](https://rust-fuzz.github.io/book/cargo-fuzz.html).
|
[this guide](https://rust-fuzz.github.io/book/cargo-fuzz.html).
|
||||||
|
|
||||||
|
|
||||||
### Playwright
|
### Playwright
|
||||||
|
|
||||||
First time running plawright locally, you'll need to add the secrets file
|
For a portable way to run Playwright you'll need Docker.
|
||||||
|
|
||||||
|
After that, open a terminal and run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
touch ./e2e/playwright/playwright-secrets.env
|
docker run --network host --rm --init -it playwright/chrome:playwright-1.43.1
|
||||||
printf 'token="your-token"\nsnapshottoken="your-snapshot-token"' > ./e2e/playwright/playwright-secrets.env
|
```
|
||||||
|
|
||||||
|
and in another terminal, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:4444/ yarn playwright test --project="Google Chrome" <test suite>
|
||||||
|
```
|
||||||
|
|
||||||
|
An example of a `<test suite>` is: `e2e/playwright/flow-tests.spec.ts`
|
||||||
|
|
||||||
|
YOU WILL NEED A PLAYWRIGHT-SECRETS.ENV FILE:
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ./e2e/playwright/playwright-secrets.env
|
||||||
|
token=<your-token>
|
||||||
|
snapshottoken=<your-snapshot-token>
|
||||||
```
|
```
|
||||||
then replace "your-token" with a dev token from dev.zoo.dev/account/api-tokens
|
then replace "your-token" with a dev token from dev.zoo.dev/account/api-tokens
|
||||||
|
|
||||||
then:
|
|
||||||
run playwright
|
|
||||||
```
|
|
||||||
yarn playwright test
|
|
||||||
```
|
|
||||||
|
|
||||||
run a specific test suite
|
|
||||||
```
|
|
||||||
yarn playwright test src/e2e-tests/example.spec.ts
|
|
||||||
```
|
|
||||||
|
|
||||||
run a specific test change the test from `test('...` to `test.only('...`
|
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)
|
(note if you commit this, the tests will instantly fail without running any of the tests)
|
||||||
|
|
||||||
run headed
|
run headed
|
||||||
|
|
||||||
```
|
```
|
||||||
yarn playwright test --headed
|
yarn playwright test --headed
|
||||||
```
|
```
|
||||||
|
|
||||||
run with step through debugger
|
run with step through debugger
|
||||||
|
|
||||||
```
|
```
|
||||||
PWDEBUG=1 yarn playwright test
|
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.
|
||||||
|
|
||||||
@ -268,7 +282,6 @@ Where `./store` should look like this
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
||||||
However because much of our tests involve clicking in the stream at specific locations, it's code-gen looks `await page.locator('video').click();` when really we need to use a pixel coord, so I think it's of limited use.
|
However because much of our tests involve clicking in the stream at specific locations, it's code-gen looks `await page.locator('video').click();` when really we need to use a pixel coord, so I think it's of limited use.
|
||||||
|
|
||||||
#### Some notes on CI
|
#### Some notes on CI
|
||||||
@ -299,3 +312,26 @@ PS: for the debug panel, the following JSON is useful for snapping the camera
|
|||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
### Tauri e2e tests
|
||||||
|
|
||||||
|
#### Windows (local only until the CI edge version mismatch is fixed)
|
||||||
|
|
||||||
|
```
|
||||||
|
yarn install
|
||||||
|
yarn build:wasm-dev
|
||||||
|
cp src/wasm-lib/pkg/wasm_lib_bg.wasm public
|
||||||
|
yarn vite build --mode development
|
||||||
|
yarn tauri build --debug -b
|
||||||
|
$env:KITTYCAD_API_TOKEN="<YOUR_KITTYCAD_API_TOKEN>"
|
||||||
|
$env:VITE_KC_API_BASE_URL="https://api.dev.zoo.dev"
|
||||||
|
$env:E2E_TAURI_ENABLED="true"
|
||||||
|
$env:TS_NODE_COMPILER_OPTIONS='{"module": "commonjs"}'
|
||||||
|
$env:E2E_APPLICATION=".\src-tauri\target\debug\Zoo Modeling App.exe"
|
||||||
|
Stop-Process -Name msedgedriver
|
||||||
|
yarn wdio run wdio.conf.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
## KCL
|
||||||
|
|
||||||
|
For how to contribute to KCL, [see our KCL README](https://github.com/KittyCAD/modeling-app/tree/main/src/wasm-lib/kcl).
|
||||||
|
@ -15,7 +15,7 @@ angledLine(data: AngledLineData, sketch_group: SketchGroup, tag?: String) -> Ske
|
|||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn('-XZ')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> yLineTo(15, %)
|
|> yLineTo(15, %)
|
||||||
|> angledLine({ angle: 30, length: 15 }, %)
|
|> angledLine({ angle: 30, length: 15 }, %)
|
||||||
|
323
docs/kcl/chamfer.md
Normal file
@ -23,6 +23,7 @@ layout: manual
|
|||||||
* [`atan`](kcl/atan)
|
* [`atan`](kcl/atan)
|
||||||
* [`bezierCurve`](kcl/bezierCurve)
|
* [`bezierCurve`](kcl/bezierCurve)
|
||||||
* [`ceil`](kcl/ceil)
|
* [`ceil`](kcl/ceil)
|
||||||
|
* [`chamfer`](kcl/chamfer)
|
||||||
* [`circle`](kcl/circle)
|
* [`circle`](kcl/circle)
|
||||||
* [`close`](kcl/close)
|
* [`close`](kcl/close)
|
||||||
* [`cos`](kcl/cos)
|
* [`cos`](kcl/cos)
|
||||||
@ -56,11 +57,15 @@ layout: manual
|
|||||||
* [`patternLinear3d`](kcl/patternLinear3d)
|
* [`patternLinear3d`](kcl/patternLinear3d)
|
||||||
* [`pi`](kcl/pi)
|
* [`pi`](kcl/pi)
|
||||||
* [`pow`](kcl/pow)
|
* [`pow`](kcl/pow)
|
||||||
|
* [`profileStart`](kcl/profileStart)
|
||||||
|
* [`profileStartX`](kcl/profileStartX)
|
||||||
|
* [`profileStartY`](kcl/profileStartY)
|
||||||
* [`revolve`](kcl/revolve)
|
* [`revolve`](kcl/revolve)
|
||||||
* [`segAng`](kcl/segAng)
|
* [`segAng`](kcl/segAng)
|
||||||
* [`segEndX`](kcl/segEndX)
|
* [`segEndX`](kcl/segEndX)
|
||||||
* [`segEndY`](kcl/segEndY)
|
* [`segEndY`](kcl/segEndY)
|
||||||
* [`segLen`](kcl/segLen)
|
* [`segLen`](kcl/segLen)
|
||||||
|
* [`shell`](kcl/shell)
|
||||||
* [`sin`](kcl/sin)
|
* [`sin`](kcl/sin)
|
||||||
* [`sqrt`](kcl/sqrt)
|
* [`sqrt`](kcl/sqrt)
|
||||||
* [`startProfileAt`](kcl/startProfileAt)
|
* [`startProfileAt`](kcl/startProfileAt)
|
||||||
|
@ -15,7 +15,7 @@ lastSegX(sketch_group: SketchGroup) -> number
|
|||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn("-XZ")
|
const exampleSketch = startSketchOn("XZ")
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([5, 0], %)
|
|> line([5, 0], %)
|
||||||
|> line([20, 5], %)
|
|> line([20, 5], %)
|
||||||
|
206
docs/kcl/profileStart.md
Normal file
201
docs/kcl/profileStartX.md
Normal file
200
docs/kcl/profileStartY.md
Normal file
311
docs/kcl/shell.md
Normal file
8791
docs/kcl/std.json
@ -15,7 +15,7 @@ tangentialArc(data: TangentialArcData, sketch_group: SketchGroup, tag?: String)
|
|||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn('-XZ')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> angledLine({ angle: 60, length: 10 }, %)
|
|> angledLine({ angle: 60, length: 10 }, %)
|
||||||
|> tangentialArc({ radius: 10, offset: -120 }, %)
|
|> tangentialArc({ radius: 10, offset: -120 }, %)
|
||||||
|
@ -15,7 +15,7 @@ xLine(length: number, sketch_group: SketchGroup, tag?: String) -> SketchGroup
|
|||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn('-XZ')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> xLine(15, %)
|
|> xLine(15, %)
|
||||||
|> angledLine({ angle: 80, length: 15 }, %)
|
|> angledLine({ angle: 80, length: 15 }, %)
|
||||||
|
@ -15,7 +15,7 @@ xLineTo(to: number, sketch_group: SketchGroup, tag?: String) -> SketchGroup
|
|||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn('-XZ')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> xLineTo(15, %)
|
|> xLineTo(15, %)
|
||||||
|> angledLine({ angle: 80, length: 15 }, %)
|
|> angledLine({ angle: 80, length: 15 }, %)
|
||||||
|
@ -15,7 +15,7 @@ yLine(length: number, sketch_group: SketchGroup, tag?: String) -> SketchGroup
|
|||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn('-XZ')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> yLine(15, %)
|
|> yLine(15, %)
|
||||||
|> angledLine({ angle: 30, length: 15 }, %)
|
|> angledLine({ angle: 30, length: 15 }, %)
|
||||||
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 249 KiB |
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 249 KiB |
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 249 KiB |
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 249 KiB |
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 171 KiB |
@ -1,10 +1,10 @@
|
|||||||
import { test, expect, Download } from '@playwright/test'
|
import { test, expect } from '@playwright/test'
|
||||||
import { secrets } from './secrets'
|
import { secrets } from './secrets'
|
||||||
import { getUtils } from './test-utils'
|
import { Paths, doExport, getUtils } from './test-utils'
|
||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
import fsp from 'fs/promises'
|
import fsp from 'fs/promises'
|
||||||
import { spawn } from 'child_process'
|
import { spawn } from 'child_process'
|
||||||
import { APP_NAME, KCL_DEFAULT_LENGTH } from 'lib/constants'
|
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
|
||||||
import JSZip from 'jszip'
|
import JSZip from 'jszip'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates'
|
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates'
|
||||||
@ -20,6 +20,7 @@ test.beforeEach(async ({ page }) => {
|
|||||||
localStorage.setItem('TOKEN_PERSIST_KEY', token)
|
localStorage.setItem('TOKEN_PERSIST_KEY', token)
|
||||||
localStorage.setItem('persistCode', ``)
|
localStorage.setItem('persistCode', ``)
|
||||||
localStorage.setItem(settingsKey, settings)
|
localStorage.setItem(settingsKey, settings)
|
||||||
|
localStorage.setItem('playwright', 'true')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
token: secrets.token,
|
token: secrets.token,
|
||||||
@ -44,7 +45,7 @@ test.setTimeout(60_000)
|
|||||||
test('exports of each format should work', async ({ page, context }) => {
|
test('exports of each format should work', async ({ page, context }) => {
|
||||||
// FYI this test doesn't work with only engine running locally
|
// FYI this test doesn't work with only engine running locally
|
||||||
// And you will need to have the KittyCAD CLI installed
|
// And you will need to have the KittyCAD CLI installed
|
||||||
const u = getUtils(page)
|
const u = await getUtils(page)
|
||||||
await context.addInitScript(async () => {
|
await context.addInitScript(async () => {
|
||||||
;(window as any).playwrightSkipFilePicker = true
|
;(window as any).playwrightSkipFilePicker = true
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -98,78 +99,6 @@ const part001 = startSketchOn('-XZ')
|
|||||||
await page.waitForTimeout(1000)
|
await page.waitForTimeout(1000)
|
||||||
await u.clearAndCloseDebugPanel()
|
await u.clearAndCloseDebugPanel()
|
||||||
|
|
||||||
interface Paths {
|
|
||||||
modelPath: string
|
|
||||||
imagePath: string
|
|
||||||
outputType: string
|
|
||||||
}
|
|
||||||
const doExport = async (
|
|
||||||
output: Models['OutputFormat_type']
|
|
||||||
): Promise<Paths> => {
|
|
||||||
await page.getByRole('button', { name: APP_NAME }).click()
|
|
||||||
await expect(
|
|
||||||
page.getByRole('button', { name: 'Export Part' })
|
|
||||||
).toBeVisible()
|
|
||||||
await page.getByRole('button', { name: 'Export Part' }).click()
|
|
||||||
await expect(page.getByTestId('command-bar')).toBeVisible()
|
|
||||||
|
|
||||||
// Go through export via command bar
|
|
||||||
await page.getByRole('option', { name: output.type, exact: false }).click()
|
|
||||||
await page.locator('#arg-form').waitFor({ state: 'detached' })
|
|
||||||
if ('storage' in output) {
|
|
||||||
await page.getByTestId('arg-name-storage').waitFor({ timeout: 1000 })
|
|
||||||
await page.getByRole('button', { name: 'storage', exact: false }).click()
|
|
||||||
await page
|
|
||||||
.getByRole('option', { name: output.storage, exact: false })
|
|
||||||
.click()
|
|
||||||
await page.locator('#arg-form').waitFor({ state: 'detached' })
|
|
||||||
}
|
|
||||||
await expect(page.getByText('Confirm Export')).toBeVisible()
|
|
||||||
|
|
||||||
const getPromiseAndResolve = () => {
|
|
||||||
let resolve: any = () => {}
|
|
||||||
const promise = new Promise<Download>((r) => {
|
|
||||||
resolve = r
|
|
||||||
})
|
|
||||||
return [promise, resolve]
|
|
||||||
}
|
|
||||||
|
|
||||||
const [downloadPromise1, downloadResolve1] = getPromiseAndResolve()
|
|
||||||
let downloadCnt = 0
|
|
||||||
|
|
||||||
page.on('download', async (download) => {
|
|
||||||
if (downloadCnt === 0) {
|
|
||||||
downloadResolve1(download)
|
|
||||||
}
|
|
||||||
downloadCnt++
|
|
||||||
})
|
|
||||||
await page.getByRole('button', { name: 'Submit command' }).click()
|
|
||||||
|
|
||||||
// Handle download
|
|
||||||
const download = await downloadPromise1
|
|
||||||
const downloadLocationer = (extra = '', isImage = false) =>
|
|
||||||
`./e2e/playwright/export-snapshots/${output.type}-${
|
|
||||||
'storage' in output ? output.storage : ''
|
|
||||||
}${extra}.${isImage ? 'png' : output.type}`
|
|
||||||
const downloadLocation = downloadLocationer()
|
|
||||||
|
|
||||||
await download.saveAs(downloadLocation)
|
|
||||||
|
|
||||||
if (output.type === 'step') {
|
|
||||||
// stable timestamps for step files
|
|
||||||
const fileContents = await fsp.readFile(downloadLocation, 'utf-8')
|
|
||||||
const newFileContents = fileContents.replace(
|
|
||||||
/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]+[0-9]+[0-9]\+[0-9]{2}:[0-9]{2}/g,
|
|
||||||
'1970-01-01T00:00:00.0+00:00'
|
|
||||||
)
|
|
||||||
await fsp.writeFile(downloadLocation, newFileContents)
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
modelPath: downloadLocation,
|
|
||||||
imagePath: downloadLocationer('', true),
|
|
||||||
outputType: output.type,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const axisDirectionPair: Models['AxisDirectionPair_type'] = {
|
const axisDirectionPair: Models['AxisDirectionPair_type'] = {
|
||||||
axis: 'z',
|
axis: 'z',
|
||||||
direction: 'positive',
|
direction: 'positive',
|
||||||
@ -185,84 +114,114 @@ const part001 = startSketchOn('-XZ')
|
|||||||
// just note that only `type` and `storage` are used for selecting the drop downs is the app
|
// just note that only `type` and `storage` are used for selecting the drop downs is the app
|
||||||
// the rest are only there to make typescript happy
|
// the rest are only there to make typescript happy
|
||||||
exportLocations.push(
|
exportLocations.push(
|
||||||
await doExport({
|
await doExport(
|
||||||
|
{
|
||||||
type: 'step',
|
type: 'step',
|
||||||
coords: sysType,
|
coords: sysType,
|
||||||
})
|
},
|
||||||
|
page
|
||||||
|
)
|
||||||
)
|
)
|
||||||
exportLocations.push(
|
exportLocations.push(
|
||||||
await doExport({
|
await doExport(
|
||||||
|
{
|
||||||
type: 'ply',
|
type: 'ply',
|
||||||
coords: sysType,
|
coords: sysType,
|
||||||
selection: { type: 'default_scene' },
|
selection: { type: 'default_scene' },
|
||||||
storage: 'ascii',
|
storage: 'ascii',
|
||||||
units: 'in',
|
units: 'in',
|
||||||
})
|
},
|
||||||
|
page
|
||||||
|
)
|
||||||
)
|
)
|
||||||
exportLocations.push(
|
exportLocations.push(
|
||||||
await doExport({
|
await doExport(
|
||||||
|
{
|
||||||
type: 'ply',
|
type: 'ply',
|
||||||
storage: 'binary_little_endian',
|
storage: 'binary_little_endian',
|
||||||
coords: sysType,
|
coords: sysType,
|
||||||
selection: { type: 'default_scene' },
|
selection: { type: 'default_scene' },
|
||||||
units: 'in',
|
units: 'in',
|
||||||
})
|
},
|
||||||
|
page
|
||||||
|
)
|
||||||
)
|
)
|
||||||
exportLocations.push(
|
exportLocations.push(
|
||||||
await doExport({
|
await doExport(
|
||||||
|
{
|
||||||
type: 'ply',
|
type: 'ply',
|
||||||
storage: 'binary_big_endian',
|
storage: 'binary_big_endian',
|
||||||
coords: sysType,
|
coords: sysType,
|
||||||
selection: { type: 'default_scene' },
|
selection: { type: 'default_scene' },
|
||||||
units: 'in',
|
units: 'in',
|
||||||
})
|
},
|
||||||
|
page
|
||||||
|
)
|
||||||
)
|
)
|
||||||
exportLocations.push(
|
exportLocations.push(
|
||||||
await doExport({
|
await doExport(
|
||||||
|
{
|
||||||
type: 'stl',
|
type: 'stl',
|
||||||
storage: 'ascii',
|
storage: 'ascii',
|
||||||
coords: sysType,
|
coords: sysType,
|
||||||
units: 'in',
|
units: 'in',
|
||||||
selection: { type: 'default_scene' },
|
selection: { type: 'default_scene' },
|
||||||
})
|
},
|
||||||
|
page
|
||||||
|
)
|
||||||
)
|
)
|
||||||
exportLocations.push(
|
exportLocations.push(
|
||||||
await doExport({
|
await doExport(
|
||||||
|
{
|
||||||
type: 'stl',
|
type: 'stl',
|
||||||
storage: 'binary',
|
storage: 'binary',
|
||||||
coords: sysType,
|
coords: sysType,
|
||||||
units: 'in',
|
units: 'in',
|
||||||
selection: { type: 'default_scene' },
|
selection: { type: 'default_scene' },
|
||||||
})
|
},
|
||||||
|
page
|
||||||
|
)
|
||||||
)
|
)
|
||||||
exportLocations.push(
|
exportLocations.push(
|
||||||
await doExport({
|
await doExport(
|
||||||
|
{
|
||||||
// obj seems to be a little flaky, times out tests sometimes
|
// obj seems to be a little flaky, times out tests sometimes
|
||||||
type: 'obj',
|
type: 'obj',
|
||||||
coords: sysType,
|
coords: sysType,
|
||||||
units: 'in',
|
units: 'in',
|
||||||
})
|
},
|
||||||
|
page
|
||||||
|
)
|
||||||
)
|
)
|
||||||
exportLocations.push(
|
exportLocations.push(
|
||||||
await doExport({
|
await doExport(
|
||||||
|
{
|
||||||
type: 'gltf',
|
type: 'gltf',
|
||||||
storage: 'embedded',
|
storage: 'embedded',
|
||||||
presentation: 'pretty',
|
presentation: 'pretty',
|
||||||
})
|
},
|
||||||
|
page
|
||||||
|
)
|
||||||
)
|
)
|
||||||
exportLocations.push(
|
exportLocations.push(
|
||||||
await doExport({
|
await doExport(
|
||||||
|
{
|
||||||
type: 'gltf',
|
type: 'gltf',
|
||||||
storage: 'binary',
|
storage: 'binary',
|
||||||
presentation: 'pretty',
|
presentation: 'pretty',
|
||||||
})
|
},
|
||||||
|
page
|
||||||
|
)
|
||||||
)
|
)
|
||||||
exportLocations.push(
|
exportLocations.push(
|
||||||
await doExport({
|
await doExport(
|
||||||
|
{
|
||||||
type: 'gltf',
|
type: 'gltf',
|
||||||
storage: 'standard',
|
storage: 'standard',
|
||||||
presentation: 'pretty',
|
presentation: 'pretty',
|
||||||
})
|
},
|
||||||
|
page
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// close page to disconnect websocket since we can only have one open atm
|
// close page to disconnect websocket since we can only have one open atm
|
||||||
@ -273,6 +232,8 @@ const part001 = startSketchOn('-XZ')
|
|||||||
for (let { modelPath, imagePath, outputType } of exportLocations) {
|
for (let { modelPath, imagePath, outputType } of exportLocations) {
|
||||||
// May change depending on the file being dealt with
|
// May change depending on the file being dealt with
|
||||||
let cliCommand = `export ZOO_TOKEN=${secrets.snapshottoken} && zoo file snapshot --output-format=png --src-format=${outputType} ${modelPath} ${imagePath}`
|
let cliCommand = `export ZOO_TOKEN=${secrets.snapshottoken} && zoo file snapshot --output-format=png --src-format=${outputType} ${modelPath} ${imagePath}`
|
||||||
|
const fileSize = (await fsp.stat(modelPath)).size
|
||||||
|
console.log(`Size of the file at ${modelPath}: ${fileSize} bytes`)
|
||||||
|
|
||||||
const parentPath = path.dirname(modelPath)
|
const parentPath = path.dirname(modelPath)
|
||||||
|
|
||||||
@ -367,7 +328,7 @@ const extrudeDefaultPlane = async (context: any, page: any, plane: string) => {
|
|||||||
localStorage.setItem('persistCode', code)
|
localStorage.setItem('persistCode', code)
|
||||||
})
|
})
|
||||||
|
|
||||||
const u = getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
@ -422,7 +383,7 @@ test.describe('extrude on default planes should be stable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('Draft segments should look right', async ({ page, context }) => {
|
test('Draft segments should look right', async ({ page, context }) => {
|
||||||
const u = getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
@ -444,17 +405,16 @@ test('Draft segments should look right', async ({ page, context }) => {
|
|||||||
// select a plane
|
// select a plane
|
||||||
await page.mouse.click(700, 200)
|
await page.mouse.click(700, 200)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content')).toHaveText(
|
let code = `const sketch001 = startSketchOn('XZ')`
|
||||||
`const part001 = startSketchOn('-XZ')`
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
||||||
)
|
|
||||||
|
|
||||||
await page.waitForTimeout(300) // TODO detect animation ending, or disable animation
|
await page.waitForTimeout(700) // TODO detect animation ending, or disable animation
|
||||||
|
|
||||||
const startXPx = 600
|
const startXPx = 600
|
||||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||||
await expect(page.locator('.cm-content'))
|
code += `
|
||||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
|> startProfileAt([7.19, -9.7], %)`
|
||||||
|> startProfileAt([9.06, -12.22], %)`)
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
@ -466,10 +426,9 @@ test('Draft segments should look right', async ({ page, context }) => {
|
|||||||
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
code += `
|
||||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
|> line([7.25, 0], %)`
|
||||||
|> startProfileAt([9.06, -12.22], %)
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
||||||
|> line([9.14, 0], %)`)
|
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
||||||
|
|
||||||
@ -481,7 +440,7 @@ test('Draft segments should look right', async ({ page, context }) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('Draft rectangles should look right', async ({ page, context }) => {
|
test('Draft rectangles should look right', async ({ page, context }) => {
|
||||||
const u = getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
@ -504,7 +463,7 @@ test('Draft rectangles should look right', async ({ page, context }) => {
|
|||||||
await page.mouse.click(700, 200)
|
await page.mouse.click(700, 200)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content')).toHaveText(
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
`const part001 = startSketchOn('-XZ')`
|
`const sketch001 = startSketchOn('XZ')`
|
||||||
)
|
)
|
||||||
|
|
||||||
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
|
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
|
||||||
@ -528,7 +487,7 @@ test('Draft rectangles should look right', async ({ page, context }) => {
|
|||||||
|
|
||||||
test.describe('Client side scene scale should match engine scale', () => {
|
test.describe('Client side scene scale should match engine scale', () => {
|
||||||
test('Inch scale', async ({ page }) => {
|
test('Inch scale', async ({ page }) => {
|
||||||
const u = getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
@ -552,17 +511,16 @@ test.describe('Client side scene scale should match engine scale', () => {
|
|||||||
// select a plane
|
// select a plane
|
||||||
await page.mouse.click(700, 200)
|
await page.mouse.click(700, 200)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content')).toHaveText(
|
let code = `const sketch001 = startSketchOn('XZ')`
|
||||||
`const part001 = startSketchOn('-XZ')`
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
||||||
)
|
|
||||||
|
|
||||||
await page.waitForTimeout(300) // TODO detect animation ending, or disable animation
|
await page.waitForTimeout(600) // TODO detect animation ending, or disable animation
|
||||||
|
|
||||||
const startXPx = 600
|
const startXPx = 600
|
||||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||||
await expect(page.locator('.cm-content'))
|
code += `
|
||||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
|> startProfileAt([7.19, -9.7], %)`
|
||||||
|> startProfileAt([9.06, -12.22], %)`)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
@ -570,21 +528,18 @@ test.describe('Client side scene scale should match engine scale', () => {
|
|||||||
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
code += `
|
||||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
|> line([7.25, 0], %)`
|
||||||
|> startProfileAt([9.06, -12.22], %)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
|> line([9.14, 0], %)`)
|
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
code += `
|
||||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
|> tangentialArcTo([21.7, -2.44], %)`
|
||||||
|> startProfileAt([9.06, -12.22], %)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
|> line([9.14, 0], %)
|
|
||||||
|> tangentialArcTo([27.34, -3.08], %)`)
|
|
||||||
|
|
||||||
// click tangential arc tool again to unequip it
|
// click tangential arc tool again to unequip it
|
||||||
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
||||||
@ -631,7 +586,7 @@ test.describe('Client side scene scale should match engine scale', () => {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
const u = getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
await page.goto('/')
|
await page.goto('/')
|
||||||
@ -655,17 +610,16 @@ test.describe('Client side scene scale should match engine scale', () => {
|
|||||||
// select a plane
|
// select a plane
|
||||||
await page.mouse.click(700, 200)
|
await page.mouse.click(700, 200)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content')).toHaveText(
|
let code = `const sketch001 = startSketchOn('XZ')`
|
||||||
`const part001 = startSketchOn('-XZ')`
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
)
|
|
||||||
|
|
||||||
await page.waitForTimeout(300) // TODO detect animation ending, or disable animation
|
await page.waitForTimeout(600) // TODO detect animation ending, or disable animation
|
||||||
|
|
||||||
const startXPx = 600
|
const startXPx = 600
|
||||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||||
await expect(page.locator('.cm-content'))
|
code += `
|
||||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
|> startProfileAt([182.59, -246.32], %)`
|
||||||
|> startProfileAt([230.03, -310.32], %)`)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
@ -673,21 +627,18 @@ test.describe('Client side scene scale should match engine scale', () => {
|
|||||||
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
code += `
|
||||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
|> line([184.3, 0], %)`
|
||||||
|> startProfileAt([230.03, -310.32], %)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
|> line([232.2, 0], %)`)
|
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
code += `
|
||||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
|> tangentialArcTo([551.2, -62.01], %)`
|
||||||
|> startProfileAt([230.03, -310.32], %)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
|> line([232.2, 0], %)
|
|
||||||
|> tangentialArcTo([694.43, -78.12], %)`)
|
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
@ -717,7 +668,7 @@ test.describe('Client side scene scale should match engine scale', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('Sketch on face with none z-up', async ({ page, context }) => {
|
test('Sketch on face with none z-up', async ({ page, context }) => {
|
||||||
const u = getUtils(page)
|
const u = await getUtils(page)
|
||||||
await context.addInitScript(async (KCL_DEFAULT_LENGTH) => {
|
await context.addInitScript(async (KCL_DEFAULT_LENGTH) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -771,3 +722,76 @@ const part002 = startSketchOn(part001, 'seg01')
|
|||||||
maxDiffPixels: 100,
|
maxDiffPixels: 100,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Zoom to fit on load - solid 2d', async ({ page, context }) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await context.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`const part001 = startSketchOn('XY')
|
||||||
|
|> startProfileAt([-10, -10], %)
|
||||||
|
|> line([20, 0], %)
|
||||||
|
|> line([0, 20], %)
|
||||||
|
|> line([-20, 0], %)
|
||||||
|
|> close(%)
|
||||||
|
`
|
||||||
|
)
|
||||||
|
}, KCL_DEFAULT_LENGTH)
|
||||||
|
|
||||||
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
await page.goto('/')
|
||||||
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
|
await u.openDebugPanel()
|
||||||
|
// wait for execution done
|
||||||
|
await expect(
|
||||||
|
page.locator('[data-message-type="execution-done"]')
|
||||||
|
).toHaveCount(2)
|
||||||
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
|
// Wait for the second extrusion to appear
|
||||||
|
// TODO: Find a way to truly know that the objects have finished
|
||||||
|
// rendering, because an execution-done message is not sufficient.
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
|
|
||||||
|
await expect(page).toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Zoom to fit on load - solid 3d', async ({ page, context }) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await context.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`const part001 = startSketchOn('XY')
|
||||||
|
|> startProfileAt([-10, -10], %)
|
||||||
|
|> line([20, 0], %)
|
||||||
|
|> line([0, 20], %)
|
||||||
|
|> line([-20, 0], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(10, %)
|
||||||
|
`
|
||||||
|
)
|
||||||
|
}, KCL_DEFAULT_LENGTH)
|
||||||
|
|
||||||
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
await page.goto('/')
|
||||||
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
|
await u.openDebugPanel()
|
||||||
|
// wait for execution done
|
||||||
|
await expect(
|
||||||
|
page.locator('[data-message-type="execution-done"]')
|
||||||
|
).toHaveCount(2)
|
||||||
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
|
// Wait for the second extrusion to appear
|
||||||
|
// TODO: Find a way to truly know that the objects have finished
|
||||||
|
// rendering, because an execution-done message is not sufficient.
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
|
|
||||||
|
await expect(page).toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 36 KiB |