Compare commits
168 Commits
remove-ext
...
nicboone8-
Author | SHA1 | Date | |
---|---|---|---|
a831dcefb4 | |||
bc6a8ccb78 | |||
4390788f17 | |||
2ddd546123 | |||
fd3125e641 | |||
402de8c926 | |||
75dff9f775 | |||
5f6d810fbb | |||
55e1ec7dad | |||
b123dacc41 | |||
5911df46ee | |||
ec19b9bfaa | |||
962609e3d3 | |||
87e3588ceb | |||
c4d2e33a99 | |||
2ac05508bc | |||
5c6d4fbf5a | |||
aaff027830 | |||
355a450c09 | |||
21f4fcb041 | |||
37aea72a88 | |||
783b6ed76c | |||
9dfb67cf61 | |||
889c72ec60 | |||
067e193780 | |||
77730196ae | |||
dba0173cc3 | |||
8f4327ab6b | |||
cc2769e907 | |||
91b6db0ba5 | |||
8bae76000c | |||
f502e445cc | |||
083bfe6ec2 | |||
2c1a5ff5c4 | |||
0c2785df67 | |||
fa9d5a0104 | |||
678433d2b3 | |||
30bd307931 | |||
08dfaba7f7 | |||
eb2327827b | |||
1f53dd1357 | |||
034366e65e | |||
cd537cd9c2 | |||
22f92942f6 | |||
4eee50d79e | |||
125b2c44d4 | |||
db9e35d686 | |||
d0958220fe | |||
fa4b3cfd1b | |||
8972f8f109 | |||
85ccc6900c | |||
4e2deca5d8 | |||
04a2c184d7 | |||
2c7701e2d4 | |||
ae569b61db | |||
0a0e6abd3f | |||
9c7aee32bd | |||
ed979d807b | |||
f5c244dbb1 | |||
0ea1e9a6da | |||
a36530d6df | |||
825d34718a | |||
d90d445d84 | |||
5976a0cba6 | |||
b50f2f5a2a | |||
f877b52898 | |||
4a585db637 | |||
4d404bf137 | |||
e644b7e1fc | |||
aff1684064 | |||
d9afc50f91 | |||
eb7b4ccda6 | |||
bbf4f1d251 | |||
3cc7859ca5 | |||
ab63345c57 | |||
3df02e02fa | |||
35f5c62633 | |||
0f0fc39d07 | |||
a13b6b2b70 | |||
4212b95232 | |||
38a73a603b | |||
c48d9fd4d7 | |||
0753987b5a | |||
815ff7dc2b | |||
46684d420d | |||
eca09984a3 | |||
ce63c6423e | |||
09699afe82 | |||
36c8ad439d | |||
5dc77ceed5 | |||
c7baa26b2d | |||
4d0454abcd | |||
1dafbf105e | |||
773f013115 | |||
c5cd460595 | |||
845352046b | |||
597f1087f9 | |||
511334683a | |||
223a4ad45d | |||
edf31ec1d3 | |||
1539557005 | |||
1d3ba4e3ac | |||
4110aa00db | |||
7eb52cda36 | |||
7872fb9cbd | |||
651181e62c | |||
38a245f2fc | |||
1b4289f93f | |||
d0697c24fd | |||
8c24e29081 | |||
2b9d26e2ff | |||
ab148a7654 | |||
553e650fbe | |||
9690a24c68 | |||
978d5d44a2 | |||
9df476543a | |||
cf303ebe97 | |||
b1d1d89ca5 | |||
3a599d0a0a | |||
8340f6b906 | |||
ddb034b14d | |||
bfa2f67393 | |||
447069a97b | |||
49b78d726a | |||
5b4cddd0b0 | |||
8878c148ed | |||
c3c2ded795 | |||
fb35fdcc38 | |||
e76ba9921c | |||
b19acd550d | |||
f3e9d110c0 | |||
658497da1d | |||
bd01059a92 | |||
57a977e6be | |||
94b0cc1f3e | |||
5734cc7fc3 | |||
3168c22de7 | |||
3c94fe9047 | |||
cdd6b56d42 | |||
75ac3bc61b | |||
29d511d085 | |||
b0a41939e8 | |||
7d2c1061ba | |||
d768073d17 | |||
dc8496c62e | |||
416de9a9fb | |||
da65426ddc | |||
585b485852 | |||
e85f16ff9c | |||
e7d2289a14 | |||
d35531758d | |||
729e0a7949 | |||
620b7401aa | |||
e3e67b00d5 | |||
49d4f8e5c3 | |||
47b159c605 | |||
c7b086fa69 | |||
203db79204 | |||
48a4fd8373 | |||
17eb84325f | |||
ebf048478d | |||
28a8cd2421 | |||
1506de92f5 | |||
8a03413643 | |||
f59b806a88 | |||
23a0085c78 | |||
a280a8c3f0 | |||
11620dfa6b |
12
.github/ci-cd-scripts/playwright-electron.sh
vendored
@ -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" -- npm run test:playwright:electron -- --shard=$1/$2 || true
|
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:e2e:desktop -- --shard=$1/$2 || true
|
||||||
elif [[ "$3" == *windows* ]]; then
|
elif [[ "$3" == *windows* ]]; then
|
||||||
npm run test:playwright:electron -- --grep=@windows --shard=$1/$2 || true
|
npm run test:e2e:desktop -- --grep=@windows --shard=$1/$2 || true
|
||||||
elif [[ "$3" == *macos* ]]; then
|
elif [[ "$3" == *macos* ]]; then
|
||||||
npm run test:playwright:electron -- --grep=@macos --shard=$1/$2 || true
|
npm run test:e2e:desktop -- --grep=@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" -- npm run test:playwright:electron -- --last-failed || true
|
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:e2e:desktop -- --last-failed || true
|
||||||
elif [[ "$3" == *windows* ]]; then
|
elif [[ "$3" == *windows* ]]; then
|
||||||
npm run test:playwright:electron -- --grep=@windows --last-failed || true
|
npm run test:e2e:desktop -- --grep=@windows --last-failed || true
|
||||||
elif [[ "$3" == *macos* ]]; then
|
elif [[ "$3" == *macos* ]]; then
|
||||||
npm run test:playwright:electron -- --grep=@macos --last-failed || true
|
npm run test:e2e:desktop -- --grep=@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
|
||||||
|
2
.github/ci-cd-scripts/upload-results.sh
vendored
@ -6,6 +6,7 @@ if [ -z "${TAB_API_URL:-}" ] || [ -z "${TAB_API_KEY:-}" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
project="https://github.com/KittyCAD/modeling-app"
|
project="https://github.com/KittyCAD/modeling-app"
|
||||||
|
suite="${CI_SUITE:-unit}"
|
||||||
branch="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-}}"
|
branch="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-}}"
|
||||||
commit="${CI_COMMIT_SHA:-${GITHUB_SHA:-}}"
|
commit="${CI_COMMIT_SHA:-${GITHUB_SHA:-}}"
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ echo "Uploading batch results"
|
|||||||
curl --silent --request POST \
|
curl --silent --request POST \
|
||||||
--header "X-API-Key: ${TAB_API_KEY}" \
|
--header "X-API-Key: ${TAB_API_KEY}" \
|
||||||
--form "project=${project}" \
|
--form "project=${project}" \
|
||||||
|
--form "suite=${suite}" \
|
||||||
--form "branch=${branch}" \
|
--form "branch=${branch}" \
|
||||||
--form "commit=${commit}" \
|
--form "commit=${commit}" \
|
||||||
--form "tests=@test-results/junit.xml" \
|
--form "tests=@test-results/junit.xml" \
|
||||||
|
56
.github/workflows/build-wasm.yml
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
name: Build WASM
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
npm-build-wasm:
|
||||||
|
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Use correct Rust toolchain
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||||
|
|
||||||
|
- name: Install rust
|
||||||
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
cache: false # configured below
|
||||||
|
|
||||||
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
|
with:
|
||||||
|
tool: wasm-pack
|
||||||
|
|
||||||
|
- name: Use Rust cache
|
||||||
|
uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
workspaces: './rust'
|
||||||
|
|
||||||
|
- name: Build Wasm
|
||||||
|
shell: bash
|
||||||
|
run: npm run build:wasm
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: prepared-wasm
|
||||||
|
path: |
|
||||||
|
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: prepared-ts-rs-bindings
|
||||||
|
path: |
|
||||||
|
rust/kcl-lib/bindings/*
|
63
.github/workflows/cargo-test.yml
vendored
@ -1,16 +1,22 @@
|
|||||||
|
name: cargo test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: 0 * * * * # hourly
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
|
||||||
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
|
||||||
name: cargo test
|
|
||||||
jobs:
|
jobs:
|
||||||
build-test-artifacts:
|
build-test-artifacts:
|
||||||
name: Build test artifacts
|
name: Build test artifacts
|
||||||
@ -88,6 +94,7 @@ jobs:
|
|||||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
||||||
ZOO_HOST: https://api.dev.zoo.dev
|
ZOO_HOST: https://api.dev.zoo.dev
|
||||||
RUST_BACKTRACE: full
|
RUST_BACKTRACE: full
|
||||||
|
RUST_MIN_STACK: 10485760000
|
||||||
- name: Commit differences
|
- name: Commit differences
|
||||||
if: steps.path-changes.outputs.outside-kcl-samples == 'false' && steps.cargo-test-kcl-samples.outcome == 'failure'
|
if: steps.path-changes.outputs.outside-kcl-samples == 'false' && steps.cargo-test-kcl-samples.outcome == 'failure'
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -119,6 +126,7 @@ jobs:
|
|||||||
# Configure nextest when it's run by insta (via just).
|
# Configure nextest when it's run by insta (via just).
|
||||||
NEXTEST_PROFILE: ci
|
NEXTEST_PROFILE: ci
|
||||||
RUST_BACKTRACE: full
|
RUST_BACKTRACE: full
|
||||||
|
RUST_MIN_STACK: 10485760000
|
||||||
- name: Build and archive tests
|
- name: Build and archive tests
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
@ -155,7 +163,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||||
- name: Install rust
|
- name: Install Rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: false # Configured below.
|
cache: false # Configured below.
|
||||||
@ -182,6 +190,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
||||||
ZOO_HOST: https://api.dev.zoo.dev
|
ZOO_HOST: https://api.dev.zoo.dev
|
||||||
|
RUST_MIN_STACK: 10485760000
|
||||||
- name: Upload results
|
- name: Upload results
|
||||||
if: always()
|
if: always()
|
||||||
run: .github/ci-cd-scripts/upload-results.sh
|
run: .github/ci-cd-scripts/upload-results.sh
|
||||||
@ -190,6 +199,56 @@ jobs:
|
|||||||
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
||||||
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
CI_SUITE: e2e:kcl
|
||||||
|
run-internal-kcl-samples:
|
||||||
|
name: cargo test (internal-kcl-samples)
|
||||||
|
runs-on:
|
||||||
|
- runs-on=${{ github.run_id }}
|
||||||
|
- runner=32cpu-linux-x64
|
||||||
|
- extras=s3-cache
|
||||||
|
steps:
|
||||||
|
- uses: runs-on/action@v1
|
||||||
|
- uses: actions/create-github-app-token@v1
|
||||||
|
id: app-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||||
|
private-key: ${{ secrets.MODELING_APP_GH_APP_PRIVATE_KEY }}
|
||||||
|
owner: ${{ github.repository_owner }}
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ steps.app-token.outputs.token }}
|
||||||
|
- name: Use correct Rust toolchain
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||||
|
- name: Install Rust
|
||||||
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
cache: false # Configured below.
|
||||||
|
- name: Start Vector
|
||||||
|
run: .github/ci-cd-scripts/start-vector-ubuntu.sh
|
||||||
|
env:
|
||||||
|
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
||||||
|
OS_NAME: ${{ env.OS_NAME }}
|
||||||
|
- uses: taiki-e/install-action@nextest
|
||||||
|
- name: Download internal KCL samples
|
||||||
|
run: git clone --depth=1 https://x-access-token:${{ secrets.GH_PAT_KCL_SAMPLES_INTERNAL }}@github.com/KittyCAD/kcl-samples-internal public/kcl-samples/internal
|
||||||
|
- name: Run tests
|
||||||
|
shell: bash
|
||||||
|
run: |-
|
||||||
|
cd rust/kcl-lib
|
||||||
|
cargo nextest run \
|
||||||
|
--retries=10 --no-fail-fast --features artifact-graph --profile=ci \
|
||||||
|
internal \
|
||||||
|
2>&1 | tee /tmp/github-actions.log
|
||||||
|
env:
|
||||||
|
TWENTY_TWENTY: overwrite
|
||||||
|
INSTA_UPDATE: always
|
||||||
|
EXPECTORATE: overwrite
|
||||||
|
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
||||||
|
ZOO_HOST: https://api.dev.zoo.dev
|
||||||
|
MODELING_APP_INTERNAL_SAMPLES_SECRET: ${{secrets.MODELING_APP_INTERNAL_SAMPLES_SECRET}}
|
||||||
|
RUST_MIN_STACK: 10485760000
|
||||||
run-wasm-tests:
|
run-wasm-tests:
|
||||||
name: Run wasm tests
|
name: Run wasm tests
|
||||||
strategy:
|
strategy:
|
||||||
|
136
.github/workflows/e2e-tests.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
name: E2E Tests
|
name: E2E Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@ -19,9 +20,11 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
prepare-wasm:
|
prepare-wasm:
|
||||||
|
|
||||||
# separate job on Ubuntu to build or fetch the wasm blob once on the fastest runner
|
# separate job on Ubuntu to build or fetch 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:
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- id: filter
|
- id: filter
|
||||||
@ -99,10 +102,13 @@ jobs:
|
|||||||
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
|
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
|
||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
name: playwright:snapshots:ubuntu
|
|
||||||
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
|
||||||
needs: [prepare-wasm]
|
needs: [prepare-wasm]
|
||||||
|
|
||||||
|
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||||
|
name: e2e:snapshots
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/create-github-app-token@v1
|
- uses: actions/create-github-app-token@v1
|
||||||
id: app-token
|
id: app-token
|
||||||
with:
|
with:
|
||||||
@ -130,10 +136,9 @@ jobs:
|
|||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
id: deps-install
|
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: Cache browsers
|
- name: Download browser cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@ -143,7 +148,7 @@ jobs:
|
|||||||
- name: Install browsers
|
- name: Install browsers
|
||||||
run: npm run playwright install --with-deps
|
run: npm run playwright install --with-deps
|
||||||
|
|
||||||
- name: Capture snapshots
|
- name: npm run test:snapshots
|
||||||
uses: nick-fields/retry@v3.0.2
|
uses: nick-fields/retry@v3.0.2
|
||||||
with:
|
with:
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -156,6 +161,19 @@ jobs:
|
|||||||
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
||||||
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
CI_SUITE: e2e:snapshots
|
||||||
|
TARGET: web
|
||||||
|
|
||||||
|
- name: Update snapshots
|
||||||
|
if: always()
|
||||||
|
run: npm run test:snapshots -- --last-failed --update-snapshots
|
||||||
|
env:
|
||||||
|
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
TAB_API_URL: ${{ secrets.TAB_API_URL }}
|
||||||
|
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
||||||
|
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
|
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
CI_SUITE: e2e:snapshots
|
||||||
TARGET: web
|
TARGET: web
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
@ -173,7 +191,7 @@ jobs:
|
|||||||
id: git-check
|
id: git-check
|
||||||
run: |
|
run: |
|
||||||
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
||||||
if git status | grep -q "Changes to be committed"
|
if git status | grep --quiet "Changes to be committed"
|
||||||
then echo "modified=true" >> $GITHUB_OUTPUT
|
then echo "modified=true" >> $GITHUB_OUTPUT
|
||||||
else echo "modified=false" >> $GITHUB_OUTPUT
|
else echo "modified=false" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
@ -193,12 +211,93 @@ jobs:
|
|||||||
git push
|
git push
|
||||||
git push origin ${{ github.head_ref }}
|
git push origin ${{ github.head_ref }}
|
||||||
|
|
||||||
electron:
|
web:
|
||||||
needs: [prepare-wasm]
|
needs: [prepare-wasm]
|
||||||
timeout-minutes: 60
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
name: e2e:web (${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }})
|
||||||
env:
|
env:
|
||||||
OS_NAME: ${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}
|
OS_NAME: ${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}
|
||||||
name: playwright:electron:${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }} (shard ${{ matrix.shardIndex }})
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- uses: actions/create-github-app-token@v1
|
||||||
|
id: app-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||||
|
private-key: ${{ secrets.MODELING_APP_GH_APP_PRIVATE_KEY }}
|
||||||
|
owner: ${{ github.repository_owner }}
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ steps.app-token.outputs.token }}
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
name: prepared-wasm
|
||||||
|
|
||||||
|
- name: Copy prepared Wasm
|
||||||
|
run: |
|
||||||
|
ls -R prepared-wasm
|
||||||
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
|
mkdir rust/kcl-wasm-lib/pkg
|
||||||
|
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Download browser cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cache/ms-playwright/
|
||||||
|
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
|
||||||
|
|
||||||
|
- name: Install browsers
|
||||||
|
run: npm run playwright install --with-deps
|
||||||
|
|
||||||
|
- name: Start Vector
|
||||||
|
if: ${{ !contains(matrix.os, 'windows') }}
|
||||||
|
run: .github/ci-cd-scripts/start-vector-${{ env.OS_NAME }}.sh
|
||||||
|
env:
|
||||||
|
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
||||||
|
OS_NAME: ${{ env.OS_NAME }}
|
||||||
|
|
||||||
|
- name: npm run test:e2e:web
|
||||||
|
uses: nick-fields/retry@v3.0.2
|
||||||
|
with:
|
||||||
|
shell: bash
|
||||||
|
command: npm run test:e2e:web
|
||||||
|
timeout_minutes: 5
|
||||||
|
max_attempts: 5
|
||||||
|
env:
|
||||||
|
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
TAB_API_URL: ${{ secrets.TAB_API_URL }}
|
||||||
|
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
||||||
|
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
|
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
CI_SUITE: e2e:web
|
||||||
|
TARGET: web
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
if: ${{ !cancelled() && (success() || failure()) }}
|
||||||
|
with:
|
||||||
|
path: playwright-report/
|
||||||
|
include-hidden-files: true
|
||||||
|
retention-days: 30
|
||||||
|
overwrite: true
|
||||||
|
|
||||||
|
desktop:
|
||||||
|
needs: [prepare-wasm]
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@ -241,13 +340,17 @@ jobs:
|
|||||||
shardIndex: 2
|
shardIndex: 2
|
||||||
shardTotal: 2
|
shardTotal: 2
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
name: e2e:desktop (${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}, shard ${{ matrix.shardIndex }})
|
||||||
|
env:
|
||||||
|
OS_NAME: ${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
name: prepared-wasm
|
name: prepared-wasm
|
||||||
|
|
||||||
- name: Copy prepared wasm
|
- name: Copy prepared Wasm
|
||||||
run: |
|
run: |
|
||||||
ls -R prepared-wasm
|
ls -R prepared-wasm
|
||||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
@ -263,19 +366,16 @@ jobs:
|
|||||||
id: deps-install
|
id: deps-install
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: Cache Playwright Browsers
|
- name: Download browser cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/ms-playwright/
|
~/.cache/ms-playwright/
|
||||||
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
|
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install browsers
|
||||||
run: npm run playwright install --with-deps
|
run: npm run playwright install --with-deps
|
||||||
|
|
||||||
- name: Build web
|
|
||||||
run: npm run tronb:vite:dev
|
|
||||||
|
|
||||||
- name: Start Vector
|
- name: Start Vector
|
||||||
if: ${{ !contains(matrix.os, 'windows') }}
|
if: ${{ !contains(matrix.os, 'windows') }}
|
||||||
run: .github/ci-cd-scripts/start-vector-${{ env.OS_NAME }}.sh
|
run: .github/ci-cd-scripts/start-vector-${{ env.OS_NAME }}.sh
|
||||||
@ -283,6 +383,9 @@ jobs:
|
|||||||
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
||||||
OS_NAME: ${{ env.OS_NAME }}
|
OS_NAME: ${{ env.OS_NAME }}
|
||||||
|
|
||||||
|
- name: Build app
|
||||||
|
run: npm run tronb:vite:dev
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
if: ${{ !cancelled() && (success() || failure()) }}
|
if: ${{ !cancelled() && (success() || failure()) }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@ -290,7 +393,7 @@ jobs:
|
|||||||
name: test-results-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
name: test-results-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||||
path: test-results/
|
path: test-results/
|
||||||
|
|
||||||
- name: Run playwright/electron flow (with retries)
|
- name: npm run test:e2e:desktop
|
||||||
id: retry
|
id: retry
|
||||||
if: ${{ !cancelled() && steps.deps-install.outcome == 'success' }}
|
if: ${{ !cancelled() && steps.deps-install.outcome == 'success' }}
|
||||||
uses: nick-fields/retry@v3.0.2
|
uses: nick-fields/retry@v3.0.2
|
||||||
@ -306,6 +409,7 @@ jobs:
|
|||||||
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
||||||
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
CI_SUITE: e2e:desktop
|
||||||
TARGET: desktop
|
TARGET: desktop
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
|
61
.github/workflows/kcl-language-server.yml
vendored
@ -21,14 +21,11 @@ on:
|
|||||||
- '**.rs'
|
- '**.rs'
|
||||||
- .github/workflows/kcl-language-server.yml
|
- .github/workflows/kcl-language-server.yml
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_INCREMENTAL: 0
|
CARGO_INCREMENTAL: 0
|
||||||
CARGO_NET_RETRY: 10
|
CARGO_NET_RETRY: 10
|
||||||
@ -38,10 +35,9 @@ env:
|
|||||||
MACOSX_DEPLOYMENT_TARGET: 10.15
|
MACOSX_DEPLOYMENT_TARGET: 10.15
|
||||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||||
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: vscode tests
|
name: kcl-language-server (vscode tests)
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@ -77,8 +73,7 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
target: x86_64-pc-windows-msvc
|
target: x86_64-pc-windows-msvc
|
||||||
code-target:
|
code-target: win32-x64
|
||||||
win32-x64
|
|
||||||
#- os: windows-latest
|
#- os: windows-latest
|
||||||
#target: i686-pc-windows-msvc
|
#target: i686-pc-windows-msvc
|
||||||
#code-target:
|
#code-target:
|
||||||
@ -88,8 +83,7 @@ jobs:
|
|||||||
#code-target: win32-arm64
|
#code-target: win32-arm64
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
target: x86_64-unknown-linux-gnu
|
target: x86_64-unknown-linux-gnu
|
||||||
code-target:
|
code-target: linux-x64
|
||||||
linux-x64
|
|
||||||
#- os: ubuntu-latest
|
#- os: ubuntu-latest
|
||||||
#target: aarch64-unknown-linux-musl
|
#target: aarch64-unknown-linux-musl
|
||||||
#code-target: linux-arm64
|
#code-target: linux-arm64
|
||||||
@ -105,41 +99,33 @@ jobs:
|
|||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
target: aarch64-apple-darwin
|
target: aarch64-apple-darwin
|
||||||
code-target: darwin-arm64
|
code-target: darwin-arm64
|
||||||
|
name: kcl-language-server build-release (${{ matrix.target }})
|
||||||
name: build-release (${{ matrix.target }})
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
container: ${{ matrix.container }}
|
container: ${{ matrix.container }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
RA_TARGET: ${{ matrix.target }}
|
RA_TARGET: ${{ matrix.target }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: ${{ env.FETCH_DEPTH }}
|
fetch-depth: ${{ env.FETCH_DEPTH }}
|
||||||
|
|
||||||
- name: Use correct Rust toolchain
|
- name: Use correct Rust toolchain
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
rm rust/rust-toolchain.toml
|
rm rust/rust-toolchain.toml
|
||||||
|
|
||||||
- name: Install rust
|
- name: Install rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: rust
|
cache: rust
|
||||||
components: rust-src
|
components: rust-src
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
|
|
||||||
- name: Update apt repositories
|
- name: Update apt repositories
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf' || matrix.os == 'ubuntu-latest'
|
if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf' || matrix.os == 'ubuntu-latest'
|
||||||
run: sudo apt-get update
|
run: sudo apt-get update
|
||||||
|
|
||||||
- if: ${{ matrix.os == 'ubuntu-latest' }}
|
- if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||||
name: Install deps
|
name: Install deps
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -164,64 +150,53 @@ jobs:
|
|||||||
zlib1g-dev
|
zlib1g-dev
|
||||||
|
|
||||||
cargo install cross
|
cargo install cross
|
||||||
|
|
||||||
- name: Install AArch64 target toolchain
|
- name: Install AArch64 target toolchain
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||||
run: sudo apt-get install gcc-aarch64-linux-gnu
|
run: sudo apt-get install gcc-aarch64-linux-gnu
|
||||||
|
|
||||||
- name: Install ARM target toolchain
|
- name: Install ARM target toolchain
|
||||||
if: matrix.target == 'arm-unknown-linux-gnueabihf'
|
if: matrix.target == 'arm-unknown-linux-gnueabihf'
|
||||||
run: sudo apt-get install gcc-arm-linux-gnueabihf
|
run: sudo apt-get install gcc-arm-linux-gnueabihf
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
||||||
|
|
||||||
- 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
|
# 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 --yarn -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 --yarn -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'
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
rm -rf server
|
rm -rf server
|
||||||
|
|
||||||
- name: Package Extension (no server, release)
|
- name: Package Extension (no server, release)
|
||||||
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 --yarn -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 --yarn -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
|
||||||
with:
|
with:
|
||||||
name: release-${{ matrix.target }}
|
name: release-${{ matrix.target }}
|
||||||
path: ./rust/build
|
path: ./rust/build
|
||||||
|
|
||||||
build-release-x86_64-unknown-linux-musl:
|
build-release-x86_64-unknown-linux-musl:
|
||||||
name: build-release (x86_64-unknown-linux-musl)
|
name: kcl-language-server build-release (x86_64-unknown-linux-musl)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
RA_TARGET: x86_64-unknown-linux-musl
|
RA_TARGET: x86_64-unknown-linux-musl
|
||||||
@ -231,7 +206,6 @@ jobs:
|
|||||||
image: alpine:latest
|
image: alpine:latest
|
||||||
volumes:
|
volumes:
|
||||||
- /usr/local/cargo/registry:/usr/local/cargo/registry
|
- /usr/local/cargo/registry:/usr/local/cargo/registry
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
@ -245,55 +219,46 @@ jobs:
|
|||||||
nodejs \
|
nodejs \
|
||||||
npm \
|
npm \
|
||||||
yarn
|
yarn
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: ${{ env.FETCH_DEPTH }}
|
fetch-depth: ${{ env.FETCH_DEPTH }}
|
||||||
|
|
||||||
- name: Use correct Rust toolchain
|
- name: Use correct Rust toolchain
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
rm rust/rust-toolchain.toml
|
rm rust/rust-toolchain.toml
|
||||||
|
|
||||||
- name: Install rust
|
- name: Install rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: rust
|
cache: rust
|
||||||
components: rust-src
|
components: rust-src
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
||||||
|
|
||||||
- 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
|
# 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 --yarn -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 --yarn -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
|
||||||
with:
|
with:
|
||||||
name: release-x86_64-unknown-linux-musl
|
name: release-x86_64-unknown-linux-musl
|
||||||
path: ./rust/build
|
path: ./rust/build
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
name: publish
|
name: kcl-language-server (publish)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: ["build-release", "build-release-x86_64-unknown-linux-musl"]
|
needs: ["build-release", "build-release-x86_64-unknown-linux-musl"]
|
||||||
if: startsWith(github.event.ref, 'refs/tags')
|
if: startsWith(github.event.ref, 'refs/tags')
|
||||||
@ -301,22 +266,17 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- run: echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
- run: echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- run: 'echo "TAG: $TAG"'
|
- run: 'echo "TAG: $TAG"'
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: ${{ env.FETCH_DEPTH }}
|
fetch-depth: ${{ env.FETCH_DEPTH }}
|
||||||
|
|
||||||
- name: Install Nodejs
|
- name: Install Nodejs
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
|
|
||||||
- run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
- run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
||||||
- run: 'echo "HEAD_SHA: $HEAD_SHA"'
|
- run: 'echo "HEAD_SHA: $HEAD_SHA"'
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-aarch64-apple-darwin
|
name: release-aarch64-apple-darwin
|
||||||
@ -344,8 +304,7 @@ jobs:
|
|||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-x86_64-pc-windows-msvc
|
name: release-x86_64-pc-windows-msvc
|
||||||
path:
|
path: rust/build
|
||||||
rust/build
|
|
||||||
#- uses: actions/download-artifact@v4
|
#- uses: actions/download-artifact@v4
|
||||||
#with:
|
#with:
|
||||||
#name: release-i686-pc-windows-msvc
|
#name: release-i686-pc-windows-msvc
|
||||||
@ -356,21 +315,18 @@ jobs:
|
|||||||
#name: release-aarch64-pc-windows-msvc
|
#name: release-aarch64-pc-windows-msvc
|
||||||
#path: rust/build
|
#path: rust/build
|
||||||
- run: ls -al ./rust/build
|
- run: ls -al ./rust/build
|
||||||
|
|
||||||
- name: Publish Release
|
- name: Publish Release
|
||||||
uses: ./.github/actions/github-release
|
uses: ./.github/actions/github-release
|
||||||
with:
|
with:
|
||||||
files: "rust/build/*"
|
files: "rust/build/*"
|
||||||
name: ${{ env.TAG }}
|
name: ${{ env.TAG }}
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: move files to dir for upload
|
- name: move files to dir for upload
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
mkdir -p releases/language-server/${{ env.TAG }}
|
mkdir -p releases/language-server/${{ env.TAG }}
|
||||||
cp -r build/* releases/language-server/${{ env.TAG }}
|
cp -r build/* releases/language-server/${{ env.TAG }}
|
||||||
|
|
||||||
- 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"
|
||||||
with:
|
with:
|
||||||
@ -385,15 +341,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: rust/releases
|
path: rust/releases
|
||||||
destination: dl.kittycad.io
|
destination: dl.kittycad.io
|
||||||
|
|
||||||
- run: rm rust/build/kcl-language-server-no-server.vsix
|
- run: rm rust/build/kcl-language-server-no-server.vsix
|
||||||
|
|
||||||
- name: Publish Extension (Code Marketplace, release)
|
- name: Publish Extension (Code Marketplace, release)
|
||||||
# token from https://dev.azure.com/kcl-language-server/
|
# token from https://dev.azure.com/kcl-language-server/
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce publish --pat ${{ secrets.VSCE_PAT }} --packagePath ../build/kcl-language-server-*.vsix
|
npx vsce publish --pat ${{ secrets.VSCE_PAT }} --packagePath ../build/kcl-language-server-*.vsix
|
||||||
|
|
||||||
- name: Publish Extension (OpenVSX, release)
|
- name: Publish Extension (OpenVSX, release)
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
|
14
.github/workflows/kcl-python-bindings.yml
vendored
@ -4,7 +4,6 @@
|
|||||||
# maturin generate-ci github
|
# maturin generate-ci github
|
||||||
#
|
#
|
||||||
name: kcl-python-bindings
|
name: kcl-python-bindings
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@ -27,16 +26,14 @@ on:
|
|||||||
- '**.rs'
|
- '**.rs'
|
||||||
- .github/workflows/kcl-python-bindings.yml
|
- .github/workflows/kcl-python-bindings.yml
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
linux-x86_64:
|
linux-x86_64:
|
||||||
|
name: kcl-python-bindings (linux-x86_64)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -58,8 +55,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-linux-x86_64
|
name: wheels-linux-x86_64
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
|
name: kcl-python-bindings (windows)
|
||||||
runs-on: windows-16-cores
|
runs-on: windows-16-cores
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -84,8 +81,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-windows-${{ matrix.target }}
|
name: wheels-windows-${{ matrix.target }}
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
|
name: kcl-python-bindings (macos)
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -110,8 +107,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-macos-${{ matrix.target }}
|
name: wheels-macos-${{ matrix.target }}
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
name: kcl-python-bindings (test)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -127,8 +124,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
ZOO_HOST: https://api.dev.zoo.dev
|
ZOO_HOST: https://api.dev.zoo.dev
|
||||||
|
|
||||||
sdist:
|
sdist:
|
||||||
|
name: kcl-python-bindings (sdist)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -151,7 +148,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-sdist
|
name: wheels-sdist
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
167
.github/workflows/static-analysis.yml
vendored
@ -28,53 +28,7 @@ jobs:
|
|||||||
- run: npm run fmt:check
|
- run: npm run fmt:check
|
||||||
|
|
||||||
npm-build-wasm:
|
npm-build-wasm:
|
||||||
# Build the wasm blob once on the fastest runner.
|
uses: ./.github/workflows/build-wasm.yml
|
||||||
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: Use correct Rust toolchain
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
|
||||||
|
|
||||||
- name: Install rust
|
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
||||||
with:
|
|
||||||
cache: false # Configured below.
|
|
||||||
|
|
||||||
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
|
||||||
with:
|
|
||||||
tool: wasm-pack
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: './rust'
|
|
||||||
|
|
||||||
- name: Build Wasm
|
|
||||||
shell: bash
|
|
||||||
run: npm run build:wasm
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: prepared-wasm
|
|
||||||
path: |
|
|
||||||
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: prepared-ts-rs-bindings
|
|
||||||
path: |
|
|
||||||
rust/kcl-lib/bindings/*
|
|
||||||
|
|
||||||
npm-tsc:
|
npm-tsc:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -173,122 +127,3 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Run codespell
|
- name: Run codespell
|
||||||
uses: crate-ci/typos@v1.32.0
|
uses: crate-ci/typos@v1.32.0
|
||||||
|
|
||||||
npm-unit-test-kcl-samples:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: npm-build-wasm
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- run: npm install
|
|
||||||
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
|
||||||
with:
|
|
||||||
tool: wasm-pack
|
|
||||||
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
|
|
||||||
- name: Copy prepared wasm
|
|
||||||
run: |
|
|
||||||
ls -R prepared-wasm
|
|
||||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
|
||||||
mkdir rust/kcl-wasm-lib/pkg
|
|
||||||
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
|
||||||
|
|
||||||
- name: Copy prepared ts-rs bindings
|
|
||||||
run: |
|
|
||||||
ls -R prepared-ts-rs-bindings
|
|
||||||
mkdir rust/kcl-lib/bindings
|
|
||||||
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
|
||||||
|
|
||||||
- run: npm run simpleserver:bg
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
|
|
||||||
- name: Install Chromium Browser
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
run: npm run playwright install chromium --with-deps
|
|
||||||
|
|
||||||
- name: Download internal KCL samples
|
|
||||||
run: git clone --depth=1 https://x-access-token:${{ secrets.GH_PAT_KCL_SAMPLES_INTERNAL }}@github.com/KittyCAD/kcl-samples-internal public/kcl-samples/internal
|
|
||||||
|
|
||||||
- name: Regenerate KCL samples manifest
|
|
||||||
run: cd rust/kcl-lib && EXPECTORATE=overwrite cargo test generate_manifest
|
|
||||||
|
|
||||||
- name: Check public and internal KCL samples
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
run: npm run test:unit:kcl-samples
|
|
||||||
env:
|
|
||||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
|
||||||
|
|
||||||
npm-unit-test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: npm-build-wasm
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- run: npm install
|
|
||||||
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
|
||||||
with:
|
|
||||||
tool: wasm-pack
|
|
||||||
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
|
|
||||||
- name: Copy prepared wasm
|
|
||||||
run: |
|
|
||||||
ls -R prepared-wasm
|
|
||||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
|
||||||
mkdir rust/kcl-wasm-lib/pkg
|
|
||||||
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
|
||||||
|
|
||||||
- name: Copy prepared ts-rs bindings
|
|
||||||
run: |
|
|
||||||
ls -R prepared-ts-rs-bindings
|
|
||||||
mkdir rust/kcl-lib/bindings
|
|
||||||
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
|
||||||
|
|
||||||
- run: npm run simpleserver:bg
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
|
|
||||||
- name: Install Chromium Browser
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
run: npm run playwright install chromium --with-deps
|
|
||||||
|
|
||||||
- name: Run unit tests
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
run: xvfb-run -a npm run test:unit
|
|
||||||
env:
|
|
||||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
|
||||||
|
|
||||||
- name: Check for changes
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
id: git-check
|
|
||||||
run: |
|
|
||||||
git add src/lang/std/artifactMapGraphs
|
|
||||||
if git status src/lang/std/artifactMapGraphs | grep -q "Changes to be committed"
|
|
||||||
then echo "modified=true" >> $GITHUB_OUTPUT
|
|
||||||
else echo "modified=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
- name: Commit changes, if any
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' && steps.git-check.outputs.modified == 'true' }}
|
|
||||||
run: |
|
|
||||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git config --local user.name "github-actions[bot]"
|
|
||||||
git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
|
|
||||||
git fetch origin
|
|
||||||
echo ${{ github.head_ref }}
|
|
||||||
git checkout ${{ github.head_ref }}
|
|
||||||
# TODO when webkit works on ubuntu remove the os part of the commit message
|
|
||||||
git commit -am "Look at this (photo)Graph *in the voice of Nickelback*" || true
|
|
||||||
git push
|
|
||||||
git push origin ${{ github.head_ref }}
|
|
||||||
|
124
.github/workflows/unit-tests.yml
vendored
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
name: Unit Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
actions: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
npm-build-wasm:
|
||||||
|
uses: ./.github/workflows/build-wasm.yml
|
||||||
|
|
||||||
|
npm-test-unit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: npm-build-wasm
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- run: npm install
|
||||||
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
|
with:
|
||||||
|
tool: wasm-pack
|
||||||
|
|
||||||
|
- name: Download all artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
|
- name: Copy prepared wasm
|
||||||
|
run: |
|
||||||
|
ls -R prepared-wasm
|
||||||
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
|
mkdir rust/kcl-wasm-lib/pkg
|
||||||
|
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
|
- name: Copy prepared ts-rs bindings
|
||||||
|
run: |
|
||||||
|
ls -R prepared-ts-rs-bindings
|
||||||
|
mkdir rust/kcl-lib/bindings
|
||||||
|
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
||||||
|
|
||||||
|
- run: npm run simpleserver:bg
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
|
||||||
|
- name: Install Chromium Browser
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
run: npm run playwright install chromium --with-deps
|
||||||
|
|
||||||
|
- name: Run unit tests
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
run: xvfb-run -a npm run test:unit
|
||||||
|
env:
|
||||||
|
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
|
||||||
|
- name: Check for changes
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
id: git-check
|
||||||
|
run: |
|
||||||
|
git add src/lang/std/artifactMapGraphs
|
||||||
|
if git status src/lang/std/artifactMapGraphs | grep -q "Changes to be committed"
|
||||||
|
then echo "modified=true" >> $GITHUB_OUTPUT
|
||||||
|
else echo "modified=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Commit changes, if any
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' && steps.git-check.outputs.modified == 'true' }}
|
||||||
|
run: |
|
||||||
|
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --local user.name "github-actions[bot]"
|
||||||
|
git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
|
||||||
|
git fetch origin
|
||||||
|
echo ${{ github.head_ref }}
|
||||||
|
git checkout ${{ github.head_ref }}
|
||||||
|
# TODO when webkit works on ubuntu remove the os part of the commit message
|
||||||
|
git commit -am "Look at this (photo)Graph *in the voice of Nickelback*" || true
|
||||||
|
git push
|
||||||
|
git push origin ${{ github.head_ref }}
|
||||||
|
|
||||||
|
npm-test-unit-components:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: npm-build-wasm
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- run: npm install
|
||||||
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
|
with:
|
||||||
|
tool: wasm-pack
|
||||||
|
|
||||||
|
- name: Download all artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
|
- name: Copy prepared wasm
|
||||||
|
run: |
|
||||||
|
ls -R prepared-wasm
|
||||||
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
|
mkdir rust/kcl-wasm-lib/pkg
|
||||||
|
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
|
- name: Copy prepared ts-rs bindings
|
||||||
|
run: |
|
||||||
|
ls -R prepared-ts-rs-bindings
|
||||||
|
mkdir rust/kcl-lib/bindings
|
||||||
|
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
||||||
|
|
||||||
|
- name: Run component tests
|
||||||
|
run: npm run test:unit:components
|
2
.gitignore
vendored
@ -58,6 +58,8 @@ trace.zip
|
|||||||
/public/kcl-samples/.github
|
/public/kcl-samples/.github
|
||||||
/public/kcl-samples/screenshots/main.kcl
|
/public/kcl-samples/screenshots/main.kcl
|
||||||
/public/kcl-samples/step/main.kcl
|
/public/kcl-samples/step/main.kcl
|
||||||
|
/public/kcl-samples/internal
|
||||||
|
/rust/kcl-lib/tests/kcl_samples/internal
|
||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
/blob-report/
|
/blob-report/
|
||||||
|
@ -122,25 +122,24 @@ https://github.com/KittyCAD/modeling-app/issues/new
|
|||||||
|
|
||||||
#### 2. Push a new tag
|
#### 2. Push a new tag
|
||||||
|
|
||||||
Create a new tag and push it to the repo. The `semantic-release.sh` script will automatically bump the minor part, which we use the most. For instance going from `v0.27.0` to `v0.28.0`.
|
Decide on a `v`-prefixed semver `VERSION` (e.g. `v1.2.3`) with the team and tag the repo on the latest main:
|
||||||
|
|
||||||
```
|
```
|
||||||
VERSION=$(./scripts/semantic-release.sh)
|
git tag $VERSION --message=""
|
||||||
git tag $VERSION
|
git push origin $VERSION
|
||||||
git push origin --tags
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This will trigger the `build-apps` workflow, set the version, build & sign the apps, and generate release files.
|
This will trigger the `build-apps` workflow to set the version, build & sign the apps, and generate release files.
|
||||||
|
|
||||||
The workflow should be listed right away [in this list](https://github.com/KittyCAD/modeling-app/actions/workflows/build-apps.yml?query=event%3Apush)).
|
The workflow should be listed right away [in this list](https://github.com/KittyCAD/modeling-app/actions/workflows/build-apps.yml?query=event%3Apush).
|
||||||
|
|
||||||
#### 3. Manually test artifacts
|
#### 3. Manually test artifacts
|
||||||
|
|
||||||
##### Release builds
|
##### Release builds
|
||||||
|
|
||||||
The release builds can be found under the `out-{arch}-{platform}` zip files, at the very bottom of the `build-apps` summary page for the workflow (triggered by the tag in 2.).
|
The release builds can be found under the `out-{arch}-{platform}` zip files, at the very bottom of the `build-apps` summary page for the workflow (triggered by the tag in step 2).
|
||||||
|
|
||||||
Manually test against this [list](https://github.com/KittyCAD/modeling-app/issues/3588) across Windows, MacOS, Linux and posting results as comments in the issue.
|
Manually test against [this list](https://github.com/KittyCAD/modeling-app/issues/3588) across Windows, MacOS, Linux and posting results as comments in the issue.
|
||||||
|
|
||||||
A prompt should show up asking for a downgrade to the last release version. Running through that at the end of testing
|
A prompt should show up asking for a downgrade to the last release version. Running through that at the end of testing
|
||||||
and making sure the current release candidate has the ability to be updated to what electron-updater points to is critical,
|
and making sure the current release candidate has the ability to be updated to what electron-updater points to is critical,
|
||||||
@ -158,15 +157,20 @@ If the prompt doesn't show up, start the app in command line to grab the electro
|
|||||||
./Zoo Design Studio-{version}-{arch}-linux.AppImage
|
./Zoo Design Studio-{version}-{arch}-linux.AppImage
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 4. Publish the release
|
#### 4. Bump the KCL version
|
||||||
|
|
||||||
Head over to https://github.com/KittyCAD/modeling-app/releases/new, pick the newly created tag and type it in the _Release title_ field as well.
|
Follow the instructions [here](./rust/README.md) to publish new crates.
|
||||||
|
This ensures that the KCL accepted by the app is also accepted by the CLI.
|
||||||
|
|
||||||
Hit _Generate release notes_ as a starting point to discuss the changelog in the issue. Once done, make sure _Set as the latest release_ is checked, and hit _Publish release_.
|
#### 5. Publish the release
|
||||||
|
|
||||||
A new `publish-apps-release` will kick in and you should be able to find it [here](https://github.com/KittyCAD/modeling-app/actions?query=event%3Arelease). On success, the files will be uploaded to the public bucket as well as to the GitHub release, and the announcement on Discord will be sent.
|
Head over to https://github.com/KittyCAD/modeling-app/releases/new, pick the newly created tag and type it in the **Release title** field as well.
|
||||||
|
|
||||||
#### 5. Close the issue
|
Click **Generate release notes** as a starting point to discuss the changelog in the issue. Once done, make sure **Set as the latest release** is checked, and click **Publish release**.
|
||||||
|
|
||||||
|
A new `publish-apps-release` workflow will start and you should be able to find it [here](https://github.com/KittyCAD/modeling-app/actions?query=event%3Arelease). On success, the files will be uploaded to the public bucket as well as to the GitHub release, and the announcement on Discord will be sent.
|
||||||
|
|
||||||
|
#### 6. Close the issue
|
||||||
|
|
||||||
If everything is well and the release is out to the public, the issue tracking the release shall be closed.
|
If everything is well and the release is out to the public, the issue tracking the release shall be closed.
|
||||||
|
|
||||||
@ -201,7 +205,7 @@ Prepare these system dependencies:
|
|||||||
|
|
||||||
#### Snapshot tests (Google Chrome on Ubuntu only)
|
#### Snapshot tests (Google Chrome on Ubuntu only)
|
||||||
|
|
||||||
Only Ubunu and Google Chrome is supported for the set of tests evaluating screenshot snapshots.
|
Only Ubuntu 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.
|
If you don't run Ubuntu locally or in a VM, you may use a GitHub Codespace.
|
||||||
```
|
```
|
||||||
npm run playwright -- install chrome
|
npm run playwright -- install chrome
|
||||||
@ -209,14 +213,21 @@ npm run test:snapshots
|
|||||||
```
|
```
|
||||||
You may use `-- --update-snapshots` as needed.
|
You may use `-- --update-snapshots` as needed.
|
||||||
|
|
||||||
#### Electron flow tests (Chromium on Ubuntu, macOS, Windows)
|
#### Desktop tests (Electron on all platforms)
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run playwright -- install chromium
|
npm run playwright -- install chromium
|
||||||
npm run test:playwright:electron:local
|
npm run test:e2e:desktop:local
|
||||||
```
|
```
|
||||||
|
|
||||||
You may use `-- -g "my test"` to match specific test titles, or `-- path/to/file.spec.ts` for a test file.
|
You may use `-- -g "my test"` to match specific test titles, or `-- path/to/file.spec.ts` for a test file.
|
||||||
|
|
||||||
|
#### Web tests (Google Chrome on all platforms)
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run test:e2e:web
|
||||||
|
```
|
||||||
|
|
||||||
#### Debugger
|
#### Debugger
|
||||||
|
|
||||||
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.
|
||||||
|
@ -4,7 +4,7 @@ Compared to other CAD software, getting Zoo Design Studio up and running is quic
|
|||||||
|
|
||||||
## Windows
|
## Windows
|
||||||
|
|
||||||
1. Download the [Zoo Design Studio installer](https://zoo.dev/modeling-app/download) for Windows and for your processor type.
|
1. Download the [Zoo Design Studio installer](https://zoo.dev/design-studio/download) for Windows and for your processor type.
|
||||||
|
|
||||||
2. Once downloaded, run the installer `Zoo Design Studio-{version}-{arch}-win.exe` which should take a few seconds.
|
2. Once downloaded, run the installer `Zoo Design Studio-{version}-{arch}-win.exe` which should take a few seconds.
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ Compared to other CAD software, getting Zoo Design Studio up and running is quic
|
|||||||
|
|
||||||
## macOS
|
## macOS
|
||||||
|
|
||||||
1. Download the [Zoo Design Studio installer](https://zoo.dev/modeling-app/download) for macOS and for your processor type.
|
1. Download the [Zoo Design Studio installer](https://zoo.dev/design-studio/download) for macOS and for your processor type.
|
||||||
|
|
||||||
2. Once downloaded, open the disk image `Zoo Design Studio-{version}-{arch}-mac.dmg` and drag the applications to your `Applications` directory.
|
2. Once downloaded, open the disk image `Zoo Design Studio-{version}-{arch}-mac.dmg` and drag the applications to your `Applications` directory.
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ Compared to other CAD software, getting Zoo Design Studio up and running is quic
|
|||||||
|
|
||||||
## Linux
|
## Linux
|
||||||
|
|
||||||
1. Download the [Zoo Design Studio installer](https://zoo.dev/modeling-app/download) for Linux and for your processor type.
|
1. Download the [Zoo Design Studio installer](https://zoo.dev/design-studio/download) for Linux and for your processor type.
|
||||||
|
|
||||||
2. Install the dependencies needed to run the [AppImage format](https://appimage.org/).
|
2. Install the dependencies needed to run the [AppImage format](https://appimage.org/).
|
||||||
- On Ubuntu, install the FUSE library with these commands in a terminal.
|
- On Ubuntu, install the FUSE library with these commands in a terminal.
|
||||||
|
10
Makefile
@ -114,26 +114,24 @@ test-unit: install ## Run the unit tests
|
|||||||
npm run test:unit:components
|
npm run test:unit:components
|
||||||
@ 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 )
|
||||||
npm run test:unit
|
npm run test:unit
|
||||||
npm run test:unit:kcl-samples
|
|
||||||
|
|
||||||
.PHONY: test-e2e
|
.PHONY: test-e2e
|
||||||
test-e2e: test-e2e-$(TARGET)
|
test-e2e: test-e2e-$(TARGET)
|
||||||
|
|
||||||
.PHONY: test-e2e-web
|
.PHONY: test-e2e-web
|
||||||
test-e2e-web: install build ## Run the web e2e tests
|
test-e2e-web: install build ## Run the web e2e tests
|
||||||
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
|
|
||||||
ifdef E2E_GREP
|
ifdef E2E_GREP
|
||||||
npm run chrome:test -- --headed --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES)
|
npm run test:e2e:web -- --headed --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES)
|
||||||
else
|
else
|
||||||
npm run chrome:test -- --headed --workers='100%'
|
npm run test:e2e:web -- --headed --workers='100%'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: test-e2e-desktop
|
.PHONY: test-e2e-desktop
|
||||||
test-e2e-desktop: install build ## Run the desktop e2e tests
|
test-e2e-desktop: install build ## Run the desktop e2e tests
|
||||||
ifdef E2E_GREP
|
ifdef E2E_GREP
|
||||||
npm run test:playwright:electron -- --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES)
|
npm run test:e2e:desktop -- --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES)
|
||||||
else
|
else
|
||||||
npm run test:playwright:electron -- --workers='100%'
|
npm run test:e2e:desktop -- --workers='100%'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
12
README.md
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Zoo Design Studio
|
# Zoo Design Studio
|
||||||
|
|
||||||
[zoo.dev/modeling-app](https://zoo.dev/modeling-app)
|
[zoo.dev/design-studio](https://zoo.dev/design-studio)
|
||||||
|
|
||||||
A CAD application from the future, brought to you by the [Zoo team](https://zoo.dev).
|
A CAD application from the future, brought to you by the [Zoo team](https://zoo.dev).
|
||||||
|
|
||||||
@ -40,14 +40,8 @@ The 3D view in Design Studio is just a video stream from our hosted geometry eng
|
|||||||
|
|
||||||
## Get Started
|
## Get Started
|
||||||
|
|
||||||
We recommend downloading the latest application binary from our [releases](https://github.com/KittyCAD/modeling-app/releases) page. If you don't see your platform or architecture supported there, please file an issue.
|
We recommend downloading the latest application binary from our [website](https://zoo.dev/design-studio/download). If you don't see your platform or architecture supported there, please file an issue. See the [installation guide](INSTALL.md) for additional instructions.
|
||||||
|
|
||||||
If you'd like to try out upcoming changes sooner, you can also download those from our [nightly releases](https://zoo.dev/modeling-app/download/nightly) page.
|
|
||||||
|
|
||||||
## Developing
|
## Developing
|
||||||
|
|
||||||
Finally, if you'd like to run a development build or contribute to the project, please visit our [contributor guide](CONTRIBUTING.md) to get started.
|
Finally, if you'd like to run a development build or contribute to the project, please visit our [contributor guide](CONTRIBUTING.md) to get started. To contribute to the KittyCAD Language, see the dedicated [readme](rust/kcl-lib/README.md) for KCL.
|
||||||
|
|
||||||
## KCL
|
|
||||||
|
|
||||||
To contribute to the KittyCAD Language, see the [README](https://github.com/KittyCAD/modeling-app/tree/main/rust/kcl-lib) for KCL.
|
|
||||||
|
@ -29,6 +29,7 @@ THRE = "THRE" # Weird bug that wrongly detects THREEjs as a typo
|
|||||||
nwo = "nwo" # don't know what this is about tbh
|
nwo = "nwo" # don't know what this is about tbh
|
||||||
"ot" = "ot" # some abbreviation, idk what
|
"ot" = "ot" # some abbreviation, idk what
|
||||||
"oe" = "oe" # some abbreviation, idk what
|
"oe" = "oe" # some abbreviation, idk what
|
||||||
|
"colinear" = "colinear" # some engine shit, kidding
|
||||||
|
|
||||||
[default]
|
[default]
|
||||||
extend-ignore-identifiers-re = [
|
extend-ignore-identifiers-re = [
|
||||||
|
@ -16,15 +16,16 @@ There are some useful functions for working with arrays in the standard library,
|
|||||||
|
|
||||||
Arrays have their own types: `[T]` where `T` is the type of the elements of the array, for example, `[string]` means an array of `string`s and `[any]` means an array of any values.
|
Arrays have their own types: `[T]` where `T` is the type of the elements of the array, for example, `[string]` means an array of `string`s and `[any]` means an array of any values.
|
||||||
|
|
||||||
Array types can also include length information: `[T; n]` denotes an array of length `n` (where `n` is a number literal) and `[T; 1+]` denotes an array whose length is at least one (i.e., a non-empty array). E.g., `[string; 1+]` and `[number(mm); 3]` are valid array types.
|
Array types can also include length information: `[T; n]` denotes an array of length `n` (where `n` is a number literal) and `[T; n+]` denotes an array whose length is at least `n`. The common case for that is `[T; 1+]`, i.e., a non-empty array. E.g., `[string; 1+]` and `[number(mm); 3]` are valid array types.
|
||||||
|
|
||||||
## Ranges
|
## Ranges
|
||||||
|
|
||||||
Ranges are a succinct way to create an array of sequential numbers. The syntax is `[start .. end]` where `start` and `end` evaluate to whole numbers (integers). Ranges are inclusive of the start and end. The end must be greater than the start. Examples:
|
Ranges are a succinct way to create an array of sequential numbers. The syntax is `[start .. end]` where `start` and `end` evaluate to whole numbers (integers). Ranges are inclusive of the start and end. The end must be greater than the start. A range which is exclusive of its end is written with `<end`. Examples:
|
||||||
|
|
||||||
```kcl,norun
|
```kcl,norun
|
||||||
[0..3] // [0, 1, 2, 3]
|
[0..3] // [0, 1, 2, 3]
|
||||||
[3..10] // [3, 4, 5, 6, 7, 8, 9, 10]
|
[3..10] // [3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
[3..<10] // [3, 4, 5, 6, 7, 8, 9]
|
||||||
x = 2
|
x = 2
|
||||||
[x..x+1] // [2, 3]
|
[x..x+1] // [2, 3]
|
||||||
```
|
```
|
||||||
|
@ -4,7 +4,7 @@ excerpt: "Documentation of the KCL language for the Zoo Design Studio."
|
|||||||
layout: manual
|
layout: manual
|
||||||
---
|
---
|
||||||
|
|
||||||
This is a reference for KCL. If you are learning KCL, you may prefer the [guide]() which explains
|
This is a reference for KCL. If you are learning KCL, you may prefer the [guide](https://zoo.dev/docs/kcl-book/intro.html) which explains
|
||||||
things in a more tutorial fashion. See also our documentation of the [standard library](/docs/kcl-std).
|
things in a more tutorial fashion. See also our documentation of the [standard library](/docs/kcl-std).
|
||||||
|
|
||||||
## Topics
|
## Topics
|
||||||
|
@ -27,9 +27,6 @@ import increment from "util.kcl"
|
|||||||
answer = increment(41)
|
answer = increment(41)
|
||||||
```
|
```
|
||||||
|
|
||||||
Imported files _must_ be in the same project so that units are uniform across
|
|
||||||
modules. This means that it must be in the same directory.
|
|
||||||
|
|
||||||
Import statements must be at the top-level of a file. It is not allowed to have
|
Import statements must be at the top-level of a file. It is not allowed to have
|
||||||
an `import` statement inside a function or in the body of an if‑else.
|
an `import` statement inside a function or in the body of an if‑else.
|
||||||
|
|
||||||
@ -58,6 +55,9 @@ Imported symbols can be renamed for convenience or to avoid name collisions.
|
|||||||
import increment as inc, decrement as dec from "util.kcl"
|
import increment as inc, decrement as dec from "util.kcl"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can import files from the current directory or from subdirectories, but if importing from a
|
||||||
|
subdirectory you can only import `main.kcl`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Functions vs `clone`
|
## Functions vs `clone`
|
||||||
@ -177,7 +177,7 @@ You can also import the whole module. This is useful if you want to use the
|
|||||||
result of a module as a variable, like a part.
|
result of a module as a variable, like a part.
|
||||||
|
|
||||||
```norun
|
```norun
|
||||||
import "tests/inputs/cube.kcl" as cube
|
import "cube.kcl"
|
||||||
cube
|
cube
|
||||||
|> translate(x=10)
|
|> translate(x=10)
|
||||||
```
|
```
|
||||||
@ -229,6 +229,19 @@ The final statement is what's important because it's the return value of the
|
|||||||
entire module. The module is expected to return a single object that can be used
|
entire module. The module is expected to return a single object that can be used
|
||||||
as a variable by the file that imports it.
|
as a variable by the file that imports it.
|
||||||
|
|
||||||
|
The name of the file or subdirectory is used as the name of the variable within the importing program.
|
||||||
|
If you want to use a different name, you can do so by using the `as` keyword:
|
||||||
|
|
||||||
|
```kcl,norun
|
||||||
|
import "cube.kcl" // Introduces a new variable called `cube`.
|
||||||
|
import "cube.kcl" as block // Introduces a new variable called `block`.
|
||||||
|
import "cube/main.kcl" // Introduces a new variable called `cube`.
|
||||||
|
import "cube/main.kcl" as block // Introduces a new variable called `block`.
|
||||||
|
```
|
||||||
|
|
||||||
|
If the filename includes hyphens (`-`) or starts with an underscore (`_`), then you must specify a
|
||||||
|
variable name.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Multiple instances of the same import
|
## Multiple instances of the same import
|
||||||
@ -241,7 +254,7 @@ If you want to have multiple instances of the same object, you can use the
|
|||||||
[`clone`](/docs/kcl/clone) function. This will render a new instance of the object in memory.
|
[`clone`](/docs/kcl/clone) function. This will render a new instance of the object in memory.
|
||||||
|
|
||||||
```norun
|
```norun
|
||||||
import cube from "tests/inputs/cube.kcl"
|
import cube from "cube.kcl"
|
||||||
|
|
||||||
cube
|
cube
|
||||||
|> translate(x=10)
|
|> translate(x=10)
|
||||||
@ -257,7 +270,7 @@ separate objects in memory, and can be manipulated independently.
|
|||||||
Here is an example with a file from another CAD system:
|
Here is an example with a file from another CAD system:
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
import "tests/inputs/cube.step" as cube
|
import "tests/inputs/cube.step"
|
||||||
|
|
||||||
cube
|
cube
|
||||||
|> translate(x=10)
|
|> translate(x=10)
|
||||||
|
@ -13,6 +13,7 @@ arc(
|
|||||||
angleStart?: number,
|
angleStart?: number,
|
||||||
angleEnd?: number,
|
angleEnd?: number,
|
||||||
radius?: number,
|
radius?: number,
|
||||||
|
diameter?: number,
|
||||||
interiorAbsolute?: Point2d,
|
interiorAbsolute?: Point2d,
|
||||||
endAbsolute?: Point2d,
|
endAbsolute?: Point2d,
|
||||||
tag?: TagDeclarator,
|
tag?: TagDeclarator,
|
||||||
@ -30,7 +31,8 @@ Unless this makes a lot of sense and feels like what you're looking for to const
|
|||||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
||||||
| `angleStart` | [`number`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc start? | No |
|
| `angleStart` | [`number`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc start? | No |
|
||||||
| `angleEnd` | [`number`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc end? | No |
|
| `angleEnd` | [`number`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc end? | No |
|
||||||
| `radius` | [`number`](/docs/kcl-std/types/std-types-number) | How large should the circle be? | No |
|
| `radius` | [`number`](/docs/kcl-std/types/std-types-number) | How large should the circle be? Incompatible with `diameter`. | No |
|
||||||
|
| `diameter` | [`number`](/docs/kcl-std/types/std-types-number) | How large should the circle be? Incompatible with `radius`. | No |
|
||||||
| `interiorAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd` | No |
|
| `interiorAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd` | No |
|
||||||
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Where should this arc end? Requires `interiorAbsolute`. Incompatible with `angleStart` or `angleEnd` | No |
|
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Where should this arc end? Requires `interiorAbsolute`. Incompatible with `angleStart` or `angleEnd` | No |
|
||||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
|
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
|
||||||
|
127
docs/kcl-std/functions/std-appearance-hexString.md
Normal file
64
docs/kcl-std/functions/std-appearance-rgb.md
Normal file
@ -12,7 +12,7 @@ reduce(
|
|||||||
@array: [any],
|
@array: [any],
|
||||||
initial: any,
|
initial: any,
|
||||||
f: fn(any, accum: any): any,
|
f: fn(any, accum: any): any,
|
||||||
): [any]
|
): any
|
||||||
```
|
```
|
||||||
|
|
||||||
Take a starting value. Then, for each element of an array, calculate the next value,
|
Take a starting value. Then, for each element of an array, calculate the next value,
|
||||||
@ -28,7 +28,7 @@ using the previous value and the element.
|
|||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`[any]`](/docs/kcl-std/types/std-types-any)
|
[`any`](/docs/kcl-std/types/std-types-any)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -11,7 +11,7 @@ Compute the length of the given leg.
|
|||||||
legLen(
|
legLen(
|
||||||
hypotenuse: number(Length),
|
hypotenuse: number(Length),
|
||||||
leg: number(Length),
|
leg: number(Length),
|
||||||
): number(deg)
|
): number(Length)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ legLen(
|
|||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`number(deg)`](/docs/kcl-std/types/std-types-number) - A number.
|
[`number(Length)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -11,7 +11,8 @@ layout: manual
|
|||||||
circle(
|
circle(
|
||||||
@sketch_or_surface: Sketch | Plane | Face,
|
@sketch_or_surface: Sketch | Plane | Face,
|
||||||
center: Point2d,
|
center: Point2d,
|
||||||
radius: number(Length),
|
radius?: number(Length),
|
||||||
|
diameter?: number(Length),
|
||||||
tag?: tag,
|
tag?: tag,
|
||||||
): Sketch
|
): Sketch
|
||||||
```
|
```
|
||||||
@ -25,7 +26,8 @@ the provided (x, y) origin point.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketch_or_surface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
|
| `sketch_or_surface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
|
||||||
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center of the circle. | Yes |
|
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center of the circle. | Yes |
|
||||||
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The radius of the circle. | Yes |
|
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The radius of the circle. Incompatible with `diameter`. | No |
|
||||||
|
| `diameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The diameter of the circle. Incompatible with `radius`. | No |
|
||||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this circle. | No |
|
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this circle. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
@ -51,7 +53,7 @@ exampleSketch = startSketchOn(XZ)
|
|||||||
|> line(end = [0, 30])
|
|> line(end = [0, 30])
|
||||||
|> line(end = [-30, 0])
|
|> line(end = [-30, 0])
|
||||||
|> close()
|
|> close()
|
||||||
|> subtract2d(tool = circle(center = [0, 15], radius = 5))
|
|> subtract2d(tool = circle(center = [0, 15], diameter = 10))
|
||||||
|
|
||||||
example = extrude(exampleSketch, length = 5)
|
example = extrude(exampleSketch, length = 5)
|
||||||
```
|
```
|
||||||
|
@ -8,7 +8,7 @@ layout: manual
|
|||||||
Get the shared edge between two faces.
|
Get the shared edge between two faces.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
getCommonEdge(faces: [TagIdentifier]): Uuid
|
getCommonEdge(faces: [tag; 2]): Edge
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -17,11 +17,11 @@ getCommonEdge(faces: [TagIdentifier]): Uuid
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `faces` | [`[TagIdentifier]`](/docs/kcl-lang/types#TagIdentifier) | The tags of the faces you want to find the common edge between | Yes |
|
| `faces` | `[tag; 2]` | The tags of the faces you want to find the common edge between. | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
`Uuid`
|
[`Edge`](/docs/kcl-std/types/std-types-Edge) - An edge of a solid.
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
@ -29,7 +29,6 @@ getCommonEdge(faces: [TagIdentifier]): Uuid
|
|||||||
```kcl
|
```kcl
|
||||||
// Get an edge shared between two faces, created after a chamfer.
|
// Get an edge shared between two faces, created after a chamfer.
|
||||||
|
|
||||||
|
|
||||||
scale = 20
|
scale = 20
|
||||||
part001 = startSketchOn(XY)
|
part001 = startSketchOn(XY)
|
||||||
|> startProfile(at = [0, 0])
|
|> startProfile(at = [0, 0])
|
@ -1,19 +1,19 @@
|
|||||||
---
|
---
|
||||||
title: "patternTransform2d"
|
title: "patternTransform2d"
|
||||||
subtitle: "Function in std::sketch"
|
subtitle: "Function in std::sketch"
|
||||||
excerpt: "Just like patternTransform, but works on 2D sketches not 3D solids."
|
excerpt: "Just like `patternTransform`, but works on 2D sketches not 3D solids."
|
||||||
layout: manual
|
layout: manual
|
||||||
---
|
---
|
||||||
|
|
||||||
Just like patternTransform, but works on 2D sketches not 3D solids.
|
Just like `patternTransform`, but works on 2D sketches not 3D solids.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
patternTransform2d(
|
patternTransform2d(
|
||||||
@sketches: [Sketch],
|
@sketches: [Sketch; 1+],
|
||||||
instances: number,
|
instances: number(_),
|
||||||
transform: FunctionSource,
|
transform: fn(number(_)): { },
|
||||||
useOriginal?: bool,
|
useOriginal?: boolean,
|
||||||
): [Sketch]
|
): [Sketch; 1+]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -22,14 +22,14 @@ patternTransform2d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketches` | [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) | The sketch(es) to duplicate | Yes |
|
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | The sketch(es) to duplicate. | Yes |
|
||||||
| `instances` | [`number`](/docs/kcl-std/types/std-types-number) | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | [`number(_)`](/docs/kcl-std/types/std-types-number) | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `transform` | `FunctionSource` | How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples. | Yes |
|
| `transform` | [`fn(number(_)): { }`](/docs/kcl-std/types/std-types-fn) | How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples. | Yes |
|
||||||
| `useOriginal` | [`bool`](/docs/kcl-std/types/std-types-bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. | No |
|
| `useOriginal` | `boolean` | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`[Sketch]`](/docs/kcl-std/types/std-types-Sketch)
|
[`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
@ -1,31 +1,36 @@
|
|||||||
---
|
---
|
||||||
title: "intersect"
|
title: "intersect"
|
||||||
subtitle: "Function in std::solid"
|
subtitle: "Function in std::solid"
|
||||||
excerpt: "Intersect returns the shared volume between multiple solids, preserving only overlapping regions."
|
excerpt: ""
|
||||||
layout: manual
|
layout: manual
|
||||||
---
|
---
|
||||||
|
|
||||||
Intersect returns the shared volume between multiple solids, preserving only overlapping regions.
|
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
intersect(
|
intersect(
|
||||||
@solids: [Solid],
|
@solids: [Solid; 2+],
|
||||||
tolerance?: number,
|
tolerance?: number(Length),
|
||||||
): [Solid]
|
): [Solid; 1+]
|
||||||
```
|
```
|
||||||
|
|
||||||
Intersect computes the geometric intersection of multiple solid bodies, returning a new solid representing the volume that is common to all input solids. This operation is useful for determining shared material regions, verifying fit, and analyzing overlapping geometries in assemblies.
|
Intersect returns the shared volume between multiple solids, preserving only
|
||||||
|
overlapping regions.
|
||||||
|
Intersect computes the geometric intersection of multiple solid bodies,
|
||||||
|
returning a new solid representing the volume that is common to all input
|
||||||
|
solids. This operation is useful for determining shared material regions,
|
||||||
|
verifying fit, and analyzing overlapping geometries in assemblies.
|
||||||
|
|
||||||
### Arguments
|
### Arguments
|
||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solids` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) | The solids to intersect. | Yes |
|
| `solids` | `[Solid; 2+]` | The solids to intersect. | Yes |
|
||||||
| `tolerance` | [`number`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the intersection operation. | No |
|
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the intersection operation. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid)
|
[`[Solid; 1+]`](/docs/kcl-std/types/std-types-Solid)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
@ -33,7 +38,6 @@ Intersect computes the geometric intersection of multiple solid bodies, returnin
|
|||||||
```kcl
|
```kcl
|
||||||
// Intersect two cubes using the stdlib functions.
|
// Intersect two cubes using the stdlib functions.
|
||||||
|
|
||||||
|
|
||||||
fn cube(center, size) {
|
fn cube(center, size) {
|
||||||
return startSketchOn(XY)
|
return startSketchOn(XY)
|
||||||
|> startProfile(at = [center[0] - size, center[1] - size])
|
|> startProfile(at = [center[0] - size, center[1] - size])
|
||||||
@ -58,7 +62,6 @@ intersectedPart = intersect([part001, part002])
|
|||||||
// NOTE: This will not work when using codemods through the UI.
|
// NOTE: This will not work when using codemods through the UI.
|
||||||
// Codemods will generate the stdlib function call instead.
|
// Codemods will generate the stdlib function call instead.
|
||||||
|
|
||||||
|
|
||||||
fn cube(center, size) {
|
fn cube(center, size) {
|
||||||
return startSketchOn(XY)
|
return startSketchOn(XY)
|
||||||
|> startProfile(at = [center[0] - size, center[1] - size])
|
|> startProfile(at = [center[0] - size, center[1] - size])
|
@ -9,9 +9,9 @@ Union two or more solids into a single solid.
|
|||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
union(
|
union(
|
||||||
@solids: [Solid],
|
@solids: [Solid; 2+],
|
||||||
tolerance?: number,
|
tolerance?: number(Length),
|
||||||
): [Solid]
|
): [Solid; 1+]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -20,12 +20,12 @@ union(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solids` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) | The solids to union. | Yes |
|
| `solids` | `[Solid; 2+]` | The solids to union. | Yes |
|
||||||
| `tolerance` | [`number`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the union operation. | No |
|
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the union operation. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid)
|
[`[Solid; 1+]`](/docs/kcl-std/types/std-types-Solid)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
@ -33,7 +33,6 @@ union(
|
|||||||
```kcl
|
```kcl
|
||||||
// Union two cubes using the stdlib functions.
|
// Union two cubes using the stdlib functions.
|
||||||
|
|
||||||
|
|
||||||
fn cube(center, size) {
|
fn cube(center, size) {
|
||||||
return startSketchOn(XY)
|
return startSketchOn(XY)
|
||||||
|> startProfile(at = [center[0] - size, center[1] - size])
|
|> startProfile(at = [center[0] - size, center[1] - size])
|
||||||
@ -58,7 +57,6 @@ unionedPart = union([part001, part002])
|
|||||||
// NOTE: This will not work when using codemods through the UI.
|
// NOTE: This will not work when using codemods through the UI.
|
||||||
// Codemods will generate the stdlib function call instead.
|
// Codemods will generate the stdlib function call instead.
|
||||||
|
|
||||||
|
|
||||||
fn cube(center, size) {
|
fn cube(center, size) {
|
||||||
return startSketchOn(XY)
|
return startSketchOn(XY)
|
||||||
|> startProfile(at = [center[0] - size, center[1] - size])
|
|> startProfile(at = [center[0] - size, center[1] - size])
|
||||||
@ -84,7 +82,6 @@ unionedPart = part001 + part002
|
|||||||
// NOTE: This will not work when using codemods through the UI.
|
// NOTE: This will not work when using codemods through the UI.
|
||||||
// Codemods will generate the stdlib function call instead.
|
// Codemods will generate the stdlib function call instead.
|
||||||
|
|
||||||
|
|
||||||
fn cube(center, size) {
|
fn cube(center, size) {
|
||||||
return startSketchOn(XY)
|
return startSketchOn(XY)
|
||||||
|> startProfile(at = [center[0] - size, center[1] - size])
|
|> startProfile(at = [center[0] - size, center[1] - size])
|
||||||
@ -99,8 +96,8 @@ part001 = cube(center = [0, 0], size = 10)
|
|||||||
part002 = cube(center = [7, 3], size = 5)
|
part002 = cube(center = [7, 3], size = 5)
|
||||||
|> translate(z = 1)
|
|> translate(z = 1)
|
||||||
|
|
||||||
// This is the equivalent of: union([part001, part002])
|
// This is the equivalent of: union([part001, part002])
|
||||||
// Programmers will understand `|` as a union operation, but mechanical engineers
|
// Programmers will understand `|` as a union operation, but mechanical engineers
|
||||||
// will understand `+`, we made both work.
|
// will understand `+`, we made both work.
|
||||||
unionedPart = part001 | part002
|
unionedPart = part001 | part002
|
||||||
```
|
```
|
@ -14,8 +14,6 @@ mirror2d(
|
|||||||
): Sketch
|
): Sketch
|
||||||
```
|
```
|
||||||
|
|
||||||
Only works on unclosed sketches for now.
|
|
||||||
|
|
||||||
Mirror occurs around a local sketch axis rather than a global axis.
|
Mirror occurs around a local sketch axis rather than a global axis.
|
||||||
|
|
||||||
### Arguments
|
### Arguments
|
||||||
|
@ -9,13 +9,14 @@ layout: manual
|
|||||||
### Functions
|
### Functions
|
||||||
|
|
||||||
* [**std**](/docs/kcl-std/modules/std)
|
* [**std**](/docs/kcl-std/modules/std)
|
||||||
* [`appearance`](/docs/kcl-std/appearance)
|
|
||||||
* [`assert`](/docs/kcl-std/assert)
|
* [`assert`](/docs/kcl-std/assert)
|
||||||
* [`assertIs`](/docs/kcl-std/assertIs)
|
* [`assertIs`](/docs/kcl-std/assertIs)
|
||||||
* [`clone`](/docs/kcl-std/functions/std-clone)
|
* [`clone`](/docs/kcl-std/functions/std-clone)
|
||||||
* [`helix`](/docs/kcl-std/functions/std-helix)
|
* [`helix`](/docs/kcl-std/functions/std-helix)
|
||||||
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
||||||
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
||||||
|
* [**std::appearance**](/docs/kcl-std/modules/std-appearance)
|
||||||
|
* [`appearance::hexString`](/docs/kcl-std/functions/std-appearance-hexString)
|
||||||
* [**std::array**](/docs/kcl-std/modules/std-array)
|
* [**std::array**](/docs/kcl-std/modules/std-array)
|
||||||
* [`map`](/docs/kcl-std/functions/std-array-map)
|
* [`map`](/docs/kcl-std/functions/std-array-map)
|
||||||
* [`pop`](/docs/kcl-std/functions/std-array-pop)
|
* [`pop`](/docs/kcl-std/functions/std-array-pop)
|
||||||
@ -55,17 +56,17 @@ layout: manual
|
|||||||
* [`circleThreePoint`](/docs/kcl-std/circleThreePoint)
|
* [`circleThreePoint`](/docs/kcl-std/circleThreePoint)
|
||||||
* [`close`](/docs/kcl-std/close)
|
* [`close`](/docs/kcl-std/close)
|
||||||
* [`extrude`](/docs/kcl-std/extrude)
|
* [`extrude`](/docs/kcl-std/extrude)
|
||||||
* [`getCommonEdge`](/docs/kcl-std/getCommonEdge)
|
* [`getCommonEdge`](/docs/kcl-std/functions/std-sketch-getCommonEdge)
|
||||||
* [`getNextAdjacentEdge`](/docs/kcl-std/getNextAdjacentEdge)
|
* [`getNextAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getNextAdjacentEdge)
|
||||||
* [`getOppositeEdge`](/docs/kcl-std/getOppositeEdge)
|
* [`getOppositeEdge`](/docs/kcl-std/functions/std-sketch-getOppositeEdge)
|
||||||
* [`getPreviousAdjacentEdge`](/docs/kcl-std/getPreviousAdjacentEdge)
|
* [`getPreviousAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getPreviousAdjacentEdge)
|
||||||
* [`involuteCircular`](/docs/kcl-std/involuteCircular)
|
* [`involuteCircular`](/docs/kcl-std/involuteCircular)
|
||||||
* [`lastSegX`](/docs/kcl-std/lastSegX)
|
* [`lastSegX`](/docs/kcl-std/lastSegX)
|
||||||
* [`lastSegY`](/docs/kcl-std/lastSegY)
|
* [`lastSegY`](/docs/kcl-std/lastSegY)
|
||||||
* [`line`](/docs/kcl-std/line)
|
* [`line`](/docs/kcl-std/line)
|
||||||
* [`loft`](/docs/kcl-std/loft)
|
* [`loft`](/docs/kcl-std/loft)
|
||||||
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
|
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
|
||||||
* [`patternTransform2d`](/docs/kcl-std/patternTransform2d)
|
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
|
||||||
* [`polygon`](/docs/kcl-std/polygon)
|
* [`polygon`](/docs/kcl-std/polygon)
|
||||||
* [`profileStart`](/docs/kcl-std/profileStart)
|
* [`profileStart`](/docs/kcl-std/profileStart)
|
||||||
* [`profileStartX`](/docs/kcl-std/profileStartX)
|
* [`profileStartX`](/docs/kcl-std/profileStartX)
|
||||||
@ -88,21 +89,22 @@ layout: manual
|
|||||||
* [`xLine`](/docs/kcl-std/xLine)
|
* [`xLine`](/docs/kcl-std/xLine)
|
||||||
* [`yLine`](/docs/kcl-std/yLine)
|
* [`yLine`](/docs/kcl-std/yLine)
|
||||||
* [**std::solid**](/docs/kcl-std/modules/std-solid)
|
* [**std::solid**](/docs/kcl-std/modules/std-solid)
|
||||||
|
* [`appearance`](/docs/kcl-std/functions/std-solid-appearance)
|
||||||
* [`chamfer`](/docs/kcl-std/functions/std-solid-chamfer)
|
* [`chamfer`](/docs/kcl-std/functions/std-solid-chamfer)
|
||||||
* [`fillet`](/docs/kcl-std/functions/std-solid-fillet)
|
* [`fillet`](/docs/kcl-std/functions/std-solid-fillet)
|
||||||
* [`hollow`](/docs/kcl-std/functions/std-solid-hollow)
|
* [`hollow`](/docs/kcl-std/functions/std-solid-hollow)
|
||||||
* [`intersect`](/docs/kcl-std/intersect)
|
* [`intersect`](/docs/kcl-std/functions/std-solid-intersect)
|
||||||
* [`patternCircular3d`](/docs/kcl-std/patternCircular3d)
|
* [`patternCircular3d`](/docs/kcl-std/functions/std-solid-patternCircular3d)
|
||||||
* [`patternLinear3d`](/docs/kcl-std/patternLinear3d)
|
* [`patternLinear3d`](/docs/kcl-std/functions/std-solid-patternLinear3d)
|
||||||
* [`patternTransform`](/docs/kcl-std/patternTransform)
|
* [`patternTransform`](/docs/kcl-std/functions/std-solid-patternTransform)
|
||||||
* [`shell`](/docs/kcl-std/functions/std-solid-shell)
|
* [`shell`](/docs/kcl-std/functions/std-solid-shell)
|
||||||
* [`subtract`](/docs/kcl-std/subtract)
|
* [`subtract`](/docs/kcl-std/functions/std-solid-subtract)
|
||||||
* [`union`](/docs/kcl-std/union)
|
* [`union`](/docs/kcl-std/functions/std-solid-union)
|
||||||
* [**std::transform**](/docs/kcl-std/modules/std-transform)
|
* [**std::transform**](/docs/kcl-std/modules/std-transform)
|
||||||
* [`mirror2d`](/docs/kcl-std/functions/std-transform-mirror2d)
|
* [`mirror2d`](/docs/kcl-std/functions/std-transform-mirror2d)
|
||||||
* [`rotate`](/docs/kcl-std/rotate)
|
* [`rotate`](/docs/kcl-std/functions/std-transform-rotate)
|
||||||
* [`scale`](/docs/kcl-std/scale)
|
* [`scale`](/docs/kcl-std/functions/std-transform-scale)
|
||||||
* [`translate`](/docs/kcl-std/translate)
|
* [`translate`](/docs/kcl-std/functions/std-transform-translate)
|
||||||
* [**std::units**](/docs/kcl-std/modules/std-units)
|
* [**std::units**](/docs/kcl-std/modules/std-units)
|
||||||
* [`units::toCentimeters`](/docs/kcl-std/functions/std-units-toCentimeters)
|
* [`units::toCentimeters`](/docs/kcl-std/functions/std-units-toCentimeters)
|
||||||
* [`units::toDegrees`](/docs/kcl-std/functions/std-units-toDegrees)
|
* [`units::toDegrees`](/docs/kcl-std/functions/std-units-toDegrees)
|
||||||
|
16
docs/kcl-std/modules/std-appearance.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "appearance"
|
||||||
|
subtitle: "Module in std"
|
||||||
|
excerpt: ""
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Functions and constants
|
||||||
|
|
||||||
|
* [`appearance::hexString`](/docs/kcl-std/functions/std-appearance-hexString)
|
||||||
|
|
@ -20,17 +20,17 @@ This module contains functions for creating and manipulating sketches, and makin
|
|||||||
* [`circleThreePoint`](/docs/kcl-std/circleThreePoint)
|
* [`circleThreePoint`](/docs/kcl-std/circleThreePoint)
|
||||||
* [`close`](/docs/kcl-std/close)
|
* [`close`](/docs/kcl-std/close)
|
||||||
* [`extrude`](/docs/kcl-std/extrude)
|
* [`extrude`](/docs/kcl-std/extrude)
|
||||||
* [`getCommonEdge`](/docs/kcl-std/getCommonEdge)
|
* [`getCommonEdge`](/docs/kcl-std/functions/std-sketch-getCommonEdge)
|
||||||
* [`getNextAdjacentEdge`](/docs/kcl-std/getNextAdjacentEdge)
|
* [`getNextAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getNextAdjacentEdge)
|
||||||
* [`getOppositeEdge`](/docs/kcl-std/getOppositeEdge)
|
* [`getOppositeEdge`](/docs/kcl-std/functions/std-sketch-getOppositeEdge)
|
||||||
* [`getPreviousAdjacentEdge`](/docs/kcl-std/getPreviousAdjacentEdge)
|
* [`getPreviousAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getPreviousAdjacentEdge)
|
||||||
* [`involuteCircular`](/docs/kcl-std/involuteCircular)
|
* [`involuteCircular`](/docs/kcl-std/involuteCircular)
|
||||||
* [`lastSegX`](/docs/kcl-std/lastSegX)
|
* [`lastSegX`](/docs/kcl-std/lastSegX)
|
||||||
* [`lastSegY`](/docs/kcl-std/lastSegY)
|
* [`lastSegY`](/docs/kcl-std/lastSegY)
|
||||||
* [`line`](/docs/kcl-std/line)
|
* [`line`](/docs/kcl-std/line)
|
||||||
* [`loft`](/docs/kcl-std/loft)
|
* [`loft`](/docs/kcl-std/loft)
|
||||||
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
|
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
|
||||||
* [`patternTransform2d`](/docs/kcl-std/patternTransform2d)
|
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
|
||||||
* [`polygon`](/docs/kcl-std/polygon)
|
* [`polygon`](/docs/kcl-std/polygon)
|
||||||
* [`profileStart`](/docs/kcl-std/profileStart)
|
* [`profileStart`](/docs/kcl-std/profileStart)
|
||||||
* [`profileStartX`](/docs/kcl-std/profileStartX)
|
* [`profileStartX`](/docs/kcl-std/profileStartX)
|
||||||
|
@ -12,14 +12,15 @@ This module contains functions for modifying solids, e.g., by adding a fillet or
|
|||||||
|
|
||||||
## Functions and constants
|
## Functions and constants
|
||||||
|
|
||||||
|
* [`appearance`](/docs/kcl-std/functions/std-solid-appearance)
|
||||||
* [`chamfer`](/docs/kcl-std/functions/std-solid-chamfer)
|
* [`chamfer`](/docs/kcl-std/functions/std-solid-chamfer)
|
||||||
* [`fillet`](/docs/kcl-std/functions/std-solid-fillet)
|
* [`fillet`](/docs/kcl-std/functions/std-solid-fillet)
|
||||||
* [`hollow`](/docs/kcl-std/functions/std-solid-hollow)
|
* [`hollow`](/docs/kcl-std/functions/std-solid-hollow)
|
||||||
* [`intersect`](/docs/kcl-std/intersect)
|
* [`intersect`](/docs/kcl-std/functions/std-solid-intersect)
|
||||||
* [`patternCircular3d`](/docs/kcl-std/patternCircular3d)
|
* [`patternCircular3d`](/docs/kcl-std/functions/std-solid-patternCircular3d)
|
||||||
* [`patternLinear3d`](/docs/kcl-std/patternLinear3d)
|
* [`patternLinear3d`](/docs/kcl-std/functions/std-solid-patternLinear3d)
|
||||||
* [`patternTransform`](/docs/kcl-std/patternTransform)
|
* [`patternTransform`](/docs/kcl-std/functions/std-solid-patternTransform)
|
||||||
* [`shell`](/docs/kcl-std/functions/std-solid-shell)
|
* [`shell`](/docs/kcl-std/functions/std-solid-shell)
|
||||||
* [`subtract`](/docs/kcl-std/subtract)
|
* [`subtract`](/docs/kcl-std/functions/std-solid-subtract)
|
||||||
* [`union`](/docs/kcl-std/union)
|
* [`union`](/docs/kcl-std/functions/std-solid-union)
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ This module contains functions for transforming sketches and solids.
|
|||||||
## Functions and constants
|
## Functions and constants
|
||||||
|
|
||||||
* [`mirror2d`](/docs/kcl-std/functions/std-transform-mirror2d)
|
* [`mirror2d`](/docs/kcl-std/functions/std-transform-mirror2d)
|
||||||
* [`rotate`](/docs/kcl-std/rotate)
|
* [`rotate`](/docs/kcl-std/functions/std-transform-rotate)
|
||||||
* [`scale`](/docs/kcl-std/scale)
|
* [`scale`](/docs/kcl-std/functions/std-transform-scale)
|
||||||
* [`translate`](/docs/kcl-std/translate)
|
* [`translate`](/docs/kcl-std/functions/std-transform-translate)
|
||||||
|
|
||||||
|
@ -11,10 +11,11 @@ Contains frequently used constants, functions for interacting with the KittyCAD
|
|||||||
|
|
||||||
The standard library is organised into modules (listed below), but most things are always available in KCL programs.
|
The standard library is organised into modules (listed below), but most things are always available in KCL programs.
|
||||||
|
|
||||||
You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL guide]().
|
You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL guide](https://zoo.dev/docs/kcl-book/intro.html).
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
|
* [`appearance::appearance`](/docs/kcl-std/modules/std-appearance)
|
||||||
* [`array`](/docs/kcl-std/modules/std-array)
|
* [`array`](/docs/kcl-std/modules/std-array)
|
||||||
* [`math`](/docs/kcl-std/modules/std-math)
|
* [`math`](/docs/kcl-std/modules/std-math)
|
||||||
* [`sketch`](/docs/kcl-std/modules/std-sketch)
|
* [`sketch`](/docs/kcl-std/modules/std-sketch)
|
||||||
@ -35,7 +36,6 @@ You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL gui
|
|||||||
* [`Y`](/docs/kcl-std/consts/std-Y)
|
* [`Y`](/docs/kcl-std/consts/std-Y)
|
||||||
* [`YZ`](/docs/kcl-std/consts/std-YZ)
|
* [`YZ`](/docs/kcl-std/consts/std-YZ)
|
||||||
* [`Z`](/docs/kcl-std/consts/std-Z)
|
* [`Z`](/docs/kcl-std/consts/std-Z)
|
||||||
* [`appearance`](/docs/kcl-std/appearance)
|
|
||||||
* [`assert`](/docs/kcl-std/assert)
|
* [`assert`](/docs/kcl-std/assert)
|
||||||
* [`assertIs`](/docs/kcl-std/assertIs)
|
* [`assertIs`](/docs/kcl-std/assertIs)
|
||||||
* [`clone`](/docs/kcl-std/functions/std-clone)
|
* [`clone`](/docs/kcl-std/functions/std-clone)
|
||||||
|
@ -12,8 +12,8 @@ patternCircular2d(
|
|||||||
@sketchSet: [Sketch],
|
@sketchSet: [Sketch],
|
||||||
instances: number,
|
instances: number,
|
||||||
center: Point2d,
|
center: Point2d,
|
||||||
arcDegrees: number,
|
arcDegrees?: number,
|
||||||
rotateDuplicates: bool,
|
rotateDuplicates?: bool,
|
||||||
useOriginal?: bool,
|
useOriginal?: bool,
|
||||||
): [Sketch]
|
): [Sketch]
|
||||||
```
|
```
|
||||||
@ -27,8 +27,8 @@ patternCircular2d(
|
|||||||
| `sketchSet` | [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch(es) to pattern | Yes |
|
| `sketchSet` | [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch(es) to pattern | Yes |
|
||||||
| `instances` | [`number`](/docs/kcl-std/types/std-types-number) | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | [`number`](/docs/kcl-std/types/std-types-number) | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center about which to make the pattern. This is a 2D vector. | Yes |
|
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center about which to make the pattern. This is a 2D vector. | Yes |
|
||||||
| `arcDegrees` | [`number`](/docs/kcl-std/types/std-types-number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. | Yes |
|
| `arcDegrees` | [`number`](/docs/kcl-std/types/std-types-number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. Defaults to 360. | No |
|
||||||
| `rotateDuplicates` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether or not to rotate the duplicates as they are copied. | Yes |
|
| `rotateDuplicates` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether or not to rotate the duplicates as they are copied. Defaults to true. | No |
|
||||||
| `useOriginal` | [`bool`](/docs/kcl-std/types/std-types-bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. | No |
|
| `useOriginal` | [`bool`](/docs/kcl-std/types/std-types-bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
103964
docs/kcl-std/std.json
@ -13,6 +13,7 @@ tangentialArc(
|
|||||||
endAbsolute?: Point2d,
|
endAbsolute?: Point2d,
|
||||||
end?: Point2d,
|
end?: Point2d,
|
||||||
radius?: number,
|
radius?: number,
|
||||||
|
diameter?: number,
|
||||||
angle?: number,
|
angle?: number,
|
||||||
tag?: TagDeclarator,
|
tag?: TagDeclarator,
|
||||||
): Sketch
|
): Sketch
|
||||||
@ -27,7 +28,8 @@ When using radius and angle, draw a curved line segment along part of an imagina
|
|||||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
||||||
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Which absolute point should this arc go to? Incompatible with `end`, `radius`, and `offset`. | No |
|
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Which absolute point should this arc go to? Incompatible with `end`, `radius`, and `offset`. | No |
|
||||||
| `end` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | How far away (along the X and Y axes) should this arc go? Incompatible with `endAbsolute`, `radius`, and `offset`. | No |
|
| `end` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | How far away (along the X and Y axes) should this arc go? Incompatible with `endAbsolute`, `radius`, and `offset`. | No |
|
||||||
| `radius` | [`number`](/docs/kcl-std/types/std-types-number) | Radius of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute`. | No |
|
| `radius` | [`number`](/docs/kcl-std/types/std-types-number) | Radius of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `diameter`. | No |
|
||||||
|
| `diameter` | [`number`](/docs/kcl-std/types/std-types-number) | Diameter of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `radius`. | No |
|
||||||
| `angle` | [`number`](/docs/kcl-std/types/std-types-number) | Offset of the arc in degrees. `radius` must be given. Incompatible with `end` and `endAbsolute`. | No |
|
| `angle` | [`number`](/docs/kcl-std/types/std-types-number) | Offset of the arc in degrees. `radius` must be given. Incompatible with `end` and `endAbsolute`. | No |
|
||||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this arc | No |
|
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this arc | No |
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import * as fsp from 'fs/promises'
|
|||||||
test.describe('Electron app header tests', () => {
|
test.describe('Electron app header tests', () => {
|
||||||
test(
|
test(
|
||||||
'Open Command Palette button has correct shortcut',
|
'Open Command Palette button has correct shortcut',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page }, testInfo) => {
|
async ({ page }, testInfo) => {
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ test.describe('Electron app header tests', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'User settings has correct shortcut',
|
'User settings has correct shortcut',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page, toolbar }, testInfo) => {
|
async ({ page, toolbar }, testInfo) => {
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
|||||||
test.describe('Authentication tests', () => {
|
test.describe('Authentication tests', () => {
|
||||||
test(
|
test(
|
||||||
`The user can sign out and back in`,
|
`The user can sign out and back in`,
|
||||||
{ tag: ['@electron'] },
|
{ tag: ['@desktop'] },
|
||||||
async ({ page, homePage, signInPage, toolbar, tronApp }) => {
|
async ({ page, homePage, signInPage, toolbar, tronApp }) => {
|
||||||
if (!tronApp) {
|
if (!tronApp) {
|
||||||
fail()
|
fail()
|
||||||
|
@ -78,11 +78,10 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
|
|
||||||
// Delete a character to break the KCL
|
// Delete a character to break the KCL
|
||||||
await editor.openPane()
|
await editor.openPane()
|
||||||
await editor.scrollToText('bracketLeg1Sketch, length = thickness)')
|
await editor.scrollToText('extrude(%, length = width)')
|
||||||
await page
|
await page.getByText('extrude(%, length = width)').click()
|
||||||
.getByText('extrude(bracketLeg1Sketch, length = thickness)')
|
|
||||||
.click()
|
await page.keyboard.press(')')
|
||||||
await page.keyboard.press('Backspace')
|
|
||||||
|
|
||||||
// Ensure that a badge appears on the button
|
// Ensure that a badge appears on the button
|
||||||
await expect(codePaneButtonHolder).toContainText('notification')
|
await expect(codePaneButtonHolder).toContainText('notification')
|
||||||
@ -99,16 +98,11 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
|
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
// Ensure that a badge appears on the button
|
|
||||||
await expect(codePaneButtonHolder).toContainText('notification')
|
|
||||||
// Ensure we have no errors in the gutter.
|
|
||||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
|
||||||
|
|
||||||
// Open the code pane
|
// Open the code pane
|
||||||
await editor.openPane()
|
await editor.openPane()
|
||||||
|
|
||||||
// Go to our problematic code again (missing closing paren!)
|
// Go to our problematic code again
|
||||||
await editor.scrollToText('extrude(bracketLeg1Sketch, length = thickness')
|
await editor.scrollToText('extrude(%, length = w')
|
||||||
|
|
||||||
// Ensure that a badge appears on the button
|
// Ensure that a badge appears on the button
|
||||||
await expect(codePaneButtonHolder).toContainText('notification')
|
await expect(codePaneButtonHolder).toContainText('notification')
|
||||||
@ -235,11 +229,53 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
.first()
|
.first()
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('KCL errors with functions show hints for the entire backtrace', async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
editor,
|
||||||
|
toolbar,
|
||||||
|
}) => {
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
const code = `fn check(@x) {
|
||||||
|
return assert(x, isGreaterThan = 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn middle(@x) {
|
||||||
|
return check(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
middle(1)
|
||||||
|
middle(0)
|
||||||
|
`
|
||||||
|
await test.step('Set the code with a KCL error', async () => {
|
||||||
|
await toolbar.openPane('code')
|
||||||
|
await editor.replaceCode('', code)
|
||||||
|
})
|
||||||
|
// This shows all the diagnostics in a way that doesn't require the mouse
|
||||||
|
// pointer hovering over a coordinate, which would be brittle.
|
||||||
|
await test.step('Open CodeMirror diagnostics list', async () => {
|
||||||
|
// Ensure keyboard focus is in the editor.
|
||||||
|
await page.getByText('fn check(').click()
|
||||||
|
await page.keyboard.press('ControlOrMeta+Shift+M')
|
||||||
|
})
|
||||||
|
await expect(
|
||||||
|
page.getByText(`assert failed: Expected 0 to be greater than 0 but it wasn't
|
||||||
|
check()
|
||||||
|
middle()`)
|
||||||
|
).toBeVisible()
|
||||||
|
// There should be one hint inside middle() and one at the top level.
|
||||||
|
await expect(page.getByText('Part of the error backtrace')).toHaveCount(2)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'Opening multiple panes persists when switching projects',
|
'Opening multiple panes persists when switching projects',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
// Setup multiple projects.
|
// Setup multiple projects.
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
@ -310,7 +346,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'external change of file contents are reflected in editor',
|
'external change of file contents are reflected in editor',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const PROJECT_DIR_NAME = 'lee-was-here'
|
const PROJECT_DIR_NAME = 'lee-was-here'
|
||||||
const { dir: projectsDir } = await context.folderSetupFn(async (dir) => {
|
const { dir: projectsDir } = await context.folderSetupFn(async (dir) => {
|
||||||
|
@ -36,7 +36,10 @@ test.describe('Command bar tests', () => {
|
|||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
// Click the line of code for xLine.
|
// Click the line of code for xLine.
|
||||||
await page.getByText(`close()`).click() // TODO remove this and reinstate // await topHorzSegmentClick()
|
await page.getByText(`startProfile(at = [-10, -10])`).click()
|
||||||
|
|
||||||
|
// Wait for the selection to register (TODO: we need a definitive way to wait for this)
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
|
||||||
await toolbar.extrudeButton.click()
|
await toolbar.extrudeButton.click()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
@ -45,10 +48,10 @@ test.describe('Command bar tests', () => {
|
|||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '',
|
Profiles: '',
|
||||||
Length: '',
|
Length: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'sketches',
|
highlightedHeaderArg: 'Profiles',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -56,7 +59,7 @@ test.describe('Command bar tests', () => {
|
|||||||
stage: 'review',
|
stage: 'review',
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '1 segment',
|
Profiles: '1 profile',
|
||||||
Length: '5',
|
Length: '5',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -286,7 +289,7 @@ test.describe('Command bar tests', () => {
|
|||||||
await cmdBar.cmdOptions.getByText('Extrude').click()
|
await cmdBar.cmdOptions.getByText('Extrude').click()
|
||||||
|
|
||||||
// Assert that we're on the selection step
|
// Assert that we're on the selection step
|
||||||
await expect(page.getByRole('button', { name: 'sketches' })).toBeDisabled()
|
await expect(page.getByRole('button', { name: 'Profiles' })).toBeDisabled()
|
||||||
// Select a face
|
// Select a face
|
||||||
await page.mouse.move(700, 200)
|
await page.mouse.move(700, 200)
|
||||||
await page.mouse.click(700, 200)
|
await page.mouse.click(700, 200)
|
||||||
@ -399,7 +402,6 @@ test.describe('Command bar tests', () => {
|
|||||||
sortBy: 'last-modified-desc',
|
sortBy: 'last-modified-desc',
|
||||||
})
|
})
|
||||||
await page.goto(page.url() + targetURL)
|
await page.goto(page.url() + targetURL)
|
||||||
expect(page.url()).toContain(targetURL)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Submit the command`, async () => {
|
await test.step(`Submit the command`, async () => {
|
||||||
@ -410,7 +412,7 @@ test.describe('Command bar tests', () => {
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Method: '',
|
Method: '',
|
||||||
Name: 'test',
|
Name: 'main.kcl',
|
||||||
Code: '1 line',
|
Code: '1 line',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'method',
|
highlightedHeaderArg: 'method',
|
||||||
@ -421,7 +423,7 @@ test.describe('Command bar tests', () => {
|
|||||||
commandName: 'Import file from URL',
|
commandName: 'Import file from URL',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Method: 'New project',
|
Method: 'New project',
|
||||||
Name: 'test',
|
Name: 'main.kcl',
|
||||||
Code: '1 line',
|
Code: '1 line',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -463,7 +465,6 @@ test.describe('Command bar tests', () => {
|
|||||||
sortBy: 'last-modified-desc',
|
sortBy: 'last-modified-desc',
|
||||||
})
|
})
|
||||||
await page.goto(page.url() + targetURL)
|
await page.goto(page.url() + targetURL)
|
||||||
expect(page.url()).toContain(targetURL)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Submit the command`, async () => {
|
await test.step(`Submit the command`, async () => {
|
||||||
@ -474,7 +475,7 @@ test.describe('Command bar tests', () => {
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Method: '',
|
Method: '',
|
||||||
Name: 'test',
|
Name: 'main.kcl',
|
||||||
Code: '1 line',
|
Code: '1 line',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'method',
|
highlightedHeaderArg: 'method',
|
||||||
@ -487,7 +488,7 @@ test.describe('Command bar tests', () => {
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Method: 'Existing project',
|
Method: 'Existing project',
|
||||||
Name: 'test',
|
Name: 'main.kcl',
|
||||||
ProjectName: '',
|
ProjectName: '',
|
||||||
Code: '1 line',
|
Code: '1 line',
|
||||||
},
|
},
|
||||||
@ -500,7 +501,7 @@ test.describe('Command bar tests', () => {
|
|||||||
headerArguments: {
|
headerArguments: {
|
||||||
Method: 'Existing project',
|
Method: 'Existing project',
|
||||||
ProjectName: 'testProjectDir',
|
ProjectName: 'testProjectDir',
|
||||||
Name: 'test',
|
Name: 'main.kcl',
|
||||||
Code: '1 line',
|
Code: '1 line',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -510,7 +511,7 @@ test.describe('Command bar tests', () => {
|
|||||||
await test.step(`Ensure we created the project and are in the modeling scene`, async () => {
|
await test.step(`Ensure we created the project and are in the modeling scene`, async () => {
|
||||||
await editor.expectEditor.toContain('extrusionDistance = 12')
|
await editor.expectEditor.toContain('extrusionDistance = 12')
|
||||||
await toolbar.openPane('files')
|
await toolbar.openPane('files')
|
||||||
await toolbar.expectFileTreeState(['main.kcl', 'test.kcl'])
|
await toolbar.expectFileTreeState(['main-1.kcl', 'main.kcl'])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -518,7 +519,7 @@ test.describe('Command bar tests', () => {
|
|||||||
`Zoom to fit to shared model on web`,
|
`Zoom to fit to shared model on web`,
|
||||||
{ tag: ['@web'] },
|
{ tag: ['@web'] },
|
||||||
async ({ page, scene }) => {
|
async ({ page, scene }) => {
|
||||||
if (process.env.PLATFORM !== 'web') {
|
if (process.env.TARGET !== 'web') {
|
||||||
// This test is web-only
|
// This test is web-only
|
||||||
// TODO: re-enable on CI as part of a new @web test suite
|
// TODO: re-enable on CI as part of a new @web test suite
|
||||||
return
|
return
|
||||||
@ -661,4 +662,56 @@ c = 3 + a`
|
|||||||
`a = 5b = a * amyParameter001 = ${newValue}c = 3 + a`
|
`a = 5b = a * amyParameter001 = ${newValue}c = 3 + a`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Command palette can be opened via query parameter', async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
await page.goto(`${page.url()}/?cmd=app.theme&groupId=settings`)
|
||||||
|
await homePage.expectState({
|
||||||
|
projectCards: [],
|
||||||
|
sortBy: 'last-modified-desc',
|
||||||
|
})
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
commandName: 'Settings · app · theme',
|
||||||
|
currentArgKey: 'value',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Level: 'user',
|
||||||
|
Value: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'value',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Text-to-CAD command can be closed with escape while in prompt', async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
await homePage.expectState({
|
||||||
|
projectCards: [],
|
||||||
|
sortBy: 'last-modified-desc',
|
||||||
|
})
|
||||||
|
await homePage.textToCadBtn.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
commandName: 'Text-to-CAD Create',
|
||||||
|
currentArgKey: 'prompt',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Method: 'New project',
|
||||||
|
NewProjectName: 'untitled',
|
||||||
|
Prompt: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'prompt',
|
||||||
|
})
|
||||||
|
await page.keyboard.press('Escape')
|
||||||
|
await cmdBar.toBeClosed()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'commandBarClosed',
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -10,7 +10,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'export works on the first try',
|
'export works on the first try',
|
||||||
{ tag: ['@electron', '@macos', '@windows', '@skipLocalEngine'] },
|
{ tag: ['@desktop', '@macos', '@windows', '@skipLocalEngine'] },
|
||||||
async ({ page, context, scene, tronApp, cmdBar }, testInfo) => {
|
async ({ page, context, scene, tronApp, cmdBar }, testInfo) => {
|
||||||
if (!tronApp) {
|
if (!tronApp) {
|
||||||
fail()
|
fail()
|
||||||
|
@ -1001,7 +1001,7 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
|
|||||||
await expect(page.locator('.cm-content')).toHaveText(
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
`@settings(defaultLengthUnit = in)
|
`@settings(defaultLengthUnit = in)
|
||||||
sketch001 = startSketchOn(XZ)
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfile(%, at = [3.14, 12])
|
|> startProfile(%, at = [0, 12])
|
||||||
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1076,7 +1076,7 @@ sketch001 = startSketchOn(XZ)
|
|||||||
await expect(page.locator('.cm-content')).toHaveText(
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
`@settings(defaultLengthUnit = in)
|
`@settings(defaultLengthUnit = in)
|
||||||
sketch001 = startSketchOn(XZ)
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfile(%, at = [3.14, 12])
|
|> startProfile(%, at = [0, 12])
|
||||||
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -1131,6 +1131,8 @@ sketch001 = startSketchOn(XZ)
|
|||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await page.getByText('startProfile(at = [4.61, -14.01])').click()
|
await page.getByText('startProfile(at = [4.61, -14.01])').click()
|
||||||
|
// Wait for the selection to register (TODO: we need a definitive way to wait for this)
|
||||||
|
await page.waitForTimeout(200)
|
||||||
await toolbar.extrudeButton.click()
|
await toolbar.extrudeButton.click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
@ -1138,7 +1140,7 @@ sketch001 = startSketchOn(XZ)
|
|||||||
currentArgKey: 'length',
|
currentArgKey: 'length',
|
||||||
currentArgValue: '5',
|
currentArgValue: '5',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '1 face',
|
Profiles: '1 profile',
|
||||||
Length: '',
|
Length: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'length',
|
||||||
@ -1148,7 +1150,7 @@ sketch001 = startSketchOn(XZ)
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '1 face',
|
Profiles: '1 profile',
|
||||||
Length: '5',
|
Length: '5',
|
||||||
},
|
},
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
@ -1335,7 +1337,7 @@ sketch001 = startSketchOn(XZ)
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`Can import a local OBJ file`,
|
`Can import a local OBJ file`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page, context }, testInfo) => {
|
async ({ page, context }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = join(dir, 'cube')
|
const bracketDir = join(dir, 'cube')
|
||||||
@ -1588,4 +1590,38 @@ sketch001 = startSketchOn(XZ)
|
|||||||
await expect(page.getByTestId('center-rectangle')).toBeVisible()
|
await expect(page.getByTestId('center-rectangle')).toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('syntax errors still show when reopening KCL pane', async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
// Wait for connection, this is especially important for this test, because safeParse is invoked when
|
||||||
|
// connection is established which would interfere with the test if it happened during later steps.
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
// Code with no error
|
||||||
|
await u.codeLocator.fill(`x = 7`)
|
||||||
|
await page.waitForTimeout(200) // allow some time for the error to show potentially
|
||||||
|
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(0)
|
||||||
|
|
||||||
|
// Code with error
|
||||||
|
await u.codeLocator.fill(`x 7`)
|
||||||
|
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(1)
|
||||||
|
|
||||||
|
// Close and reopen KCL code panel
|
||||||
|
await u.closeKclCodePanel()
|
||||||
|
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(0) // error disappears on close
|
||||||
|
await u.openKclCodePanel()
|
||||||
|
|
||||||
|
// Verify error is still visible
|
||||||
|
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -57,7 +57,7 @@ sketch003 = startSketchOn(plane001)
|
|||||||
test.describe('Feature Tree pane', () => {
|
test.describe('Feature Tree pane', () => {
|
||||||
test(
|
test(
|
||||||
'User can go to definition and go to function definition',
|
'User can go to definition and go to function definition',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, homePage, scene, editor, toolbar, cmdBar, page }) => {
|
async ({ context, homePage, scene, editor, toolbar, cmdBar, page }) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = join(dir, 'test-sample')
|
const bracketDir = join(dir, 'test-sample')
|
||||||
@ -150,7 +150,7 @@ test.describe('Feature Tree pane', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`User can edit sketch (but not on offset plane yet) from the feature tree`,
|
`User can edit sketch (but not on offset plane yet) from the feature tree`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, homePage, scene, editor, toolbar, page }) => {
|
async ({ context, homePage, scene, editor, toolbar, page }) => {
|
||||||
await context.addInitScript((initialCode) => {
|
await context.addInitScript((initialCode) => {
|
||||||
localStorage.setItem('persistCode', initialCode)
|
localStorage.setItem('persistCode', initialCode)
|
||||||
|
@ -13,7 +13,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
|||||||
test.describe('integrations tests', () => {
|
test.describe('integrations tests', () => {
|
||||||
test(
|
test(
|
||||||
'Creating a new file or switching file while in sketchMode should exit sketchMode',
|
'Creating a new file or switching file while in sketchMode should exit sketchMode',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page, context, homePage, scene, editor, toolbar, cmdBar }) => {
|
async ({ page, context, homePage, scene, editor, toolbar, cmdBar }) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = join(dir, 'test-sample')
|
const bracketDir = join(dir, 'test-sample')
|
||||||
@ -100,7 +100,7 @@ test.describe('when using the file tree to', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`rename ${fromFile} to ${toFile}, and doesn't crash on reload and settings load`,
|
`rename ${fromFile} to ${toFile}, and doesn't crash on reload and settings load`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page }, testInfo) => {
|
async ({ page }, testInfo) => {
|
||||||
const { panesOpen, pasteCodeInEditor, renameFile, editorTextMatches } =
|
const { panesOpen, pasteCodeInEditor, renameFile, editorTextMatches } =
|
||||||
await getUtils(page, test)
|
await getUtils(page, test)
|
||||||
@ -142,7 +142,7 @@ test.describe('when using the file tree to', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`create many new files of the same name, incrementing their names`,
|
`create many new files of the same name, incrementing their names`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page }, testInfo) => {
|
async ({ page }, testInfo) => {
|
||||||
const { panesOpen, createNewFile } = await getUtils(page, test)
|
const { panesOpen, createNewFile } = await getUtils(page, test)
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ test.describe('when using the file tree to', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'create a new file with the same name as an existing file cancels the operation',
|
'create a new file with the same name as an existing file cancels the operation',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, homePage, scene, editor, toolbar }, testInfo) => {
|
async ({ context, page, homePage, scene, editor, toolbar }, testInfo) => {
|
||||||
const projectName = 'cube'
|
const projectName = 'cube'
|
||||||
const mainFile = 'main.kcl'
|
const mainFile = 'main.kcl'
|
||||||
@ -238,9 +238,29 @@ test.describe('when using the file tree to', () => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test(
|
||||||
|
`create new folders and that doesn't trigger a navigation`,
|
||||||
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||||
|
async ({ page, homePage, scene, toolbar, cmdBar }) => {
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
await toolbar.openPane('files')
|
||||||
|
const { createNewFolder } = await getUtils(page, test)
|
||||||
|
|
||||||
|
await createNewFolder('folder')
|
||||||
|
|
||||||
|
await createNewFolder('folder.kcl')
|
||||||
|
|
||||||
|
await test.step(`Postcondition: folders are created and we didn't navigate`, async () => {
|
||||||
|
await toolbar.expectFileTreeState(['folder', 'folder.kcl', 'main.kcl'])
|
||||||
|
await expect(toolbar.fileName).toHaveText('main.kcl')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'deleting all files recreates a default main.kcl with no code',
|
'deleting all files recreates a default main.kcl with no code',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page }, testInfo) => {
|
async ({ page }, testInfo) => {
|
||||||
const { panesOpen, pasteCodeInEditor, deleteFile, editorTextMatches } =
|
const { panesOpen, pasteCodeInEditor, deleteFile, editorTextMatches } =
|
||||||
await getUtils(page, test)
|
await getUtils(page, test)
|
||||||
@ -271,7 +291,7 @@ test.describe('when using the file tree to', () => {
|
|||||||
test(
|
test(
|
||||||
'loading small file, then large, then back to small',
|
'loading small file, then large, then back to small',
|
||||||
{
|
{
|
||||||
tag: '@electron',
|
tag: '@desktop',
|
||||||
},
|
},
|
||||||
async ({ page }, testInfo) => {
|
async ({ page }, testInfo) => {
|
||||||
const {
|
const {
|
||||||
@ -341,7 +361,7 @@ test.describe('when using the file tree to', () => {
|
|||||||
test.describe('Renaming in the file tree', () => {
|
test.describe('Renaming in the file tree', () => {
|
||||||
test(
|
test(
|
||||||
'A file you have open',
|
'A file you have open',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const { dir } = await context.folderSetupFn(async (dir) => {
|
const { dir } = await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||||
@ -430,7 +450,7 @@ test.describe('Renaming in the file tree', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'A file you do not have open',
|
'A file you do not have open',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const { dir } = await context.folderSetupFn(async (dir) => {
|
const { dir } = await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||||
@ -516,7 +536,7 @@ test.describe('Renaming in the file tree', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`A folder you're not inside`,
|
`A folder you're not inside`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const { dir } = await context.folderSetupFn(async (dir) => {
|
const { dir } = await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||||
@ -598,7 +618,7 @@ test.describe('Renaming in the file tree', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`A folder you are inside`,
|
`A folder you are inside`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page, context }, testInfo) => {
|
async ({ page, context }, testInfo) => {
|
||||||
const { dir } = await context.folderSetupFn(async (dir) => {
|
const { dir } = await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||||
@ -701,7 +721,7 @@ test.describe('Renaming in the file tree', () => {
|
|||||||
test.describe('Deleting items from the file pane', () => {
|
test.describe('Deleting items from the file pane', () => {
|
||||||
test(
|
test(
|
||||||
`delete file when main.kcl exists, navigate to main.kcl`,
|
`delete file when main.kcl exists, navigate to main.kcl`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page, context }, testInfo) => {
|
async ({ page, context }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const testDir = join(dir, 'testProject')
|
const testDir = join(dir, 'testProject')
|
||||||
@ -766,7 +786,7 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`Delete folder we are not in, don't navigate`,
|
`Delete folder we are not in, don't navigate`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||||
@ -820,7 +840,7 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`Delete folder we are in, navigate to main.kcl`,
|
`Delete folder we are in, navigate to main.kcl`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||||
@ -886,7 +906,7 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
// Copied from tests above.
|
// Copied from tests above.
|
||||||
test(
|
test(
|
||||||
`external deletion of project navigates back home`,
|
`external deletion of project navigates back home`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const TEST_PROJECT_NAME = 'Test Project'
|
const TEST_PROJECT_NAME = 'Test Project'
|
||||||
const { dir: projectsDirName } = await context.folderSetupFn(
|
const { dir: projectsDirName } = await context.folderSetupFn(
|
||||||
@ -950,7 +970,7 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
// Similar to the above
|
// Similar to the above
|
||||||
test(
|
test(
|
||||||
`external deletion of file in sub-directory updates the file tree and recreates it on code editor typing`,
|
`external deletion of file in sub-directory updates the file tree and recreates it on code editor typing`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const TEST_PROJECT_NAME = 'Test Project'
|
const TEST_PROJECT_NAME = 'Test Project'
|
||||||
const { dir: projectsDirName } = await context.folderSetupFn(
|
const { dir: projectsDirName } = await context.folderSetupFn(
|
||||||
@ -1025,7 +1045,7 @@ test.describe('Deleting items from the file pane', () => {
|
|||||||
test.describe('Undo and redo do not keep history when navigating between files', () => {
|
test.describe('Undo and redo do not keep history when navigating between files', () => {
|
||||||
test(
|
test(
|
||||||
`open a file, change something, open a different file, hitting undo should do nothing`,
|
`open a file, change something, open a different file, hitting undo should do nothing`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const testDir = join(dir, 'testProject')
|
const testDir = join(dir, 'testProject')
|
||||||
@ -1092,7 +1112,7 @@ test.describe('Undo and redo do not keep history when navigating between files',
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`open a file, change something, undo it, open a different file, hitting redo should do nothing`,
|
`open a file, change something, undo it, open a different file, hitting redo should do nothing`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const testDir = join(dir, 'testProject')
|
const testDir = join(dir, 'testProject')
|
||||||
@ -1192,7 +1212,7 @@ test.describe('Undo and redo do not keep history when navigating between files',
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`cloned file has an incremented name and same contents`,
|
`cloned file has an incremented name and same contents`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page, context, homePage }, testInfo) => {
|
async ({ page, context, homePage }, testInfo) => {
|
||||||
const { panesOpen, cloneFile } = await getUtils(page, test)
|
const { panesOpen, cloneFile } = await getUtils(page, test)
|
||||||
|
|
||||||
|
@ -105,14 +105,19 @@ export class CmdBarFixture {
|
|||||||
expectState = async (expected: CmdBarSerialised) => {
|
expectState = async (expected: CmdBarSerialised) => {
|
||||||
return expect.poll(() => this._serialiseCmdBar()).toEqual(expected)
|
return expect.poll(() => this._serialiseCmdBar()).toEqual(expected)
|
||||||
}
|
}
|
||||||
/** The method will use buttons OR press enter randomly to progress the cmdbar,
|
/**
|
||||||
* this could have unexpected results depending on what's focused
|
* This method is used to progress the command bar to the next step, defaulting to clicking the next button.
|
||||||
*
|
* Optionally, with the `shouldUseKeyboard` parameter, it will hit `Enter` to progress.
|
||||||
* TODO: This method assumes the user has a valid input to the current stage,
|
* * TODO: This method assumes the user has a valid input to the current stage,
|
||||||
* and assumes we are past the `pickCommand` step.
|
* and assumes we are past the `pickCommand` step.
|
||||||
*/
|
*/
|
||||||
progressCmdBar = async (shouldFuzzProgressMethod = true) => {
|
progressCmdBar = async (shouldUseKeyboard = false) => {
|
||||||
await this.page.waitForTimeout(2000)
|
await this.page.waitForTimeout(2000)
|
||||||
|
if (shouldUseKeyboard) {
|
||||||
|
await this.page.keyboard.press('Enter')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const arrowButton = this.page.getByRole('button', {
|
const arrowButton = this.page.getByRole('button', {
|
||||||
name: 'arrow right Continue',
|
name: 'arrow right Continue',
|
||||||
})
|
})
|
||||||
@ -146,9 +151,7 @@ export class CmdBarFixture {
|
|||||||
await this.cmdBarOpenBtn.click()
|
await this.cmdBarOpenBtn.click()
|
||||||
await expect(this.page.getByPlaceholder('Search commands')).toBeVisible()
|
await expect(this.page.getByPlaceholder('Search commands')).toBeVisible()
|
||||||
if (selectCmd === 'promptToEdit') {
|
if (selectCmd === 'promptToEdit') {
|
||||||
const promptEditCommand = this.page.getByText(
|
const promptEditCommand = this.selectOption({ name: 'Text-to-CAD Edit' })
|
||||||
'Use Zoo AI to edit your parts and code.'
|
|
||||||
)
|
|
||||||
await expect(promptEditCommand.first()).toBeVisible()
|
await expect(promptEditCommand.first()).toBeVisible()
|
||||||
await promptEditCommand.first().scrollIntoViewIfNeeded()
|
await promptEditCommand.first().scrollIntoViewIfNeeded()
|
||||||
await promptEditCommand.first().click()
|
await promptEditCommand.first().click()
|
||||||
@ -310,6 +313,11 @@ export class CmdBarFixture {
|
|||||||
await expect(this.cmdBarElement).toBeVisible({ timeout: 10_000 })
|
await expect(this.cmdBarElement).toBeVisible({ timeout: 10_000 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async toBeClosed() {
|
||||||
|
// Check that the command bar is closed
|
||||||
|
await expect(this.cmdBarElement).not.toBeVisible({ timeout: 10_000 })
|
||||||
|
}
|
||||||
|
|
||||||
async expectArgValue(value: string) {
|
async expectArgValue(value: string) {
|
||||||
// Check the placeholder project name exists
|
// Check the placeholder project name exists
|
||||||
const actualArgument = await this.cmdBarElement
|
const actualArgument = await this.cmdBarElement
|
||||||
|
@ -394,7 +394,7 @@ const fixturesBasedOnProcessEnvPlatform = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.PLATFORM === 'web') {
|
if (process.env.TARGET === 'web') {
|
||||||
Object.assign(fixturesBasedOnProcessEnvPlatform, fixturesForWeb)
|
Object.assign(fixturesBasedOnProcessEnvPlatform, fixturesForWeb)
|
||||||
} else {
|
} else {
|
||||||
Object.assign(fixturesBasedOnProcessEnvPlatform, fixturesForElectron)
|
Object.assign(fixturesBasedOnProcessEnvPlatform, fixturesForElectron)
|
||||||
|
@ -26,6 +26,7 @@ export class HomePageFixture {
|
|||||||
sortByNameBtn!: Locator
|
sortByNameBtn!: Locator
|
||||||
appHeader!: Locator
|
appHeader!: Locator
|
||||||
tutorialBtn!: Locator
|
tutorialBtn!: Locator
|
||||||
|
textToCadBtn!: Locator
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page
|
this.page = page
|
||||||
@ -47,6 +48,7 @@ export class HomePageFixture {
|
|||||||
this.sortByNameBtn = this.page.getByTestId('home-sort-by-name')
|
this.sortByNameBtn = this.page.getByTestId('home-sort-by-name')
|
||||||
this.appHeader = this.page.getByTestId('app-header')
|
this.appHeader = this.page.getByTestId('app-header')
|
||||||
this.tutorialBtn = this.page.getByTestId('home-tutorial-button')
|
this.tutorialBtn = this.page.getByTestId('home-tutorial-button')
|
||||||
|
this.textToCadBtn = this.page.getByTestId('home-text-to-cad')
|
||||||
}
|
}
|
||||||
|
|
||||||
private _serialiseSortBy = async (): Promise<
|
private _serialiseSortBy = async (): Promise<
|
||||||
@ -121,11 +123,13 @@ export class HomePageFixture {
|
|||||||
await projectCard.click()
|
await projectCard.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
goToModelingScene = async (name: string = 'testDefault') => {
|
/** Returns the project name in case caller has used the default and needs it */
|
||||||
|
goToModelingScene = async (name = 'testDefault') => {
|
||||||
// On web this is a no-op. There is no project view.
|
// On web this is a no-op. There is no project view.
|
||||||
if (process.env.PLATFORM === 'web') return
|
if (process.env.TARGET === 'web') return ''
|
||||||
|
|
||||||
await this.createAndGoToProject(name)
|
await this.createAndGoToProject(name)
|
||||||
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
isNativeFileMenuCreated = async () => {
|
isNativeFileMenuCreated = async () => {
|
||||||
|
@ -5,7 +5,7 @@ import * as fsp from 'fs/promises'
|
|||||||
test.describe('Import UI tests', () => {
|
test.describe('Import UI tests', () => {
|
||||||
test(
|
test(
|
||||||
'shows toast when trying to sketch on imported face, and hovering over imported geometry should NOT highlight any code',
|
'shows toast when trying to sketch on imported face, and hovering over imported geometry should NOT highlight any code',
|
||||||
{ tag: ['@electron', '@macos', '@windows'] },
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||||
async ({ context, page, homePage, toolbar, scene, editor, cmdBar }) => {
|
async ({ context, page, homePage, toolbar, scene, editor, cmdBar }) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const projectDir = path.join(dir, 'import-test')
|
const projectDir = path.join(dir, 'import-test')
|
||||||
|
@ -61,6 +61,7 @@ class MyAPIReporter implements Reporter {
|
|||||||
const payload = {
|
const payload = {
|
||||||
// Required information
|
// Required information
|
||||||
project: 'https://github.com/KittyCAD/modeling-app',
|
project: 'https://github.com/KittyCAD/modeling-app',
|
||||||
|
suite: process.env.CI_SUITE || 'e2e',
|
||||||
branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
|
branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
|
||||||
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
|
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
|
||||||
test: test.titlePath().slice(2).join(' › '),
|
test: test.titlePath().slice(2).join(' › '),
|
||||||
|
@ -6,7 +6,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'When machine-api server not found butt is disabled and shows the reason',
|
'When machine-api server not found butt is disabled and shows the reason',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = join(dir, 'bracket')
|
const bracketDir = join(dir, 'bracket')
|
||||||
@ -43,7 +43,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'When machine-api server not found home screen & project status shows the reason',
|
'When machine-api server not found home screen & project status shows the reason',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = join(dir, 'bracket')
|
const bracketDir = join(dir, 'bracket')
|
||||||
|
@ -13,7 +13,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
|||||||
*/
|
*/
|
||||||
test.describe(
|
test.describe(
|
||||||
'Native file menu',
|
'Native file menu',
|
||||||
{ tag: ['@electron', '@macos', '@windows'] },
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||||
() => {
|
() => {
|
||||||
test('Home page', async ({ tronApp, cmdBar, page, homePage }) => {
|
test('Home page', async ({ tronApp, cmdBar, page, homePage }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
@ -197,18 +197,6 @@ test.describe(
|
|||||||
await clickElectronNativeMenuById(tronApp, 'File.Export current part')
|
await clickElectronNativeMenuById(tronApp, 'File.Export current part')
|
||||||
await cmdBar.expectCommandName('Export')
|
await cmdBar.expectCommandName('Export')
|
||||||
})
|
})
|
||||||
await test.step('Modeling.File.Share part via Zoo link', async () => {
|
|
||||||
await page.waitForTimeout(250)
|
|
||||||
await clickElectronNativeMenuById(
|
|
||||||
tronApp,
|
|
||||||
'File.Share part via Zoo link'
|
|
||||||
)
|
|
||||||
const textToCheck =
|
|
||||||
'Link copied to clipboard. Anyone who clicks this link will get a copy of this file. Share carefully!'
|
|
||||||
// Check if text appears anywhere in the page
|
|
||||||
const isTextVisible = page.getByText(textToCheck)
|
|
||||||
await expect(isTextVisible).toBeVisible({ timeout: 10000 })
|
|
||||||
})
|
|
||||||
await test.step('Modeling.File.Preferences.Project settings', async () => {
|
await test.step('Modeling.File.Preferences.Project settings', async () => {
|
||||||
await page.waitForTimeout(250)
|
await page.waitForTimeout(250)
|
||||||
await clickElectronNativeMenuById(
|
await clickElectronNativeMenuById(
|
||||||
@ -264,7 +252,7 @@ test.describe(
|
|||||||
tronApp,
|
tronApp,
|
||||||
'Edit.Modify with Zoo Text-To-CAD'
|
'Edit.Modify with Zoo Text-To-CAD'
|
||||||
)
|
)
|
||||||
await cmdBar.expectCommandName('Prompt-to-edit')
|
await cmdBar.expectCommandName('Text-to-CAD Edit')
|
||||||
})
|
})
|
||||||
await test.step('Modeling.Edit.Edit parameter', async () => {
|
await test.step('Modeling.Edit.Edit parameter', async () => {
|
||||||
await page.waitForTimeout(250)
|
await page.waitForTimeout(250)
|
||||||
@ -530,7 +518,7 @@ test.describe(
|
|||||||
'Design.Create with Zoo Text-To-CAD'
|
'Design.Create with Zoo Text-To-CAD'
|
||||||
)
|
)
|
||||||
await cmdBar.toBeOpened()
|
await cmdBar.toBeOpened()
|
||||||
await cmdBar.expectCommandName('Text to CAD')
|
await cmdBar.expectCommandName('Text-to-CAD Create')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Modeling.Design.Modify with Zoo Text-To-CAD', async () => {
|
await test.step('Modeling.Design.Modify with Zoo Text-To-CAD', async () => {
|
||||||
@ -540,7 +528,7 @@ test.describe(
|
|||||||
'Design.Modify with Zoo Text-To-CAD'
|
'Design.Modify with Zoo Text-To-CAD'
|
||||||
)
|
)
|
||||||
await cmdBar.toBeOpened()
|
await cmdBar.toBeOpened()
|
||||||
await cmdBar.expectCommandName('Prompt-to-edit')
|
await cmdBar.expectCommandName('Text-to-CAD Edit')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Modeling.Help.KCL code samples', async () => {
|
await test.step('Modeling.Help.KCL code samples', async () => {
|
||||||
|
@ -6,7 +6,6 @@ test.describe('Onboarding tests', () => {
|
|||||||
homePage,
|
homePage,
|
||||||
toolbar,
|
toolbar,
|
||||||
editor,
|
editor,
|
||||||
scene,
|
|
||||||
tronApp,
|
tronApp,
|
||||||
}) => {
|
}) => {
|
||||||
if (!tronApp) {
|
if (!tronApp) {
|
||||||
@ -62,7 +61,6 @@ test.describe('Onboarding tests', () => {
|
|||||||
await editor.expectEditor.toContain('@settings(defaultLengthUnit = in)', {
|
await editor.expectEditor.toContain('@settings(defaultLengthUnit = in)', {
|
||||||
shouldNormalise: true,
|
shouldNormalise: true,
|
||||||
})
|
})
|
||||||
await scene.connectionEstablished()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Go home and verify we still see the tutorial button, then begin it.', async () => {
|
await test.step('Go home and verify we still see the tutorial button, then begin it.', async () => {
|
||||||
@ -132,9 +130,7 @@ test.describe('Onboarding tests', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Dismiss the onboarding', async () => {
|
await test.step('Dismiss the onboarding', async () => {
|
||||||
await postDismissToast.waitFor({ state: 'hidden' })
|
|
||||||
await page.keyboard.press('Escape')
|
await page.keyboard.press('Escape')
|
||||||
await expect(postDismissToast).toBeVisible()
|
|
||||||
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
||||||
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
||||||
})
|
})
|
||||||
@ -162,13 +158,10 @@ test.describe('Onboarding tests', () => {
|
|||||||
await test.step('Gets to the onboarding start', async () => {
|
await test.step('Gets to the onboarding start', async () => {
|
||||||
await expect(toolbar.projectName).toContainText('tutorial-project')
|
await expect(toolbar.projectName).toContainText('tutorial-project')
|
||||||
await expect(tutorialWelcomeHeading).toBeVisible()
|
await expect(tutorialWelcomeHeading).toBeVisible()
|
||||||
await scene.connectionEstablished()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Dismiss the onboarding', async () => {
|
await test.step('Dismiss the onboarding', async () => {
|
||||||
await postDismissToast.waitFor({ state: 'hidden' })
|
|
||||||
await page.keyboard.press('Escape')
|
await page.keyboard.press('Escape')
|
||||||
await expect(postDismissToast).toBeVisible()
|
|
||||||
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
||||||
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
||||||
})
|
})
|
||||||
|
@ -43,7 +43,7 @@ async function insertPartIntoAssembly(
|
|||||||
test.describe('Point-and-click assemblies tests', () => {
|
test.describe('Point-and-click assemblies tests', () => {
|
||||||
test(
|
test(
|
||||||
`Insert kcl parts into assembly as whole module import`,
|
`Insert kcl parts into assembly as whole module import`,
|
||||||
{ tag: ['@electron', '@macos', '@windows'] },
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||||
async ({
|
async ({
|
||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
@ -70,22 +70,28 @@ test.describe('Point-and-click assemblies tests', () => {
|
|||||||
await test.step('Setup parts and expect empty assembly scene', async () => {
|
await test.step('Setup parts and expect empty assembly scene', async () => {
|
||||||
const projectName = 'assembly'
|
const projectName = 'assembly'
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, projectName)
|
const projDir = path.join(dir, projectName)
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
const nestedProjDir = path.join(dir, projectName, 'nested', 'twice')
|
||||||
|
await fsp.mkdir(projDir, { recursive: true })
|
||||||
|
await fsp.mkdir(nestedProjDir, { recursive: true })
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
fsp.copyFile(
|
fsp.copyFile(
|
||||||
executorInputPath('cylinder.kcl'),
|
executorInputPath('cylinder.kcl'),
|
||||||
path.join(bracketDir, 'cylinder.kcl')
|
path.join(projDir, 'cylinder.kcl')
|
||||||
|
),
|
||||||
|
fsp.copyFile(
|
||||||
|
executorInputPath('cylinder.kcl'),
|
||||||
|
path.join(nestedProjDir, 'main.kcl')
|
||||||
),
|
),
|
||||||
fsp.copyFile(
|
fsp.copyFile(
|
||||||
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
|
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
|
||||||
path.join(bracketDir, 'bracket.kcl')
|
path.join(projDir, 'bracket.kcl')
|
||||||
),
|
),
|
||||||
fsp.copyFile(
|
fsp.copyFile(
|
||||||
testsInputPath('cube.step'),
|
testsInputPath('cube.step'),
|
||||||
path.join(bracketDir, 'cube.step')
|
path.join(projDir, 'cube.step')
|
||||||
),
|
),
|
||||||
fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''),
|
fsp.writeFile(path.join(projDir, 'main.kcl'), ''),
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
@ -167,13 +173,32 @@ test.describe('Point-and-click assemblies tests', () => {
|
|||||||
await expect(
|
await expect(
|
||||||
page.getByText('This file is already imported')
|
page.getByText('This file is already imported')
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
|
await cmdBar.closeCmdBar()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Insert a nested kcl part', async () => {
|
||||||
|
await insertPartIntoAssembly(
|
||||||
|
'nested/twice/main.kcl',
|
||||||
|
'main',
|
||||||
|
toolbar,
|
||||||
|
cmdBar,
|
||||||
|
page
|
||||||
|
)
|
||||||
|
await toolbar.openPane('code')
|
||||||
|
await page.waitForTimeout(10000)
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
`
|
||||||
|
import "nested/twice/main.kcl" as main
|
||||||
|
`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
test(
|
test(
|
||||||
`Can still translate, rotate, and delete inserted parts even with non standard code`,
|
`Can still translate, rotate, and delete inserted parts even with non standard code`,
|
||||||
{ tag: ['@electron', '@macos', '@windows'] },
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||||
async ({
|
async ({
|
||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
@ -369,7 +394,7 @@ test.describe('Point-and-click assemblies tests', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`Insert the bracket part into an assembly and transform it`,
|
`Insert the bracket part into an assembly and transform it`,
|
||||||
{ tag: ['@electron', '@macos', '@windows'] },
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||||
async ({
|
async ({
|
||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
@ -560,7 +585,7 @@ test.describe('Point-and-click assemblies tests', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`Insert foreign parts into assembly and delete them`,
|
`Insert foreign parts into assembly and delete them`,
|
||||||
{ tag: ['@electron', '@macos', '@windows'] },
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||||
async ({
|
async ({
|
||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
@ -711,7 +736,7 @@ test.describe('Point-and-click assemblies tests', () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'Assembly gets reexecuted when imported models are updated externally',
|
'Assembly gets reexecuted when imported models are updated externally',
|
||||||
{ tag: ['@electron', '@macos', '@windows'] },
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||||
async ({ context, page, homePage, scene, toolbar, cmdBar, tronApp }) => {
|
async ({ context, page, homePage, scene, toolbar, cmdBar, tronApp }) => {
|
||||||
if (!tronApp) {
|
if (!tronApp) {
|
||||||
fail()
|
fail()
|
||||||
@ -801,7 +826,7 @@ foreign
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`Point-and-click clone`,
|
`Point-and-click clone`,
|
||||||
{ tag: ['@electron', '@macos', '@windows'] },
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||||
async ({
|
async ({
|
||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
|
@ -78,8 +78,8 @@ test.describe('Point-and-click tests', () => {
|
|||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: { Sketches: '', Length: '' },
|
headerArguments: { Profiles: '', Length: '' },
|
||||||
highlightedHeaderArg: 'sketches',
|
highlightedHeaderArg: 'Profiles',
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -87,7 +87,7 @@ test.describe('Point-and-click tests', () => {
|
|||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'length',
|
currentArgKey: 'length',
|
||||||
currentArgValue: '5',
|
currentArgValue: '5',
|
||||||
headerArguments: { Sketches: '1 face', Length: '' },
|
headerArguments: { Profiles: '1 profile', Length: '' },
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'length',
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
})
|
})
|
||||||
@ -98,7 +98,7 @@ test.describe('Point-and-click tests', () => {
|
|||||||
|
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: { Sketches: '1 face', Length: '5' },
|
headerArguments: { Profiles: '1 profile', Length: '5' },
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -1634,15 +1634,15 @@ sketch002 = startSketchOn(plane001)
|
|||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: { Sketches: '' },
|
headerArguments: { Profiles: '' },
|
||||||
highlightedHeaderArg: 'sketches',
|
highlightedHeaderArg: 'Profiles',
|
||||||
commandName: 'Loft',
|
commandName: 'Loft',
|
||||||
})
|
})
|
||||||
await selectSketches()
|
await selectSketches()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: { Sketches: '2 faces' },
|
headerArguments: { Profiles: '2 profiles' },
|
||||||
commandName: 'Loft',
|
commandName: 'Loft',
|
||||||
})
|
})
|
||||||
await cmdBar.submit()
|
await cmdBar.submit()
|
||||||
@ -1658,14 +1658,14 @@ sketch002 = startSketchOn(plane001)
|
|||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: { Sketches: '' },
|
headerArguments: { Profiles: '' },
|
||||||
highlightedHeaderArg: 'sketches',
|
highlightedHeaderArg: 'Profiles',
|
||||||
commandName: 'Loft',
|
commandName: 'Loft',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: { Sketches: '2 faces' },
|
headerArguments: { Profiles: '2 profiles' },
|
||||||
commandName: 'Loft',
|
commandName: 'Loft',
|
||||||
})
|
})
|
||||||
await cmdBar.submit()
|
await cmdBar.submit()
|
||||||
@ -1830,10 +1830,10 @@ sketch002 = startSketchOn(XZ)
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Sketches: '',
|
Profiles: '',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'sketches',
|
highlightedHeaderArg: 'Profiles',
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
})
|
})
|
||||||
await clickOnSketch1()
|
await clickOnSketch1()
|
||||||
@ -1844,7 +1844,7 @@ sketch002 = startSketchOn(XZ)
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Sketches: '1 face',
|
Profiles: '1 profile',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'path',
|
highlightedHeaderArg: 'path',
|
||||||
@ -1857,7 +1857,7 @@ sketch002 = startSketchOn(XZ)
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Sketches: '1 face',
|
Profiles: '1 profile',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'path',
|
highlightedHeaderArg: 'path',
|
||||||
@ -1867,13 +1867,17 @@ sketch002 = startSketchOn(XZ)
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '1 face',
|
Profiles: '1 profile',
|
||||||
Path: '1 segment',
|
Path: '1 segment',
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
},
|
},
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
// Confirm we can submit from the review step with just `Enter`
|
||||||
|
await cmdBar.progressCmdBar(true)
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'commandBarClosed',
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||||
@ -1968,10 +1972,10 @@ profile001 = ${circleCode}`
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Sketches: '',
|
Profiles: '',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'sketches',
|
highlightedHeaderArg: 'Profiles',
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
})
|
})
|
||||||
await editor.scrollToText(circleCode)
|
await editor.scrollToText(circleCode)
|
||||||
@ -1983,7 +1987,7 @@ profile001 = ${circleCode}`
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Sketches: '1 face',
|
Profiles: '1 profile',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'path',
|
highlightedHeaderArg: 'path',
|
||||||
@ -1997,7 +2001,7 @@ profile001 = ${circleCode}`
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Sketches: '1 face',
|
Profiles: '1 profile',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'path',
|
highlightedHeaderArg: 'path',
|
||||||
@ -2007,13 +2011,13 @@ profile001 = ${circleCode}`
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '1 face',
|
Profiles: '1 profile',
|
||||||
Path: '1 helix',
|
Path: '1 helix',
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
},
|
},
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar(true)
|
||||||
await editor.expectEditor.toContain(sweepDeclaration)
|
await editor.expectEditor.toContain(sweepDeclaration)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -3691,7 +3695,7 @@ tag=$rectangleSegmentC002,
|
|||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// select line of code
|
// select line of code
|
||||||
const codeToSelection = `segAng(rectangleSegmentA002) - 90,`
|
const codeToSelection = `startProfile(at = [-66.77, 84.81])`
|
||||||
// revolve
|
// revolve
|
||||||
await editor.scrollToText(codeToSelection)
|
await editor.scrollToText(codeToSelection)
|
||||||
await page.getByText(codeToSelection).click()
|
await page.getByText(codeToSelection).click()
|
||||||
@ -4634,10 +4638,10 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '',
|
Profiles: '',
|
||||||
Length: '',
|
Length: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'sketches',
|
highlightedHeaderArg: 'Profiles',
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -4646,7 +4650,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
currentArgKey: 'length',
|
currentArgKey: 'length',
|
||||||
currentArgValue: '5',
|
currentArgValue: '5',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '2 faces',
|
Profiles: '2 profiles',
|
||||||
Length: '',
|
Length: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'length',
|
||||||
@ -4657,7 +4661,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '2 faces',
|
Profiles: '2 profiles',
|
||||||
Length: '1',
|
Length: '1',
|
||||||
},
|
},
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
@ -4728,11 +4732,11 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '',
|
Profiles: '',
|
||||||
Path: '',
|
Path: '',
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'sketches',
|
highlightedHeaderArg: 'Profiles',
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -4741,7 +4745,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
currentArgKey: 'path',
|
currentArgKey: 'path',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '2 faces',
|
Profiles: '2 profiles',
|
||||||
Path: '',
|
Path: '',
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
},
|
},
|
||||||
@ -4754,7 +4758,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '2 faces',
|
Profiles: '2 profiles',
|
||||||
Path: '1 segment',
|
Path: '1 segment',
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
},
|
},
|
||||||
@ -4825,11 +4829,11 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '',
|
Profiles: '',
|
||||||
AxisOrEdge: '',
|
AxisOrEdge: '',
|
||||||
Angle: '',
|
Angle: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'sketches',
|
highlightedHeaderArg: 'Profiles',
|
||||||
commandName: 'Revolve',
|
commandName: 'Revolve',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -4838,7 +4842,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
currentArgKey: 'axisOrEdge',
|
currentArgKey: 'axisOrEdge',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '2 faces',
|
Profiles: '2 profiles',
|
||||||
AxisOrEdge: '',
|
AxisOrEdge: '',
|
||||||
Angle: '',
|
Angle: '',
|
||||||
},
|
},
|
||||||
@ -4854,7 +4858,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
currentArgKey: 'angle',
|
currentArgKey: 'angle',
|
||||||
currentArgValue: '360',
|
currentArgValue: '360',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '2 faces',
|
Profiles: '2 profiles',
|
||||||
AxisOrEdge: 'Edge',
|
AxisOrEdge: 'Edge',
|
||||||
Edge: '1 segment',
|
Edge: '1 segment',
|
||||||
Angle: '',
|
Angle: '',
|
||||||
@ -4867,7 +4871,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sketches: '2 faces',
|
Profiles: '2 profiles',
|
||||||
AxisOrEdge: 'Edge',
|
AxisOrEdge: 'Edge',
|
||||||
Edge: '1 segment',
|
Edge: '1 segment',
|
||||||
Angle: '180',
|
Angle: '180',
|
||||||
|
@ -11,12 +11,13 @@ import {
|
|||||||
getPlaywrightDownloadDir,
|
getPlaywrightDownloadDir,
|
||||||
getUtils,
|
getUtils,
|
||||||
isOutOfViewInScrollContainer,
|
isOutOfViewInScrollContainer,
|
||||||
|
runningOnWindows,
|
||||||
} 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'
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'projects reload if a new one is created, deleted, or renamed externally',
|
'projects reload if a new one is created, deleted, or renamed externally',
|
||||||
{ tag: ['@electron', '@macos', '@windows'] },
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
let externalCreatedProjectName = 'external-created-project'
|
let externalCreatedProjectName = 'external-created-project'
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'click help/keybindings from home page',
|
'click help/keybindings from home page',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page }, testInfo) => {
|
async ({ page }, testInfo) => {
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'click help/keybindings from project page',
|
'click help/keybindings from project page',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
@ -111,7 +112,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'open a file in a project works and renders, open another file in different project with errors, it should clear the scene',
|
'open a file in a project works and renders, open another file in different project with errors, it should clear the scene',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ scene, cmdBar, context, page, editor }, testInfo) => {
|
async ({ scene, cmdBar, context, page, editor }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
@ -183,7 +184,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'open a file in a project works and renders, open another file in different project that is empty, it should clear the scene',
|
'open a file in a project works and renders, open another file in different project that is empty, it should clear the scene',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
@ -243,7 +244,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'open a file in a project works and renders, open empty file, it should clear the scene',
|
'open a file in a project works and renders, open empty file, it should clear the scene',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
@ -309,7 +310,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'open a file in a project works and renders, open another file in the same project with errors, it should clear the scene',
|
'open a file in a project works and renders, open another file in the same project with errors, it should clear the scene',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
@ -381,7 +382,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'when code with error first loads you get errors in console',
|
'when code with error first loads you get errors in console',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, editor }, testInfo) => {
|
async ({ context, page, editor }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(path.join(dir, 'broken-code'), { recursive: true })
|
await fsp.mkdir(path.join(dir, 'broken-code'), { recursive: true })
|
||||||
@ -415,7 +416,7 @@ test.describe('Can export from electron app', () => {
|
|||||||
for (const method of exportMethods) {
|
for (const method of exportMethods) {
|
||||||
test(
|
test(
|
||||||
`Can export using ${method}`,
|
`Can export using ${method}`,
|
||||||
{ tag: ['@electron', '@skipLocalEngine'] },
|
{ tag: ['@desktop', '@skipLocalEngine'] },
|
||||||
async ({ scene, cmdBar, context, page, tronApp }, testInfo) => {
|
async ({ scene, cmdBar, context, page, tronApp }, testInfo) => {
|
||||||
if (!tronApp) {
|
if (!tronApp) {
|
||||||
fail()
|
fail()
|
||||||
@ -506,7 +507,7 @@ test.describe('Can export from electron app', () => {
|
|||||||
})
|
})
|
||||||
test(
|
test(
|
||||||
'Rename and delete projects, also spam arrow keys when renaming',
|
'Rename and delete projects, also spam arrow keys when renaming',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true })
|
await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true })
|
||||||
@ -722,7 +723,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'pressing "delete" on home screen should do nothing',
|
'pressing "delete" on home screen should do nothing',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, homePage }, testInfo) => {
|
async ({ context, page, homePage }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true })
|
await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true })
|
||||||
@ -752,7 +753,7 @@ test(
|
|||||||
test.describe(`Project management commands`, () => {
|
test.describe(`Project management commands`, () => {
|
||||||
test(
|
test(
|
||||||
`Rename from project page`,
|
`Rename from project page`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
const projectName = `my_project_to_rename`
|
const projectName = `my_project_to_rename`
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
@ -814,7 +815,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`Delete from project page`,
|
`Delete from project page`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
const projectName = `my_project_to_delete`
|
const projectName = `my_project_to_delete`
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
@ -868,7 +869,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
)
|
)
|
||||||
test(
|
test(
|
||||||
`Rename from home page`,
|
`Rename from home page`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, homePage, scene, cmdBar }, testInfo) => {
|
async ({ context, page, homePage, scene, cmdBar }, testInfo) => {
|
||||||
const projectName = `my_project_to_rename`
|
const projectName = `my_project_to_rename`
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
@ -926,7 +927,7 @@ test.describe(`Project management commands`, () => {
|
|||||||
)
|
)
|
||||||
test(
|
test(
|
||||||
`Delete from home page`,
|
`Delete from home page`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
const projectName = `my_project_to_delete`
|
const projectName = `my_project_to_delete`
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
@ -1102,7 +1103,7 @@ test(`Create a few projects using the default project name`, async ({
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'File in the file pane should open with a single click',
|
'File in the file pane should open with a single click',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, homePage, page }, testInfo) => {
|
async ({ context, homePage, page }, testInfo) => {
|
||||||
const projectName = 'router-template-slate'
|
const projectName = 'router-template-slate'
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
@ -1144,7 +1145,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'Nested directories in project without main.kcl do not create main.kcl',
|
'Nested directories in project without main.kcl do not create main.kcl',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
let testDir: string | undefined
|
let testDir: string | undefined
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
@ -1201,7 +1202,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'Deleting projects, can delete individual project, can still create projects after deleting all',
|
'Deleting projects, can delete individual project, can still create projects after deleting all',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const projectData = [
|
const projectData = [
|
||||||
['router-template-slate', 'cylinder.kcl'],
|
['router-template-slate', 'cylinder.kcl'],
|
||||||
@ -1279,7 +1280,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'Can load a file with CRLF line endings',
|
'Can load a file with CRLF line endings',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const routerTemplateDir = path.join(dir, 'router-template-slate')
|
const routerTemplateDir = path.join(dir, 'router-template-slate')
|
||||||
@ -1311,7 +1312,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'Can sort projects on home page',
|
'Can sort projects on home page',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const projectData = [
|
const projectData = [
|
||||||
['router-template-slate', 'cylinder.kcl'],
|
['router-template-slate', 'cylinder.kcl'],
|
||||||
@ -1418,7 +1419,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'When the project folder is empty, user can create new project and open it.',
|
'When the project folder is empty, user can create new project and open it.',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page }, testInfo) => {
|
async ({ page }, testInfo) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
@ -1514,7 +1515,7 @@ extrude001 = extrude(sketch001, length = 200)`)
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'Opening a project should successfully load the stream, (regression test that this also works when switching between projects)',
|
'Opening a project should successfully load the stream, (regression test that this also works when switching between projects)',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, cmdBar, homePage, scene }, testInfo) => {
|
async ({ context, page, cmdBar, homePage, scene }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
await fsp.mkdir(path.join(dir, 'router-template-slate'), {
|
await fsp.mkdir(path.join(dir, 'router-template-slate'), {
|
||||||
@ -1627,7 +1628,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'You can change the root projects directory and nothing is lost',
|
'You can change the root projects directory and nothing is lost',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page, tronApp, homePage }, testInfo) => {
|
async ({ context, page, tronApp, homePage }, testInfo) => {
|
||||||
if (!tronApp) {
|
if (!tronApp) {
|
||||||
fail()
|
fail()
|
||||||
@ -1734,7 +1735,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'Search projects on desktop home',
|
'Search projects on desktop home',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const projectData = [
|
const projectData = [
|
||||||
['basic bracket', 'focusrite_scarlett_mounting_bracket.kcl'],
|
['basic bracket', 'focusrite_scarlett_mounting_bracket.kcl'],
|
||||||
@ -1790,7 +1791,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'file pane is scrollable when there are many files',
|
'file pane is scrollable when there are many files',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const testDir = path.join(dir, 'testProject')
|
const testDir = path.join(dir, 'testProject')
|
||||||
@ -1891,7 +1892,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'select all in code editor does not actually select all, just what is visible (regression)',
|
'select all in code editor does not actually select all, just what is visible (regression)',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
// rust/kcl-lib/e2e/executor/inputs/mike_stress_test.kcl
|
// rust/kcl-lib/e2e/executor/inputs/mike_stress_test.kcl
|
||||||
@ -1949,7 +1950,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'Settings persist across restarts',
|
'Settings persist across restarts',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page, toolbar }, testInfo) => {
|
async ({ page, toolbar }, testInfo) => {
|
||||||
await test.step('We can change a user setting like theme', async () => {
|
await test.step('We can change a user setting like theme', async () => {
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
@ -1979,10 +1980,9 @@ test(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Flaky
|
|
||||||
test(
|
test(
|
||||||
'Original project name persist after onboarding',
|
'Original project name persist after onboarding',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ page, toolbar }, testInfo) => {
|
async ({ page, toolbar }, testInfo) => {
|
||||||
const nextButton = page.getByTestId('onboarding-next')
|
const nextButton = page.getByTestId('onboarding-next')
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
@ -2022,7 +2022,7 @@ test(
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
'project name with foreign characters should open',
|
'project name with foreign characters should open',
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'العربية')
|
const bracketDir = path.join(dir, 'العربية')
|
||||||
@ -2064,3 +2064,55 @@ test(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test(
|
||||||
|
'import from nested directory',
|
||||||
|
{ tag: ['@desktop', '@windows', '@macos'] },
|
||||||
|
async ({ scene, cmdBar, context, page }) => {
|
||||||
|
await context.folderSetupFn(async (dir) => {
|
||||||
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
|
const nestedDir = path.join(bracketDir, 'nested')
|
||||||
|
await fsp.mkdir(nestedDir, { recursive: true })
|
||||||
|
|
||||||
|
await fsp.copyFile(
|
||||||
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
|
path.join(nestedDir, 'main.kcl')
|
||||||
|
)
|
||||||
|
await fsp.writeFile(
|
||||||
|
path.join(bracketDir, 'main.kcl'),
|
||||||
|
runningOnWindows()
|
||||||
|
? `import 'nested\\main.kcl' as thing\n\nthing`
|
||||||
|
: `import 'nested/main.kcl' as thing\n\nthing`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
const u = await getUtils(page)
|
||||||
|
|
||||||
|
const pointOnModel = { x: 630, y: 280 }
|
||||||
|
|
||||||
|
await test.step('Opening the bracket project should load the stream', async () => {
|
||||||
|
// expect to see the text bracket
|
||||||
|
await expect(page.getByText('bracket')).toBeVisible()
|
||||||
|
|
||||||
|
await page.getByText('bracket').click()
|
||||||
|
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
|
).toBeEnabled({
|
||||||
|
timeout: 20_000,
|
||||||
|
})
|
||||||
|
|
||||||
|
// gray at this pixel means the stream has loaded in the most
|
||||||
|
// user way we can verify it (pixel color)
|
||||||
|
await expect
|
||||||
|
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
|
||||||
|
timeout: 10_000,
|
||||||
|
})
|
||||||
|
.toBeLessThan(15)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ -63,7 +63,7 @@ test.describe('edit with AI example snapshots', () => {
|
|||||||
test(
|
test(
|
||||||
`change colour`,
|
`change colour`,
|
||||||
// TODO this is more of a snapshot, but atm it needs to be manually run locally to update the files
|
// TODO this is more of a snapshot, but atm it needs to be manually run locally to update the files
|
||||||
{ tag: ['@electron'] },
|
{ tag: ['@desktop'] },
|
||||||
async ({ context, homePage, cmdBar, editor, page, scene }) => {
|
async ({ context, homePage, cmdBar, editor, page, scene }) => {
|
||||||
const project = 'test-dir'
|
const project = 'test-dir'
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
@ -99,6 +99,8 @@ test.describe('edit with AI example snapshots', () => {
|
|||||||
await test.step('fire off edit prompt', async () => {
|
await test.step('fire off edit prompt', async () => {
|
||||||
await cmdBar.captureTextToCadRequestSnapshot(test.info())
|
await cmdBar.captureTextToCadRequestSnapshot(test.info())
|
||||||
await cmdBar.openCmdBar('promptToEdit')
|
await cmdBar.openCmdBar('promptToEdit')
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
// being specific about the color with a hex means asserting pixel color is more stable
|
// being specific about the color with a hex means asserting pixel color is more stable
|
||||||
await page
|
await page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
|
@ -88,6 +88,8 @@ test.describe('Prompt-to-edit tests', () => {
|
|||||||
|
|
||||||
await test.step('fire off edit prompt', async () => {
|
await test.step('fire off edit prompt', async () => {
|
||||||
await cmdBar.openCmdBar('promptToEdit')
|
await cmdBar.openCmdBar('promptToEdit')
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
// being specific about the color with a hex means asserting pixel color is more stable
|
// being specific about the color with a hex means asserting pixel color is more stable
|
||||||
await page
|
await page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
@ -165,6 +167,8 @@ test.describe('Prompt-to-edit tests', () => {
|
|||||||
|
|
||||||
await test.step('fire of bad prompt', async () => {
|
await test.step('fire of bad prompt', async () => {
|
||||||
await cmdBar.openCmdBar('promptToEdit')
|
await cmdBar.openCmdBar('promptToEdit')
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await page
|
await page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
.fill('ansheusha asnthuatshoeuhtaoetuhthaeu laughs in dvorak')
|
.fill('ansheusha asnthuatshoeuhtaoetuhthaeu laughs in dvorak')
|
||||||
|
@ -558,7 +558,7 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
|
|
||||||
test(
|
test(
|
||||||
`Network health indicator only appears in modeling view`,
|
`Network health indicator only appears in modeling view`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@desktop' },
|
||||||
async ({ context, page }) => {
|
async ({ context, page }) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
|
@ -17,7 +17,7 @@ test.describe('Share link tests', () => {
|
|||||||
`Open in desktop app with ${codeLength}-long code ${isWindows && showsErrorOnWindows ? 'shows error' : "doesn't show error"}`,
|
`Open in desktop app with ${codeLength}-long code ${isWindows && showsErrorOnWindows ? 'shows error' : "doesn't show error"}`,
|
||||||
{ tag: ['@web'] },
|
{ tag: ['@web'] },
|
||||||
async ({ page }) => {
|
async ({ page }) => {
|
||||||
if (process.env.PLATFORM !== 'web') {
|
if (process.env.TARGET !== 'web') {
|
||||||
// This test is web-only
|
// This test is web-only
|
||||||
// TODO: re-enable on CI as part of a new @web test suite
|
// TODO: re-enable on CI as part of a new @web test suite
|
||||||
return
|
return
|
||||||
|
@ -995,8 +995,8 @@ profile001 = startProfile(sketch001, at = [${roundOff(scale * 69.6)}, ${roundOff
|
|||||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
// click "line(end = [1.32, 0.38])"
|
// click profile in code
|
||||||
await page.getByText(`line(end = [1.32, 0.38])`).click()
|
await page.getByText(`startProfile(at = [-0.45, 0.87])`).click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeEnabled(
|
await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeEnabled(
|
||||||
{ timeout: 10_000 }
|
{ timeout: 10_000 }
|
||||||
@ -1014,14 +1014,14 @@ profile001 = startProfile(sketch001, at = [${roundOff(scale * 69.6)}, ${roundOff
|
|||||||
// click extrude
|
// click extrude
|
||||||
await toolbar.extrudeButton.click()
|
await toolbar.extrudeButton.click()
|
||||||
|
|
||||||
// sketch selection should already have been made. "Sketches: 1 face" only show up when the selection has been made already
|
// sketch selection should already have been made.
|
||||||
// otherwise the cmdbar would be waiting for a selection.
|
// otherwise the cmdbar would be waiting for a selection.
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'length',
|
currentArgKey: 'length',
|
||||||
currentArgValue: '5',
|
currentArgValue: '5',
|
||||||
headerArguments: { Sketches: '1 segment', Length: '' },
|
headerArguments: { Profiles: '1 profile', Length: '' },
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'length',
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
})
|
})
|
||||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 69 KiB |