Compare commits
35 Commits
v0.47.0
...
jtran/sket
Author | SHA1 | Date | |
---|---|---|---|
6e03cf61f4 | |||
2a24a4da82 | |||
3e186fbe6b | |||
0372f35ce1 | |||
219bc4c8a3 | |||
0130d19cfb | |||
a96a5fcba8 | |||
79374a3dc0 | |||
9563fb9a5e | |||
6fb32eeff2 | |||
ec64daa01f | |||
e8886bb358 | |||
05a6313d97 | |||
80f78e1c61 | |||
c441a3ab1c | |||
e894242768 | |||
d8dff03746 | |||
60aee7ddba | |||
6c09da24a4 | |||
b61cd3123f | |||
865bf8ae7a | |||
f8e53c6577 | |||
f31c2c6f81 | |||
e5c05e1980 | |||
6d0da100e5 | |||
b8a0ad7144 | |||
724e65ac97 | |||
b5028f7aa8 | |||
df6b4f4c37 | |||
41eb64925b | |||
fc076173ff | |||
98822869f7 | |||
df0510c199 | |||
fda65bcbd7 | |||
c37e564b59 |
39
.github/workflows/build-apps.yml
vendored
39
.github/workflows/build-apps.yml
vendored
@ -33,26 +33,63 @@ jobs:
|
||||
|
||||
- run: yarn install
|
||||
|
||||
- id: filter
|
||||
name: Check for Rust changes
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
rust:
|
||||
- 'rust/**'
|
||||
|
||||
- name: Download Wasm Cache
|
||||
id: download-wasm
|
||||
if: ${{ github.event_name == 'pull_request' && steps.filter.outputs.rust == 'false' }}
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
continue-on-error: true
|
||||
with:
|
||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||
name: wasm-bundle
|
||||
workflow: build-and-store-wasm.yml
|
||||
branch: main
|
||||
path: rust/kcl-wasm-lib/pkg
|
||||
|
||||
- name: Build WASM condition
|
||||
id: wasm
|
||||
run: |
|
||||
set -euox pipefail
|
||||
# Build wasm if this is a push to main or tag, there are Rust changes, or
|
||||
# downloading from the wasm cache failed.
|
||||
if [[ ${{github.event_name}} == 'push' || ${{steps.filter.outputs.rust}} == 'true' || ${{steps.download-wasm.outcome}} == 'failure' ]]; then
|
||||
echo "should-build-wasm=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should-build-wasm=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Use correct Rust toolchain
|
||||
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||
|
||||
- name: Install rust
|
||||
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache: false # Configured below.
|
||||
|
||||
# TODO: see if we can fetch from main instead if no diff at rust
|
||||
- uses: taiki-e/install-action@955a6ff1416eae278c9f833008a9beb4b7f9afe3
|
||||
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
with:
|
||||
tool: wasm-pack
|
||||
|
||||
- name: Rust Cache
|
||||
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: rust
|
||||
|
||||
- name: Run build:wasm
|
||||
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
run: "yarn build:wasm"
|
||||
|
||||
- name: Set nightly version, product name, release notes, and icons
|
||||
|
24
.github/workflows/cargo-bench.yml
vendored
24
.github/workflows/cargo-bench.yml
vendored
@ -26,7 +26,7 @@ name: cargo bench
|
||||
jobs:
|
||||
cargo-bench:
|
||||
name: cargo bench
|
||||
runs-on: ubuntu-latest-8-cores
|
||||
runs-on: codspeed-macro
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use correct Rust toolchain
|
||||
@ -40,13 +40,19 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cargo install cargo-criterion
|
||||
sudo apt update
|
||||
sudo apt install -y valgrind
|
||||
- uses: boa-dev/criterion-compare-action@v3
|
||||
cargo install cargo-codspeed
|
||||
cd rust/kcl-lib
|
||||
cargo add --dev codspeed-criterion-compat --rename criterion
|
||||
- name: Build the benchmark target(s)
|
||||
run: |
|
||||
cd rust
|
||||
cargo codspeed build --measurement-mode walltime
|
||||
- name: Run the benchmarks
|
||||
uses: CodSpeedHQ/action@v3
|
||||
with:
|
||||
cwd: "rust"
|
||||
defaultFeatures: true
|
||||
# Needed. The name of the branch to compare with. This default uses the branch which is being pulled against
|
||||
branchName: ${{ github.base_ref }}
|
||||
working-directory: rust
|
||||
run: cargo codspeed run
|
||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||
mode: walltime
|
||||
env:
|
||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
|
||||
KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN }}
|
||||
|
515
.github/workflows/e2e-tests.yml
vendored
515
.github/workflows/e2e-tests.yml
vendored
@ -26,9 +26,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Fetch the base branch
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
run: git fetch origin ${{ github.base_ref }} --depth=1
|
||||
|
||||
- name: Check for path changes
|
||||
id: path-changes
|
||||
shell: bash
|
||||
@ -48,6 +50,7 @@ jobs:
|
||||
else
|
||||
echo "significant=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Should run
|
||||
id: should-run
|
||||
shell: bash
|
||||
@ -60,6 +63,7 @@ jobs:
|
||||
else
|
||||
echo "should-run=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Display conditions
|
||||
shell: bash
|
||||
run: |
|
||||
@ -68,7 +72,216 @@ jobs:
|
||||
echo "significant: ${{ steps.path-changes.outputs.significant }}"
|
||||
echo "should-run: ${{ steps.should-run.outputs.should-run }}"
|
||||
|
||||
|
||||
prepare-wasm:
|
||||
# seperate job on Ubuntu to build or fetch the wasm blob once on the fastest runner
|
||||
runs-on: namespace-profile-ubuntu-8-cores
|
||||
needs: conditions
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
|
||||
- id: filter
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
name: Check for Rust changes
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
rust:
|
||||
- 'rust/**'
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install dependencies
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
run: yarn
|
||||
|
||||
- name: Download Wasm Cache
|
||||
id: download-wasm
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && github.event_name != 'schedule' && steps.filter.outputs.rust == 'false' }}
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
continue-on-error: true
|
||||
with:
|
||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||
name: wasm-bundle
|
||||
workflow: build-and-store-wasm.yml
|
||||
branch: main
|
||||
path: rust/kcl-wasm-lib/pkg
|
||||
|
||||
- name: Build WASM condition
|
||||
id: wasm
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
run: |
|
||||
set -euox pipefail
|
||||
# Build wasm if this is a scheduled run, there are Rust changes, or
|
||||
# downloading from the wasm cache failed.
|
||||
if [[ ${{github.event_name}} == 'schedule' || ${{steps.filter.outputs.rust}} == 'true' || ${{steps.download-wasm.outcome}} == 'failure' ]]; then
|
||||
echo "should-build-wasm=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should-build-wasm=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Use correct Rust toolchain
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||
|
||||
- name: Install rust
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache: false # Configured below.
|
||||
|
||||
- uses: taiki-e/install-action@955a6ff1416eae278c9f833008a9beb4b7f9afe3
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
with:
|
||||
tool: wasm-pack
|
||||
|
||||
- name: Rust Cache
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: './rust'
|
||||
|
||||
- name: Build Wasm
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
shell: bash
|
||||
run: yarn build:wasm
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
with:
|
||||
name: prepared-wasm
|
||||
path: |
|
||||
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
|
||||
|
||||
|
||||
snapshots:
|
||||
name: playwright:snapshots:ubuntu
|
||||
runs-on: namespace-profile-ubuntu-8-cores
|
||||
needs: [conditions, prepare-wasm]
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v1
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
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
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
with:
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
name: prepared-wasm
|
||||
|
||||
- name: Copy prepared wasm
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
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
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install dependencies
|
||||
id: deps-install
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
run: yarn
|
||||
|
||||
- name: Cache Playwright Browsers
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/ms-playwright/
|
||||
key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
run: yarn playwright install --with-deps
|
||||
|
||||
- name: build web
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
run: yarn tronb:vite:dev
|
||||
|
||||
- name: Run ubuntu/chrome snapshots
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
run: |
|
||||
yarn test:snapshots
|
||||
env:
|
||||
CI: true
|
||||
NODE_ENV: development
|
||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
VITE_KC_SKIP_AUTH: true
|
||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
||||
with:
|
||||
name: playwright-report-snapshots-${{ matrix.os }}-snapshot-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||
path: playwright-report/
|
||||
include-hidden-files: true
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
|
||||
- name: Clean up test-results
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
||||
continue-on-error: true
|
||||
run: rm -r test-results
|
||||
|
||||
- name: check for changes
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && matrix.os == 'namespace-profile-ubuntu-8-cores' && matrix.shardIndex == 1 && github.ref != 'refs/heads/main' }}
|
||||
shell: bash
|
||||
id: git-check
|
||||
run: |
|
||||
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
||||
if git status | 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: ${{ needs.conditions.outputs.should-run == 'true' && steps.git-check.outputs.modified == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
||||
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 }}
|
||||
git commit -m "A snapshot a day keeps the bugs away! 📷🐛 (OS: ${{matrix.os}})" || true
|
||||
git push
|
||||
git push origin ${{ github.head_ref }}
|
||||
|
||||
# only upload artifacts if there's actually changes
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.git-check.outputs.modified == 'true' }}
|
||||
with:
|
||||
name: playwright-report-ubuntu-${{ github.sha }}
|
||||
path: playwright-report/
|
||||
include-hidden-files: true
|
||||
retention-days: 30
|
||||
|
||||
|
||||
electron:
|
||||
needs: [conditions, prepare-wasm]
|
||||
timeout-minutes: 60
|
||||
name: playwright:electron:${{ matrix.os }} ${{ matrix.shardIndex }} ${{ matrix.shardTotal }}
|
||||
strategy:
|
||||
@ -80,218 +293,94 @@ jobs:
|
||||
shardTotal: [4]
|
||||
# TODO: add ref here for main and latest release tag
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: conditions
|
||||
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 }}
|
||||
- id: filter
|
||||
name: Check for Rust changes
|
||||
uses: dorny/paths-filter@v3
|
||||
with:
|
||||
filters: |
|
||||
rust:
|
||||
- 'rust/**'
|
||||
- uses: actions/setup-node@v4
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'yarn'
|
||||
- name: Install dependencies
|
||||
id: deps-install
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
shell: bash
|
||||
run: yarn
|
||||
- name: Cache Playwright Browsers
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/ms-playwright/
|
||||
key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }}
|
||||
- name: Install Playwright Browsers
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
shell: bash
|
||||
run: yarn playwright install --with-deps
|
||||
- name: Download Wasm Cache
|
||||
id: download-wasm
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && github.event_name != 'schedule' && steps.filter.outputs.rust == 'false' }}
|
||||
uses: dawidd6/action-download-artifact@v7
|
||||
continue-on-error: true
|
||||
with:
|
||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||
name: wasm-bundle
|
||||
workflow: build-and-store-wasm.yml
|
||||
branch: main
|
||||
path: rust/kcl-wasm-lib/pkg
|
||||
- name: copy wasm blob
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && github.event_name != 'schedule' && steps.filter.outputs.rust == 'false' }}
|
||||
shell: bash
|
||||
run: cp rust/kcl-wasm-lib/pkg/kcl_wasm_lib_bg.wasm public
|
||||
continue-on-error: true
|
||||
- name: Build WASM condition
|
||||
id: wasm
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euox pipefail
|
||||
# Build wasm if this is a scheduled run, there are Rust changes, or
|
||||
# downloading from the wasm cache failed.
|
||||
if [[ ${{github.event_name}} == 'schedule' || ${{steps.filter.outputs.rust}} == 'true' || ${{steps.download-wasm.outcome}} == 'failure' ]]; then
|
||||
echo "should-build-wasm=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should-build-wasm=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Use correct Rust toolchain
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||
- name: Install rust
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
cache: false # Configured below.
|
||||
- uses: taiki-e/install-action@955a6ff1416eae278c9f833008a9beb4b7f9afe3
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
with:
|
||||
tool: wasm-pack
|
||||
- name: Rust Cache
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: './rust'
|
||||
- name: install good sed
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && startsWith(matrix.os, 'macos') }}
|
||||
shell: bash
|
||||
run: |
|
||||
brew install gnu-sed
|
||||
echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH
|
||||
- name: Install vector
|
||||
shell: bash
|
||||
# TODO: figure out what to do with this, it's failing
|
||||
if: false
|
||||
run: |
|
||||
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh
|
||||
chmod +x /tmp/vector.sh
|
||||
/tmp/vector.sh -y -no-modify-path
|
||||
mkdir -p /tmp/vector
|
||||
cp .github/workflows/vector.toml /tmp/vector.toml
|
||||
sed -i "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
|
||||
sed -i "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
|
||||
sed -i "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
|
||||
sed -i "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
|
||||
sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml
|
||||
cat /tmp/vector.toml
|
||||
${HOME}/.vector/bin/vector --config /tmp/vector.toml &
|
||||
- name: Build Wasm
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||
shell: bash
|
||||
run: yarn build:wasm
|
||||
- name: build web
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
shell: bash
|
||||
run: yarn tronb:vite:dev
|
||||
- name: Run ubuntu/chrome snapshots
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && matrix.os == 'namespace-profile-ubuntu-8-cores' && matrix.shardIndex == 1 }}
|
||||
shell: bash
|
||||
# TODO: break this in its own job, for now it's not slowing down the overall execution as ubuntu is the quickest,
|
||||
# but we could do better. This forces a large 1/1 shard of all 20 snapshot tests that runs in about 3 minutes.
|
||||
run: |
|
||||
yarn test:snapshots
|
||||
env:
|
||||
CI: true
|
||||
NODE_ENV: development
|
||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
VITE_KC_SKIP_AUTH: true
|
||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
||||
with:
|
||||
name: playwright-report-snapshots-${{ matrix.os }}-snapshot-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||
path: playwright-report/
|
||||
include-hidden-files: true
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
- name: Clean up test-results
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
||||
continue-on-error: true
|
||||
run: rm -r test-results
|
||||
- name: check for changes
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && matrix.os == 'namespace-profile-ubuntu-8-cores' && matrix.shardIndex == 1 && github.ref != 'refs/heads/main' }}
|
||||
shell: bash
|
||||
id: git-check
|
||||
run: |
|
||||
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
||||
if git status | 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: ${{ needs.conditions.outputs.should-run == 'true' && steps.git-check.outputs.modified == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
||||
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 }}
|
||||
git commit -m "A snapshot a day keeps the bugs away! 📷🐛 (OS: ${{matrix.os}})" || true
|
||||
git push
|
||||
git push origin ${{ github.head_ref }}
|
||||
# only upload artifacts if there's actually changes
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.git-check.outputs.modified == 'true' }}
|
||||
with:
|
||||
name: playwright-report-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||
path: playwright-report/
|
||||
include-hidden-files: true
|
||||
retention-days: 30
|
||||
- uses: actions/download-artifact@v4
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
||||
continue-on-error: true
|
||||
with:
|
||||
name: test-results-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||
path: test-results/
|
||||
- name: Run playwright/electron flow (with retries)
|
||||
id: retry
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && steps.deps-install.outcome == 'success' }}
|
||||
uses: nick-fields/retry@v3.0.2
|
||||
with:
|
||||
shell: bash
|
||||
command: .github/ci-cd-scripts/playwright-electron.sh ${{matrix.shardIndex}} ${{matrix.shardTotal}} ${{matrix.os}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 25
|
||||
env:
|
||||
CI: true
|
||||
FAIL_ON_CONSOLE_ERRORS: true
|
||||
NODE_ENV: development
|
||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
VITE_KC_SKIP_AUTH: true
|
||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && always() }}
|
||||
with:
|
||||
name: test-results-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||
path: test-results/
|
||||
include-hidden-files: true
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && always() }}
|
||||
with:
|
||||
name: playwright-report-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||
path: playwright-report/
|
||||
include-hidden-files: true
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
- uses: actions/checkout@v4
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
name: prepared-wasm
|
||||
|
||||
- name: Copy prepared wasm
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
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
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install dependencies
|
||||
id: deps-install
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
run: yarn
|
||||
|
||||
- name: Cache Playwright Browsers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/ms-playwright/
|
||||
key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: yarn playwright install --with-deps
|
||||
|
||||
- name: Build web
|
||||
if: needs.conditions.outputs.should-run == 'true'
|
||||
run: yarn tronb:vite:dev
|
||||
|
||||
- name: Install good sed
|
||||
if: startsWith(matrix.os, 'macos')
|
||||
shell: bash
|
||||
run: |
|
||||
brew install gnu-sed
|
||||
echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH
|
||||
|
||||
# TODO: Add back axiom logs
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
||||
continue-on-error: true
|
||||
with:
|
||||
name: test-results-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||
path: test-results/
|
||||
|
||||
- name: Run playwright/electron flow (with retries)
|
||||
id: retry
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && steps.deps-install.outcome == 'success' }}
|
||||
uses: nick-fields/retry@v3.0.2
|
||||
with:
|
||||
shell: bash
|
||||
command: .github/ci-cd-scripts/playwright-electron.sh ${{matrix.shardIndex}} ${{matrix.shardTotal}} ${{matrix.os}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 25
|
||||
env:
|
||||
CI: true
|
||||
FAIL_ON_CONSOLE_ERRORS: true
|
||||
NODE_ENV: development
|
||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
VITE_KC_SKIP_AUTH: true
|
||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && always() }}
|
||||
with:
|
||||
name: test-results-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||
path: test-results/
|
||||
include-hidden-files: true
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ needs.conditions.outputs.should-run == 'true' && always() }}
|
||||
with:
|
||||
name: playwright-report-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||
path: playwright-report/
|
||||
include-hidden-files: true
|
||||
retention-days: 30
|
||||
overwrite: true
|
||||
|
4
.github/workflows/generate-website-docs.yml
vendored
4
.github/workflows/generate-website-docs.yml
vendored
@ -40,9 +40,13 @@ jobs:
|
||||
# cleanup old
|
||||
rm -rf documentation/content/pages/docs/kcl/*.md
|
||||
rm -rf documentation/content/pages/docs/kcl/types
|
||||
rm -rf documentation/content/pages/docs/kcl/settings
|
||||
rm -rf documentation/content/pages/docs/kcl/consts
|
||||
# move new
|
||||
mv -f docs/kcl/*.md documentation/content/pages/docs/kcl/
|
||||
mv -f docs/kcl/types documentation/content/pages/docs/kcl/
|
||||
mv -f docs/kcl/settings documentation/content/pages/docs/kcl/
|
||||
mv -f docs/kcl/consts documentation/content/pages/docs/kcl/
|
||||
- name: move kcl-samples
|
||||
shell: bash
|
||||
run: |
|
||||
|
2
.github/workflows/kcl-python-bindings.yml
vendored
2
.github/workflows/kcl-python-bindings.yml
vendored
@ -161,6 +161,8 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: rust/kcl-python-bindings
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
- name: do uv things
|
||||
|
File diff suppressed because one or more lines are too long
25
docs/kcl/consts.md
Normal file
25
docs/kcl/consts.md
Normal file
@ -0,0 +1,25 @@
|
||||
---
|
||||
title: "KCL Constants"
|
||||
excerpt: "Documentation for the KCL constants."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
||||
### `std`
|
||||
|
||||
- [`HALF_TURN`](/docs/kcl/consts/std-HALF_TURN)
|
||||
- [`QUARTER_TURN`](/docs/kcl/consts/std-QUARTER_TURN)
|
||||
- [`THREE_QUARTER_TURN`](/docs/kcl/consts/std-THREE_QUARTER_TURN)
|
||||
- [`XY`](/docs/kcl/consts/std-XY)
|
||||
- [`XZ`](/docs/kcl/consts/std-XZ)
|
||||
- [`YZ`](/docs/kcl/consts/std-YZ)
|
||||
- [`ZERO`](/docs/kcl/consts/std-ZERO)
|
||||
|
||||
### `std::math`
|
||||
|
||||
- [`E`](/docs/kcl/consts/std-math-E)
|
||||
- [`PI`](/docs/kcl/consts/std-math-PI)
|
||||
- [`TAU`](/docs/kcl/consts/std-math-TAU)
|
||||
|
@ -6,7 +6,7 @@ layout: manual
|
||||
|
||||
Extend a 2-dimensional sketch through a third dimension in order to create new 3-dimensional volume, or if extruded into an existing volume, cut into an existing solid.
|
||||
|
||||
|
||||
You can provide more than one sketch to extrude, and they will all be extruded in the same direction.
|
||||
|
||||
```js
|
||||
extrude(
|
||||
@ -20,7 +20,7 @@ extrude(
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | Which sketches should be extruded | Yes |
|
||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | Which sketch or set of sketches should be extruded | Yes |
|
||||
| `length` | [`number`](/docs/kcl/types/number) | How far to extrude the given sketches | Yes |
|
||||
|
||||
### Returns
|
||||
|
@ -12,25 +12,26 @@ layout: manual
|
||||
* [`Modules`](kcl/modules)
|
||||
* [`Settings`](kcl/settings)
|
||||
* [`Known Issues`](kcl/known-issues)
|
||||
* [`Constants`](kcl/consts)
|
||||
|
||||
### Standard library
|
||||
|
||||
* **Primitive types**
|
||||
* [`bool`](kcl/bool)
|
||||
* [`number`](kcl/number)
|
||||
* [`string`](kcl/string)
|
||||
* [`tag`](kcl/tag)
|
||||
* [`bool`](kcl/types/bool)
|
||||
* [`number`](kcl/types/number)
|
||||
* [`string`](kcl/types/string)
|
||||
* [`tag`](kcl/types/tag)
|
||||
* **std**
|
||||
* [`HALF_TURN`](kcl/const_std-HALF_TURN)
|
||||
* [`Plane`](kcl/Plane)
|
||||
* [`QUARTER_TURN`](kcl/const_std-QUARTER_TURN)
|
||||
* [`Sketch`](kcl/Sketch)
|
||||
* [`Solid`](kcl/Solid)
|
||||
* [`THREE_QUARTER_TURN`](kcl/const_std-THREE_QUARTER_TURN)
|
||||
* [`XY`](kcl/const_std-XY)
|
||||
* [`XZ`](kcl/const_std-XZ)
|
||||
* [`YZ`](kcl/const_std-YZ)
|
||||
* [`ZERO`](kcl/const_std-ZERO)
|
||||
* [`HALF_TURN`](kcl/consts/std-HALF_TURN)
|
||||
* [`Plane`](kcl/types/Plane)
|
||||
* [`QUARTER_TURN`](kcl/consts/std-QUARTER_TURN)
|
||||
* [`Sketch`](kcl/types/Sketch)
|
||||
* [`Solid`](kcl/types/Solid)
|
||||
* [`THREE_QUARTER_TURN`](kcl/consts/std-THREE_QUARTER_TURN)
|
||||
* [`XY`](kcl/consts/std-XY)
|
||||
* [`XZ`](kcl/consts/std-XZ)
|
||||
* [`YZ`](kcl/consts/std-YZ)
|
||||
* [`ZERO`](kcl/consts/std-ZERO)
|
||||
* [`abs`](kcl/abs)
|
||||
* [`acos`](kcl/acos)
|
||||
* [`angleToMatchLengthX`](kcl/angleToMatchLengthX)
|
||||
@ -134,9 +135,9 @@ layout: manual
|
||||
* [`yLine`](kcl/yLine)
|
||||
* [`yd`](kcl/yd)
|
||||
* **std::math**
|
||||
* [`E`](kcl/const_std-math-E)
|
||||
* [`PI`](kcl/const_std-math-PI)
|
||||
* [`TAU`](kcl/const_std-math-TAU)
|
||||
* [`E`](kcl/consts/std-math-E)
|
||||
* [`PI`](kcl/consts/std-math-PI)
|
||||
* [`TAU`](kcl/consts/std-math-TAU)
|
||||
* [`cos`](kcl/std-math-cos)
|
||||
* [`sin`](kcl/std-math-sin)
|
||||
* [`tan`](kcl/std-math-tan)
|
||||
|
@ -13,9 +13,7 @@ once fixed in engine will just start working here with no language changes.
|
||||
If you see a red line around your model, it means this is happening.
|
||||
|
||||
- **Import**: Right now you can import a file, even if that file has brep data
|
||||
you cannot edit it, after v1, the engine will account for this. You also cannot
|
||||
currently move or transform the imported objects at all, once we have assemblies
|
||||
this will work.
|
||||
you cannot edit it, after v1, the engine will account for this.
|
||||
|
||||
- **Fillets**: Fillets cannot intersect, you will get an error. Only simple fillet
|
||||
cases work currently.
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "KCL settings"
|
||||
title: "KCL Settings"
|
||||
excerpt: "Documentation of settings for the KCL language and Zoo Modeling App."
|
||||
layout: manual
|
||||
---
|
||||
@ -8,16 +8,16 @@ layout: manual
|
||||
|
||||
There are three levels of settings available in the KittyCAD modeling application:
|
||||
|
||||
1. [User Settings](/docs/kcl/settings/user.toml): Global settings that apply to all projects, stored in `user.toml`
|
||||
2. [Project Settings](/docs/kcl/settings/project.toml): Settings specific to a project, stored in `project.toml`
|
||||
1. [User Settings](/docs/kcl/settings/user): Global settings that apply to all projects, stored in `user.toml`
|
||||
2. [Project Settings](/docs/kcl/settings/project): Settings specific to a project, stored in `project.toml`
|
||||
3. Per-file Settings: Settings that apply to a single KCL file, specified using the `@settings` attribute
|
||||
|
||||
## Configuration Files
|
||||
|
||||
The KittyCAD modeling app uses TOML files for configuration:
|
||||
|
||||
* **User Settings**: `user.toml` - See [complete documentation](/docs/kcl/settings/user.toml)
|
||||
* **Project Settings**: `project.toml` - See [complete documentation](/docs/kcl/settings/project.toml)
|
||||
* **User Settings**: `user.toml` - See [complete documentation](/docs/kcl/settings/user)
|
||||
* **Project Settings**: `project.toml` - See [complete documentation](/docs/kcl/settings/project)
|
||||
|
||||
## Per-file settings
|
||||
|
||||
|
15412
docs/kcl/std.json
15412
docs/kcl/std.json
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -24,6 +24,5 @@ A face.
|
||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
|
@ -22,6 +22,5 @@ A helix.
|
||||
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
|
||||
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
|
@ -22,6 +22,5 @@ A helix.
|
||||
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
|
||||
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
|
@ -18,6 +18,5 @@ Data for an imported geometry.
|
||||
|----------|------|-------------|----------|
|
||||
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
|
||||
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
|
@ -25,7 +25,6 @@ Any KCL value.
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Uuid`| | No |
|
||||
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -42,7 +41,6 @@ Any KCL value.
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Bool`| | No |
|
||||
| `value` |`boolean`| | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -60,7 +58,6 @@ Any KCL value.
|
||||
| `type` |enum: `Number`| | No |
|
||||
| `value` |[`number`](/docs/kcl/types/number)| | No |
|
||||
| `ty` |[`NumericType`](/docs/kcl/types/NumericType)| | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -77,7 +74,6 @@ Any KCL value.
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `String`| | No |
|
||||
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -94,7 +90,6 @@ Any KCL value.
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `MixedArray`| | No |
|
||||
| `value` |`[` [`KclValue`](/docs/kcl/types/KclValue) `]`| | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -111,7 +106,6 @@ Any KCL value.
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Object`| | No |
|
||||
| `value` |`object`| | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -129,7 +123,6 @@ Any KCL value.
|
||||
| `type` |enum: [`TagIdentifier`](/docs/kcl/types#tag-identifier)| | No |
|
||||
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
||||
| `info` |[`TagEngineInfo`](/docs/kcl/types/TagEngineInfo)| | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -279,7 +272,6 @@ Data for an imported geometry.
|
||||
| `type` |enum: [`ImportedGeometry`](/docs/kcl/types/ImportedGeometry)| | No |
|
||||
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
|
||||
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -295,7 +287,6 @@ Data for an imported geometry.
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Function`| | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -312,7 +303,6 @@ Data for an imported geometry.
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Module`| | No |
|
||||
| `value` |[`ModuleId`](/docs/kcl/types/ModuleId)| Identifier of a source file. Uses a u32 to keep the size small. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -328,7 +318,6 @@ Data for an imported geometry.
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Type`| | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -345,7 +334,6 @@ Data for an imported geometry.
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: [`KclNone`](/docs/kcl/types/KclNone)| | No |
|
||||
| `value` |[`KclNone`](/docs/kcl/types/KclNone)| KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application). | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -362,7 +350,6 @@ Data for an imported geometry.
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `Tombstone`| | No |
|
||||
| `value` |`null`| | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
|
@ -32,7 +32,6 @@ A sketch or a group of sketches.
|
||||
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The original id of the sketch. This stays the same even if the sketch is is sketched on face etc. | No |
|
||||
| `originalId` |[`string`](/docs/kcl/types/string)| | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
||||
|
||||
|
||||
----
|
||||
|
@ -32,7 +32,6 @@ A sketch type.
|
||||
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's Y axis be? | No |
|
||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
@ -57,7 +56,6 @@ A face.
|
||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
||||
|
||||
|
||||
----
|
||||
|
60
docs/kcl/types/SolidOrImportedGeometry.md
Normal file
60
docs/kcl/types/SolidOrImportedGeometry.md
Normal file
@ -0,0 +1,60 @@
|
||||
---
|
||||
title: "SolidOrImportedGeometry"
|
||||
excerpt: "Data for a solid or an imported geometry."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Data for a solid or an imported geometry.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
**This schema accepts exactly one of the following:**
|
||||
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `solid`| | No |
|
||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the solid. | No |
|
||||
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID of the solid. Unlike `id`, this doesn't change. | No |
|
||||
| `value` |`[` [`ExtrudeSurface`](/docs/kcl/types/ExtrudeSurface) `]`| The extrude surfaces. | No |
|
||||
| `sketch` |[`Sketch`](/docs/kcl/types/Sketch)| The sketch. | No |
|
||||
| `height` |[`number`](/docs/kcl/types/number)| The height of the solid. | No |
|
||||
| `startCapId` |[`string`](/docs/kcl/types/string)| The id of the extrusion start cap | No |
|
||||
| `endCapId` |[`string`](/docs/kcl/types/string)| The id of the extrusion end cap | No |
|
||||
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||
|
||||
|
||||
----
|
||||
Data for an imported geometry.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `importedGeometry`| | No |
|
||||
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
|
||||
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
@ -33,7 +33,6 @@ A solid or a group of solids.
|
||||
| `endCapId` |[`string`](/docs/kcl/types/string)| The id of the extrusion end cap | No |
|
||||
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
||||
|
||||
|
||||
----
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,4 +1,5 @@
|
||||
import { test, expect, Page } from './zoo-test'
|
||||
import { Page } from '@playwright/test'
|
||||
import { test, expect } from './zoo-test'
|
||||
import {
|
||||
getUtils,
|
||||
TEST_COLORS,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { test, expect, Page } from './zoo-test'
|
||||
import { Page } from '@playwright/test'
|
||||
import { test, expect } from './zoo-test'
|
||||
import { HomePageFixture } from './fixtures/homePageFixture'
|
||||
import { getUtils } from './test-utils'
|
||||
import { EngineCommand } from 'lang/std/artifactGraph'
|
||||
|
@ -10,7 +10,11 @@ import fsp from 'fs/promises'
|
||||
test(
|
||||
'export works on the first try',
|
||||
{ tag: ['@electron', '@skipLocalEngine'] },
|
||||
async ({ page, context, scene }, testInfo) => {
|
||||
async ({ page, context, scene, tronApp }, testInfo) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
await Promise.all([fsp.mkdir(bracketDir, { recursive: true })])
|
||||
@ -86,7 +90,7 @@ test(
|
||||
await expect(exportingToastMessage).not.toBeVisible()
|
||||
|
||||
const firstFileFullPath = path.resolve(
|
||||
getPlaywrightDownloadDir(page),
|
||||
getPlaywrightDownloadDir(tronApp.projectDirName),
|
||||
exportFileName
|
||||
)
|
||||
await test.step('Check the export size', async () => {
|
||||
@ -165,7 +169,7 @@ test(
|
||||
]))
|
||||
|
||||
const secondFileFullPath = path.resolve(
|
||||
getPlaywrightDownloadDir(page),
|
||||
getPlaywrightDownloadDir(tronApp.projectDirName),
|
||||
exportFileName
|
||||
)
|
||||
await test.step('Check the export size', async () => {
|
||||
|
@ -274,7 +274,6 @@ test.describe('Feature Tree pane', () => {
|
||||
currentArgKey: 'distance',
|
||||
currentArgValue: initialInput,
|
||||
headerArguments: {
|
||||
Selection: '1 face',
|
||||
Distance: initialInput,
|
||||
},
|
||||
highlightedHeaderArg: 'distance',
|
||||
@ -291,7 +290,6 @@ test.describe('Feature Tree pane', () => {
|
||||
await cmdBar.expectState({
|
||||
stage: 'review',
|
||||
headerArguments: {
|
||||
Selection: '1 face',
|
||||
// The calculated value is shown in the argument summary
|
||||
Distance: initialInput,
|
||||
},
|
||||
|
@ -158,11 +158,14 @@ test.describe('when using the file tree to', () => {
|
||||
await createNewFile('lee')
|
||||
|
||||
await test.step('Postcondition: there are 5 new lee-*.kcl files', async () => {
|
||||
await expect(
|
||||
page
|
||||
.locator('[data-testid="file-pane-scroll-container"] button')
|
||||
.filter({ hasText: /lee[-]?[0-5]?/ })
|
||||
).toHaveCount(5)
|
||||
await expect
|
||||
.poll(() =>
|
||||
page
|
||||
.locator('[data-testid="file-pane-scroll-container"] button')
|
||||
.filter({ hasText: /lee[-]?[0-5]?/ })
|
||||
.count()
|
||||
)
|
||||
.toEqual(5)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
@ -27,28 +27,19 @@ type CmdBarSerialised =
|
||||
|
||||
export class CmdBarFixture {
|
||||
public page: Page
|
||||
|
||||
get cmdBarOpenBtn() {
|
||||
return this.page.getByTestId('command-bar-open-button')
|
||||
}
|
||||
|
||||
get cmdBarElement() {
|
||||
return this.page.getByTestId('command-bar')
|
||||
}
|
||||
public cmdBarOpenBtn!: Locator
|
||||
public cmdBarElement!: Locator
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page
|
||||
this.cmdBarOpenBtn = this.page.getByTestId('command-bar-open-button')
|
||||
this.cmdBarElement = this.page.getByTestId('command-bar')
|
||||
}
|
||||
|
||||
get currentArgumentInput() {
|
||||
return this.page.getByTestId('cmd-bar-arg-value')
|
||||
}
|
||||
|
||||
// Put all selectors here because this method is re-run on fixture creation.
|
||||
reConstruct = (page: Page) => {
|
||||
this.page = page
|
||||
}
|
||||
|
||||
private _serialiseCmdBar = async (): Promise<CmdBarSerialised> => {
|
||||
if (!(await this.page.getByTestId('command-bar-wrapper').isVisible())) {
|
||||
return { stage: 'commandBarClosed' }
|
||||
|
@ -24,11 +24,6 @@ export class EditorFixture {
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page
|
||||
this.reConstruct(page)
|
||||
}
|
||||
reConstruct = (page: Page) => {
|
||||
this.page = page
|
||||
|
||||
this.codeContent = page.locator('.cm-content[data-language="kcl"]')
|
||||
this.diagnosticsTooltip = page.locator('.cm-tooltip-lint')
|
||||
this.diagnosticsGutterIcon = page.locator('.cm-lint-marker-error')
|
||||
@ -87,6 +82,30 @@ export class EditorFixture {
|
||||
toContain: this._expectEditorToContain(),
|
||||
not: { toContain: this._expectEditorToContain(true) },
|
||||
}
|
||||
snapshot = async (options?: { timeout?: number; name?: string }) => {
|
||||
const wasPaneOpen = await this.checkIfPaneIsOpen()
|
||||
if (!wasPaneOpen) {
|
||||
await this.openPane()
|
||||
}
|
||||
|
||||
try {
|
||||
// Use expect.poll to implement retry logic
|
||||
await expect
|
||||
.poll(
|
||||
async () => {
|
||||
const code = await this.codeContent.textContent()
|
||||
return code || ''
|
||||
},
|
||||
{ timeout: options?.timeout || 5000 }
|
||||
)
|
||||
.toMatchSnapshot(options?.name || 'editor-content')
|
||||
} finally {
|
||||
// Reset pane state if needed
|
||||
if (!wasPaneOpen) {
|
||||
await this.closePane()
|
||||
}
|
||||
}
|
||||
}
|
||||
private _serialiseDiagnostics = async (): Promise<Array<string>> => {
|
||||
const diagnostics = await this.diagnosticsGutterIcon.all()
|
||||
const diagnosticsContent: string[] = []
|
||||
|
@ -1,13 +1,31 @@
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
|
||||
import type {
|
||||
BrowserContext,
|
||||
ElectronApplication,
|
||||
Fixtures as PlaywrightFixtures,
|
||||
TestInfo,
|
||||
Page,
|
||||
} from '@playwright/test'
|
||||
|
||||
import { getUtils, setup, setupElectron } from '../test-utils'
|
||||
import {
|
||||
_electron as electron,
|
||||
PlaywrightTestArgs,
|
||||
PlaywrightWorkerArgs,
|
||||
} from '@playwright/test'
|
||||
|
||||
import * as TOML from '@iarna/toml'
|
||||
import {
|
||||
TEST_SETTINGS_KEY,
|
||||
TEST_SETTINGS_CORRUPTED,
|
||||
TEST_SETTINGS,
|
||||
TEST_SETTINGS_DEFAULT_THEME,
|
||||
} from '../storageStates'
|
||||
import { SETTINGS_FILE_NAME, PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
|
||||
import { getUtils, setup } from '../test-utils'
|
||||
import fsp from 'fs/promises'
|
||||
import { join } from 'path'
|
||||
import fs from 'node:fs'
|
||||
import path from 'path'
|
||||
import { CmdBarFixture } from './cmdBarFixture'
|
||||
import { EditorFixture } from './editorFixture'
|
||||
import { ToolbarFixture } from './toolbarFixture'
|
||||
@ -23,7 +41,7 @@ export class AuthenticatedApp {
|
||||
public readonly testInfo: TestInfo
|
||||
public readonly viewPortSize = { width: 1200, height: 500 }
|
||||
public electronApp: undefined | ElectronApplication
|
||||
public dir: string = ''
|
||||
public projectDirName: string = ''
|
||||
|
||||
constructor(context: BrowserContext, page: Page, testInfo: TestInfo) {
|
||||
this.context = context
|
||||
@ -46,7 +64,7 @@ export class AuthenticatedApp {
|
||||
}
|
||||
getInputFile = (fileName: string) => {
|
||||
return fsp.readFile(
|
||||
join('rust', 'kcl-lib', 'e2e', 'executor', 'inputs', fileName),
|
||||
path.join('rust', 'kcl-lib', 'e2e', 'executor', 'inputs', fileName),
|
||||
'utf-8'
|
||||
)
|
||||
}
|
||||
@ -59,101 +77,300 @@ export interface Fixtures {
|
||||
scene: SceneFixture
|
||||
homePage: HomePageFixture
|
||||
}
|
||||
export class AuthenticatedTronApp {
|
||||
public originalPage: Page
|
||||
public page: Page
|
||||
public browserContext: BrowserContext
|
||||
public context: BrowserContext
|
||||
public readonly testInfo: TestInfo
|
||||
public electronApp: ElectronApplication | undefined
|
||||
public readonly viewPortSize = { width: 1200, height: 500 }
|
||||
public dir: string = ''
|
||||
|
||||
constructor(
|
||||
browserContext: BrowserContext,
|
||||
originalPage: Page,
|
||||
testInfo: TestInfo
|
||||
) {
|
||||
this.page = originalPage
|
||||
this.originalPage = originalPage
|
||||
this.browserContext = browserContext
|
||||
// Will be overwritten in the initializer
|
||||
this.context = browserContext
|
||||
this.testInfo = testInfo
|
||||
}
|
||||
async initialise(
|
||||
arg: {
|
||||
fixtures: Partial<Fixtures>
|
||||
folderSetupFn?: (projectDirName: string) => Promise<void>
|
||||
cleanProjectDir?: boolean
|
||||
appSettings?: DeepPartial<Settings>
|
||||
} = { fixtures: {} }
|
||||
) {
|
||||
const { electronApp, page, context, dir } = await setupElectron({
|
||||
testInfo: this.testInfo,
|
||||
folderSetupFn: arg.folderSetupFn,
|
||||
cleanProjectDir: arg.cleanProjectDir,
|
||||
appSettings: arg.appSettings,
|
||||
viewport: this.viewPortSize,
|
||||
export class ElectronZoo {
|
||||
public available: boolean = true
|
||||
public electron!: ElectronApplication
|
||||
public firstUrl = ''
|
||||
public viewPortSize = { width: 1200, height: 500 }
|
||||
public projectDirName = ''
|
||||
|
||||
public page!: Page
|
||||
public context!: BrowserContext
|
||||
|
||||
constructor() {}
|
||||
|
||||
async makeAvailableAgain() {
|
||||
// Help remote end by signaling we're done with the connection.
|
||||
await this.page.evaluate(async () => {
|
||||
return new Promise((resolve) => {
|
||||
if (!window.engineCommandManager.engineConnection?.state?.type) {
|
||||
return resolve(undefined)
|
||||
}
|
||||
|
||||
window.engineCommandManager.tearDown()
|
||||
// Keep polling (per js event tick) until state is Disconnected.
|
||||
const checkDisconnected = () => {
|
||||
// It's possible we never even created an engineConnection
|
||||
// e.g. never left Projects view.
|
||||
if (
|
||||
window.engineCommandManager?.engineConnection?.state.type ===
|
||||
'disconnected'
|
||||
) {
|
||||
return resolve(undefined)
|
||||
}
|
||||
setTimeout(checkDisconnected, 0)
|
||||
}
|
||||
checkDisconnected()
|
||||
})
|
||||
})
|
||||
this.page = page
|
||||
|
||||
// These assignments "fix" some brokenness in the Playwright Workbench when
|
||||
// running against electron applications.
|
||||
// The timeline is still broken but failure screenshots work again.
|
||||
this.context = context
|
||||
// TODO: try to get this to work again for screenshots, but it messed with test ends when enabled
|
||||
// Object.assign(this.browserContext, this.context)
|
||||
await this.context.tracing.stopChunk({ path: 'trace.zip' })
|
||||
|
||||
this.electronApp = electronApp
|
||||
this.dir = dir
|
||||
// Only after cleanup we're ready.
|
||||
this.available = true
|
||||
}
|
||||
|
||||
// Easier to access throughout utils
|
||||
this.page.dir = dir
|
||||
async createInstanceIfMissing(testInfo: TestInfo) {
|
||||
// Create or otherwise clear the folder.
|
||||
this.projectDirName = testInfo.outputPath('electron-test-projects-dir')
|
||||
|
||||
// Setup localStorage, addCookies, reload
|
||||
await setup(this.context, this.page, this.testInfo)
|
||||
// We need to expose this in order for some tests that require folder
|
||||
// creation and some code below.
|
||||
const that = this
|
||||
|
||||
for (const key of unsafeTypedKeys(arg.fixtures)) {
|
||||
const fixture = arg.fixtures[key]
|
||||
if (
|
||||
!fixture ||
|
||||
fixture instanceof AuthenticatedApp ||
|
||||
fixture instanceof AuthenticatedTronApp
|
||||
)
|
||||
continue
|
||||
fixture.reConstruct(page)
|
||||
const options = {
|
||||
args: ['.', '--no-sandbox'],
|
||||
env: {
|
||||
...process.env,
|
||||
TEST_SETTINGS_FILE_KEY: this.projectDirName,
|
||||
IS_PLAYWRIGHT: 'true',
|
||||
},
|
||||
...(process.env.ELECTRON_OVERRIDE_DIST_PATH
|
||||
? {
|
||||
executablePath:
|
||||
process.env.ELECTRON_OVERRIDE_DIST_PATH + 'electron',
|
||||
}
|
||||
: {}),
|
||||
...(process.env.PLAYWRIGHT_RECORD_VIDEO
|
||||
? {
|
||||
recordVideo: {
|
||||
dir: testInfo.snapshotPath(),
|
||||
size: this.viewPortSize,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
}
|
||||
|
||||
// Do this once and then reuse window on subsequent calls.
|
||||
if (!this.electron) {
|
||||
this.electron = await electron.launch(options)
|
||||
this.context = this.electron.context()
|
||||
this.page = await this.electron.firstWindow()
|
||||
await this.context.tracing.start({ screenshots: true, snapshots: true })
|
||||
}
|
||||
|
||||
await this.context.tracing.startChunk()
|
||||
|
||||
await setup(this.context, this.page, testInfo)
|
||||
|
||||
await this.cleanProjectDir()
|
||||
|
||||
// Create a consistent way to resize the page across electron and web.
|
||||
// (lee) I had to do everything in the book to make electron change its
|
||||
// damn window size. I succeeded in making it consistently and reliably
|
||||
// do it after a whole afternoon.
|
||||
this.page.setBodyDimensions = async function (dims: {
|
||||
width: number
|
||||
height: number
|
||||
}) {
|
||||
await this.setViewportSize(dims)
|
||||
|
||||
await that.electron?.evaluateHandle(async ({ app }, dims) => {
|
||||
// @ts-ignore sorry jon but see comment in main.ts why this is ignored
|
||||
await app.resizeWindow(dims.width, dims.height)
|
||||
}, dims)
|
||||
|
||||
return this.evaluate(async (dims: { width: number; height: number }) => {
|
||||
await window.electron.resizeWindow(dims.width, dims.height)
|
||||
window.document.body.style.width = dims.width + 'px'
|
||||
window.document.body.style.height = dims.height + 'px'
|
||||
window.document.documentElement.style.width = dims.width + 'px'
|
||||
window.document.documentElement.style.height = dims.height + 'px'
|
||||
}, dims)
|
||||
}
|
||||
|
||||
await this.page.setBodyDimensions(this.viewPortSize)
|
||||
|
||||
this.context.folderSetupFn = async function (fn) {
|
||||
return fn(that.projectDirName)
|
||||
.then(() => that.page.reload())
|
||||
.then(() => ({
|
||||
dir: that.projectDirName,
|
||||
}))
|
||||
}
|
||||
|
||||
// We need to patch this because addInitScript will bind too late in our
|
||||
// electron tests, never running. We need to call reload() after each call
|
||||
// to guarantee it runs.
|
||||
const oldContextAddInitScript = this.context.addInitScript
|
||||
this.context.addInitScript = async function (a, b) {
|
||||
// @ts-ignore pretty sure way out of tsc's type checking capabilities.
|
||||
// This code works perfectly fine.
|
||||
await oldContextAddInitScript.apply(this, [a, b])
|
||||
await that.page.reload()
|
||||
}
|
||||
|
||||
// No idea why we mix and match page and context's addInitScript but we do
|
||||
const oldPageAddInitScript = this.page.addInitScript
|
||||
this.page.addInitScript = async function (a: any, b: any) {
|
||||
// @ts-ignore pretty sure way out of tsc's type checking capabilities.
|
||||
// This code works perfectly fine.
|
||||
await oldPageAddInitScript.apply(this, [a, b])
|
||||
await that.page.reload()
|
||||
}
|
||||
|
||||
if (!this.firstUrl) {
|
||||
await this.page.getByText('Your Projects').count()
|
||||
this.firstUrl = this.page.url()
|
||||
}
|
||||
|
||||
// Due to the app controlling its own window context we need to inject new
|
||||
// options and context here.
|
||||
// NOTE TO LEE: Seems to destroy page context when calling an electron loadURL.
|
||||
// await tronApp.electronApp.evaluate(({ app }) => {
|
||||
// return app.reuseWindowForTest();
|
||||
// });
|
||||
|
||||
await this.electron?.evaluate(({ app }, projectDirName) => {
|
||||
// @ts-ignore can't declaration merge see main.ts
|
||||
app.testProperty['TEST_SETTINGS_FILE_KEY'] = projectDirName
|
||||
}, this.projectDirName)
|
||||
|
||||
// Always start at the root view
|
||||
await this.page.goto(this.firstUrl)
|
||||
|
||||
// Force a hard reload, destroying the stream and other state
|
||||
await this.page.reload()
|
||||
}
|
||||
|
||||
close = async () => {
|
||||
await this.electronApp?.close?.()
|
||||
async cleanProjectDir(appSettings?: DeepPartial<Settings>) {
|
||||
try {
|
||||
if (fs.existsSync(this.projectDirName)) {
|
||||
await fsp.rm(this.projectDirName, { recursive: true })
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
try {
|
||||
await fsp.mkdir(this.projectDirName)
|
||||
} catch (e) {
|
||||
// Not a problem if it already exists.
|
||||
}
|
||||
|
||||
const tempSettingsFilePath = path.join(
|
||||
this.projectDirName,
|
||||
SETTINGS_FILE_NAME
|
||||
)
|
||||
|
||||
let settingsOverridesToml = ''
|
||||
|
||||
if (appSettings) {
|
||||
settingsOverridesToml = TOML.stringify({
|
||||
// @ts-expect-error
|
||||
settings: {
|
||||
...TEST_SETTINGS,
|
||||
...appSettings,
|
||||
app: {
|
||||
...TEST_SETTINGS.app,
|
||||
project_directory: this.projectDirName,
|
||||
...appSettings.app,
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
settingsOverridesToml = TOML.stringify({
|
||||
// @ts-expect-error
|
||||
settings: {
|
||||
...TEST_SETTINGS,
|
||||
app: {
|
||||
...TEST_SETTINGS.app,
|
||||
project_directory: this.projectDirName,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
await fsp.writeFile(tempSettingsFilePath, settingsOverridesToml)
|
||||
}
|
||||
debugPause = () =>
|
||||
new Promise(() => {
|
||||
console.log('UN-RESOLVING PROMISE')
|
||||
})
|
||||
}
|
||||
|
||||
export const fixtures = {
|
||||
cmdBar: async ({ page }: { page: Page }, use: any) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
// If yee encounter this, please try to type it.
|
||||
type FnUse = any
|
||||
|
||||
const fixturesForElectron = {
|
||||
page: async (
|
||||
{ tronApp }: { tronApp: ElectronZoo },
|
||||
use: FnUse,
|
||||
testInfo: TestInfo
|
||||
) => {
|
||||
await tronApp.createInstanceIfMissing(testInfo)
|
||||
await use(tronApp.page)
|
||||
await tronApp?.makeAvailableAgain()
|
||||
},
|
||||
context: async (
|
||||
{ tronApp }: { tronApp: ElectronZoo },
|
||||
use: FnUse,
|
||||
testInfo: TestInfo
|
||||
) => {
|
||||
await tronApp.createInstanceIfMissing(testInfo)
|
||||
await use(tronApp.context)
|
||||
},
|
||||
}
|
||||
|
||||
const fixturesForWeb = {
|
||||
page: async (
|
||||
{ page, context }: { page: Page; context: BrowserContext },
|
||||
use: FnUse,
|
||||
testInfo: TestInfo
|
||||
) => {
|
||||
page.setBodyDimensions = page.setViewportSize
|
||||
|
||||
// We do the same thing in ElectronZoo. addInitScript simply doesn't fire
|
||||
// at the correct time, so we reload the page and it fires appropriately.
|
||||
const oldPageAddInitScript = page.addInitScript
|
||||
page.addInitScript = async function (...args) {
|
||||
// @ts-expect-error
|
||||
await oldPageAddInitScript.apply(this, args)
|
||||
await page.reload()
|
||||
}
|
||||
|
||||
const oldContextAddInitScript = context.addInitScript
|
||||
context.addInitScript = async function (...args) {
|
||||
// @ts-expect-error
|
||||
await oldContextAddInitScript.apply(this, args)
|
||||
await page.reload()
|
||||
}
|
||||
|
||||
const webApp = new AuthenticatedApp(context, page, testInfo)
|
||||
await webApp.initialise()
|
||||
|
||||
await use(page)
|
||||
},
|
||||
}
|
||||
|
||||
const fixturesBasedOnProcessEnvPlatform = {
|
||||
cmdBar: async ({ page }: { page: Page }, use: FnUse) => {
|
||||
await use(new CmdBarFixture(page))
|
||||
},
|
||||
editor: async ({ page }: { page: Page }, use: any) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
editor: async ({ page }: { page: Page }, use: FnUse) => {
|
||||
await use(new EditorFixture(page))
|
||||
},
|
||||
toolbar: async ({ page }: { page: Page }, use: any) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
toolbar: async ({ page }: { page: Page }, use: FnUse) => {
|
||||
await use(new ToolbarFixture(page))
|
||||
},
|
||||
scene: async ({ page }: { page: Page }, use: any) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
scene: async ({ page }: { page: Page }, use: FnUse) => {
|
||||
await use(new SceneFixture(page))
|
||||
},
|
||||
homePage: async ({ page }: { page: Page }, use: any) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
homePage: async ({ page }: { page: Page }, use: FnUse) => {
|
||||
await use(new HomePageFixture(page))
|
||||
},
|
||||
}
|
||||
|
||||
if (process.env.PLATFORM === 'web') {
|
||||
Object.assign(fixturesBasedOnProcessEnvPlatform, fixturesForWeb)
|
||||
} else {
|
||||
Object.assign(fixturesBasedOnProcessEnvPlatform, fixturesForElectron)
|
||||
}
|
||||
|
||||
export { fixturesBasedOnProcessEnvPlatform }
|
||||
|
@ -27,10 +27,6 @@ export class HomePageFixture {
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page
|
||||
this.reConstruct(page)
|
||||
}
|
||||
reConstruct = (page: Page) => {
|
||||
this.page = page
|
||||
|
||||
this.projectSection = this.page.getByTestId('home-section')
|
||||
|
||||
@ -96,8 +92,12 @@ export class HomePageFixture {
|
||||
}
|
||||
}
|
||||
|
||||
createAndGoToProject = async (projectTitle = 'project-$nnn') => {
|
||||
projectsLoaded = async () => {
|
||||
await expect(this.projectSection).not.toHaveText('Loading your Projects...')
|
||||
}
|
||||
|
||||
createAndGoToProject = async (projectTitle = 'project-$nnn') => {
|
||||
await this.projectsLoaded()
|
||||
await this.projectButtonNew.click()
|
||||
await this.projectTextName.click()
|
||||
await this.projectTextName.fill(projectTitle)
|
||||
|
@ -53,7 +53,12 @@ export class SceneFixture {
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page
|
||||
this.reConstruct(page)
|
||||
this.streamWrapper = page.getByTestId('stream')
|
||||
this.networkToggleConnected = page.getByTestId('network-toggle-ok')
|
||||
this.loadingIndicator = this.streamWrapper.getByTestId('loading')
|
||||
this.startEditSketchBtn = page
|
||||
.getByRole('button', { name: 'Start Sketch' })
|
||||
.or(page.getByRole('button', { name: 'Edit Sketch' }))
|
||||
}
|
||||
private _serialiseScene = async (): Promise<SceneSerialised> => {
|
||||
const camera = await this.getCameraInfo()
|
||||
@ -72,17 +77,6 @@ export class SceneFixture {
|
||||
.toEqual(expected)
|
||||
}
|
||||
|
||||
reConstruct = (page: Page) => {
|
||||
this.page = page
|
||||
|
||||
this.streamWrapper = page.getByTestId('stream')
|
||||
this.networkToggleConnected = page.getByTestId('network-toggle-ok')
|
||||
this.loadingIndicator = this.streamWrapper.getByTestId('loading')
|
||||
this.startEditSketchBtn = page
|
||||
.getByRole('button', { name: 'Start Sketch' })
|
||||
.or(page.getByRole('button', { name: 'Edit Sketch' }))
|
||||
}
|
||||
|
||||
makeMouseHelpers = (
|
||||
x: number,
|
||||
y: number,
|
||||
@ -253,7 +247,7 @@ export class SceneFixture {
|
||||
|
||||
await u.openDebugPanel()
|
||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||
await u.clearAndCloseDebugPanel()
|
||||
await u.closeDebugPanel()
|
||||
|
||||
await this.waitForExecutionDone()
|
||||
await expect(this.startEditSketchBtn).not.toBeDisabled()
|
||||
|
@ -37,13 +37,12 @@ export class ToolbarFixture {
|
||||
featureTreeId = 'feature-tree' as const
|
||||
/** The pane element for the Feature Tree */
|
||||
featureTreePane!: Locator
|
||||
gizmo!: Locator
|
||||
gizmoDisabled!: Locator
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page
|
||||
this.reConstruct(page)
|
||||
}
|
||||
reConstruct = (page: Page) => {
|
||||
this.page = page
|
||||
|
||||
this.extrudeButton = page.getByTestId('extrude')
|
||||
this.loftButton = page.getByTestId('loft')
|
||||
this.sweepButton = page.getByTestId('sweep')
|
||||
@ -67,6 +66,13 @@ export class ToolbarFixture {
|
||||
this.filePane = page.locator('#files-pane')
|
||||
this.featureTreePane = page.locator('#feature-tree-pane')
|
||||
this.fileCreateToast = page.getByText('Successfully created')
|
||||
|
||||
// Note to test writers: having two locators like this is preferable to one
|
||||
// which changes another el property because it means our test "signal" is
|
||||
// completely decoupled from the elements themselves. It means the same
|
||||
// element or two different elements can represent these states.
|
||||
this.gizmo = page.getByTestId('gizmo')
|
||||
this.gizmoDisabled = page.getByTestId('gizmo-disabled')
|
||||
}
|
||||
|
||||
get editSketchBtn() {
|
||||
@ -86,6 +92,18 @@ export class ToolbarFixture {
|
||||
startSketchPlaneSelection = async () =>
|
||||
doAndWaitForImageDiff(this.page, () => this.startSketchBtn.click(), 500)
|
||||
|
||||
waitUntilSketchingReady = async () => {
|
||||
await expect(this.gizmoDisabled).toBeVisible()
|
||||
}
|
||||
|
||||
startSketchThenCallbackThenWaitUntilReady = async (
|
||||
cb: () => Promise<void>
|
||||
) => {
|
||||
await this.startSketchBtn.click()
|
||||
await cb()
|
||||
await this.waitUntilSketchingReady()
|
||||
}
|
||||
|
||||
exitSketch = async () => {
|
||||
await this.exitSketchBtn.click()
|
||||
await expect(
|
||||
|
@ -21,58 +21,54 @@ import { expectPixelColor } from './fixtures/sceneFixture'
|
||||
// we must set it to empty for the tests where we want to see the onboarding immediately.
|
||||
|
||||
test.describe('Onboarding tests', () => {
|
||||
test(
|
||||
'Onboarding code is shown in the editor',
|
||||
{
|
||||
appSettings: {
|
||||
app: {
|
||||
onboarding_status: '',
|
||||
},
|
||||
},
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
async ({ page, homePage }) => {
|
||||
const u = await getUtils(page)
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
// Test that the onboarding pane loaded
|
||||
await expect(
|
||||
page.getByText('Welcome to Modeling App! This')
|
||||
).toBeVisible()
|
||||
|
||||
// Test that the onboarding pane loaded
|
||||
await expect(
|
||||
page.getByText('Welcome to Modeling App! This')
|
||||
).toBeVisible()
|
||||
|
||||
// *and* that the code is shown in the editor
|
||||
await expect(page.locator('.cm-content')).toContainText(
|
||||
'// Shelf Bracket'
|
||||
)
|
||||
|
||||
// Make sure the model loaded
|
||||
const XYPlanePoint = { x: 774, y: 116 } as const
|
||||
const modelColor: [number, number, number] = [45, 45, 45]
|
||||
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y)
|
||||
expect(await u.getGreatestPixDiff(XYPlanePoint, modelColor)).toBeLessThan(
|
||||
8
|
||||
)
|
||||
test('Onboarding code is shown in the editor', async ({
|
||||
page,
|
||||
homePage,
|
||||
tronApp,
|
||||
}) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
)
|
||||
await tronApp.cleanProjectDir({
|
||||
app: {
|
||||
onboarding_status: '',
|
||||
},
|
||||
})
|
||||
|
||||
const u = await getUtils(page)
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
// Test that the onboarding pane loaded
|
||||
await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible()
|
||||
|
||||
// Test that the onboarding pane loaded
|
||||
await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible()
|
||||
|
||||
// *and* that the code is shown in the editor
|
||||
await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket')
|
||||
|
||||
// Make sure the model loaded
|
||||
const XYPlanePoint = { x: 774, y: 116 } as const
|
||||
const modelColor: [number, number, number] = [45, 45, 45]
|
||||
await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y)
|
||||
expect(await u.getGreatestPixDiff(XYPlanePoint, modelColor)).toBeLessThan(8)
|
||||
})
|
||||
|
||||
test(
|
||||
'Desktop: fresh onboarding executes and loads',
|
||||
{
|
||||
tag: '@electron',
|
||||
appSettings: {
|
||||
},
|
||||
async ({ page, tronApp }) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
await tronApp.cleanProjectDir({
|
||||
app: {
|
||||
onboarding_status: '',
|
||||
},
|
||||
},
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
async ({ page }) => {
|
||||
})
|
||||
const u = await getUtils(page)
|
||||
|
||||
const viewportSize = { width: 1200, height: 500 }
|
||||
@ -107,223 +103,235 @@ test.describe('Onboarding tests', () => {
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
'Code resets after confirmation',
|
||||
{
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
async ({ context, page, homePage }) => {
|
||||
const initialCode = `sketch001 = startSketchOn('XZ')`
|
||||
test('Code resets after confirmation', async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
tronApp,
|
||||
scene,
|
||||
cmdBar,
|
||||
}) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
await tronApp.cleanProjectDir()
|
||||
|
||||
// Load the page up with some code so we see the confirmation warning
|
||||
// when we go to replay onboarding
|
||||
await context.addInitScript((code) => {
|
||||
localStorage.setItem('persistCode', code)
|
||||
}, initialCode)
|
||||
const initialCode = `sketch001 = startSketchOn('XZ')`
|
||||
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
// Load the page up with some code so we see the confirmation warning
|
||||
// when we go to replay onboarding
|
||||
await page.addInitScript((code) => {
|
||||
localStorage.setItem('persistCode', code)
|
||||
}, initialCode)
|
||||
|
||||
// Replay the onboarding
|
||||
await page.getByRole('link', { name: 'Settings' }).last().click()
|
||||
const replayButton = page.getByRole('button', {
|
||||
name: 'Replay onboarding',
|
||||
})
|
||||
await expect(replayButton).toBeVisible()
|
||||
await replayButton.click()
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
await scene.connectionEstablished()
|
||||
|
||||
// Ensure we see the warning, and that the code has not yet updated
|
||||
await expect(page.getByText('Would you like to create')).toBeVisible()
|
||||
await expect(page.locator('.cm-content')).toHaveText(initialCode)
|
||||
// Replay the onboarding
|
||||
await page.getByRole('link', { name: 'Settings' }).last().click()
|
||||
const replayButton = page.getByRole('button', {
|
||||
name: 'Replay onboarding',
|
||||
})
|
||||
await expect(replayButton).toBeVisible()
|
||||
await replayButton.click()
|
||||
|
||||
const nextButton = page.getByTestId('onboarding-next')
|
||||
// Ensure we see the warning, and that the code has not yet updated
|
||||
await expect(page.getByText('Would you like to create')).toBeVisible()
|
||||
await expect(page.locator('.cm-content')).toHaveText(initialCode)
|
||||
|
||||
const nextButton = page.getByTestId('onboarding-next')
|
||||
await nextButton.hover()
|
||||
await nextButton.click()
|
||||
|
||||
// Ensure we see the introduction and that the code has been reset
|
||||
await expect(page.getByText('Welcome to Modeling App!')).toBeVisible()
|
||||
await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket')
|
||||
|
||||
// There used to be old code here that checked if we stored the reset
|
||||
// code into localStorage but that isn't the case on desktop. It gets
|
||||
// saved to the file system, which we have other tests for.
|
||||
})
|
||||
|
||||
test('Click through each onboarding step and back', async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
tronApp,
|
||||
}) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
await tronApp.cleanProjectDir({
|
||||
app: {
|
||||
onboarding_status: '',
|
||||
},
|
||||
})
|
||||
// Override beforeEach test setup
|
||||
await context.addInitScript(
|
||||
async ({ settingsKey, settings }) => {
|
||||
// Give no initial code, so that the onboarding start is shown immediately
|
||||
localStorage.setItem('persistCode', '')
|
||||
localStorage.setItem(settingsKey, settings)
|
||||
},
|
||||
{
|
||||
settingsKey: TEST_SETTINGS_KEY,
|
||||
settings: settingsToToml({
|
||||
settings: TEST_SETTINGS_ONBOARDING_START,
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
await page.setBodyDimensions({ width: 1200, height: 1080 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
// Test that the onboarding pane loaded
|
||||
await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible()
|
||||
|
||||
const nextButton = page.getByTestId('onboarding-next')
|
||||
const prevButton = page.getByTestId('onboarding-prev')
|
||||
|
||||
while ((await nextButton.innerText()) !== 'Finish') {
|
||||
await nextButton.hover()
|
||||
await nextButton.click()
|
||||
|
||||
// Ensure we see the introduction and that the code has been reset
|
||||
await expect(page.getByText('Welcome to Modeling App!')).toBeVisible()
|
||||
await expect(page.locator('.cm-content')).toContainText(
|
||||
'// Shelf Bracket'
|
||||
)
|
||||
|
||||
// There used to be old code here that checked if we stored the reset
|
||||
// code into localStorage but that isn't the case on desktop. It gets
|
||||
// saved to the file system, which we have other tests for.
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
'Click through each onboarding step and back',
|
||||
{
|
||||
appSettings: {
|
||||
app: {
|
||||
onboarding_status: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ context, page, homePage }) => {
|
||||
// Override beforeEach test setup
|
||||
await context.addInitScript(
|
||||
async ({ settingsKey, settings }) => {
|
||||
// Give no initial code, so that the onboarding start is shown immediately
|
||||
localStorage.setItem('persistCode', '')
|
||||
localStorage.setItem(settingsKey, settings)
|
||||
},
|
||||
{
|
||||
settingsKey: TEST_SETTINGS_KEY,
|
||||
settings: settingsToToml({
|
||||
settings: TEST_SETTINGS_ONBOARDING_START,
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
await page.setBodyDimensions({ width: 1200, height: 1080 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
// Test that the onboarding pane loaded
|
||||
await expect(
|
||||
page.getByText('Welcome to Modeling App! This')
|
||||
).toBeVisible()
|
||||
|
||||
const nextButton = page.getByTestId('onboarding-next')
|
||||
const prevButton = page.getByTestId('onboarding-prev')
|
||||
|
||||
while ((await nextButton.innerText()) !== 'Finish') {
|
||||
await nextButton.hover()
|
||||
await nextButton.click()
|
||||
}
|
||||
|
||||
while ((await prevButton.innerText()) !== 'Dismiss') {
|
||||
await prevButton.hover()
|
||||
await prevButton.click()
|
||||
}
|
||||
|
||||
// Dismiss the onboarding
|
||||
while ((await prevButton.innerText()) !== 'Dismiss') {
|
||||
await prevButton.hover()
|
||||
await prevButton.click()
|
||||
|
||||
// Test that the onboarding pane is gone
|
||||
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
||||
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
'Onboarding redirects and code updating',
|
||||
{
|
||||
appSettings: {
|
||||
app: {
|
||||
onboarding_status: '/export',
|
||||
},
|
||||
// Dismiss the onboarding
|
||||
await prevButton.hover()
|
||||
await prevButton.click()
|
||||
|
||||
// Test that the onboarding pane is gone
|
||||
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
||||
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
||||
})
|
||||
|
||||
test('Onboarding redirects and code updating', async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
tronApp,
|
||||
}) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
await tronApp.cleanProjectDir({
|
||||
app: {
|
||||
onboarding_status: '/export',
|
||||
},
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
async ({ context, page, homePage }) => {
|
||||
const originalCode = 'sigmaAllow = 15000'
|
||||
})
|
||||
|
||||
// Override beforeEach test setup
|
||||
await context.addInitScript(
|
||||
async ({ settingsKey, settings }) => {
|
||||
// Give some initial code, so we can test that it's cleared
|
||||
localStorage.setItem('persistCode', originalCode)
|
||||
localStorage.setItem(settingsKey, settings)
|
||||
},
|
||||
{
|
||||
settingsKey: TEST_SETTINGS_KEY,
|
||||
settings: settingsToToml({
|
||||
settings: TEST_SETTINGS_ONBOARDING_EXPORT,
|
||||
}),
|
||||
}
|
||||
)
|
||||
const originalCode = 'sigmaAllow = 15000'
|
||||
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
// Test that the redirect happened
|
||||
await expect.poll(() => page.url()).toContain('/onboarding/export')
|
||||
|
||||
// Test that you come back to this page when you refresh
|
||||
await page.reload()
|
||||
await expect.poll(() => page.url()).toContain('/onboarding/export')
|
||||
|
||||
// Test that the code changes when you advance to the next step
|
||||
await page.getByTestId('onboarding-next').hover()
|
||||
await page.getByTestId('onboarding-next').click()
|
||||
|
||||
// Test that the onboarding pane loaded
|
||||
const title = page.locator('[data-testid="onboarding-content"]')
|
||||
await expect(title).toBeAttached()
|
||||
|
||||
await expect(page.locator('.cm-content')).not.toHaveText(originalCode)
|
||||
|
||||
// Test that the code is not empty when you click on the next step
|
||||
await page.locator('[data-testid="onboarding-next"]').hover()
|
||||
await page.locator('[data-testid="onboarding-next"]').click()
|
||||
await expect(page.locator('.cm-content')).toHaveText(/.+/)
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
'Onboarding code gets reset to demo on Interactive Numbers step',
|
||||
{
|
||||
appSettings: {
|
||||
app: {
|
||||
onboarding_status: '/parametric-modeling',
|
||||
},
|
||||
// Override beforeEach test setup
|
||||
await context.addInitScript(
|
||||
async ({ settingsKey, settings }) => {
|
||||
// Give some initial code, so we can test that it's cleared
|
||||
localStorage.setItem('persistCode', originalCode)
|
||||
localStorage.setItem(settingsKey, settings)
|
||||
},
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
{
|
||||
settingsKey: TEST_SETTINGS_KEY,
|
||||
settings: settingsToToml({
|
||||
settings: TEST_SETTINGS_ONBOARDING_EXPORT,
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
async ({ page, homePage }) => {
|
||||
const u = await getUtils(page)
|
||||
const badCode = `// This is bad code we shouldn't see`
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
await page.setBodyDimensions({ width: 1200, height: 1080 })
|
||||
await homePage.goToModelingScene()
|
||||
// Test that the redirect happened
|
||||
await expect.poll(() => page.url()).toContain('/onboarding/export')
|
||||
|
||||
await expect
|
||||
.poll(() => page.url())
|
||||
.toContain(onboardingPaths.PARAMETRIC_MODELING)
|
||||
// Test that you come back to this page when you refresh
|
||||
await page.reload()
|
||||
await expect.poll(() => page.url()).toContain('/onboarding/export')
|
||||
|
||||
const bracketNoNewLines = bracket.replace(/\n/g, '')
|
||||
// Test that the code changes when you advance to the next step
|
||||
await page.getByTestId('onboarding-next').hover()
|
||||
await page.getByTestId('onboarding-next').click()
|
||||
|
||||
// Check the code got reset on load
|
||||
await expect(page.locator('#code-pane')).toBeVisible()
|
||||
await expect(u.codeLocator).toHaveText(bracketNoNewLines, {
|
||||
timeout: 10_000,
|
||||
})
|
||||
// Test that the onboarding pane loaded
|
||||
const title = page.locator('[data-testid="onboarding-content"]')
|
||||
await expect(title).toBeAttached()
|
||||
|
||||
// Mess with the code again
|
||||
await u.codeLocator.selectText()
|
||||
await u.codeLocator.fill(badCode)
|
||||
await expect(u.codeLocator).toHaveText(badCode)
|
||||
await expect(page.locator('.cm-content')).not.toHaveText(originalCode)
|
||||
|
||||
// Click to the next step
|
||||
await page.locator('[data-testid="onboarding-next"]').hover()
|
||||
await page.locator('[data-testid="onboarding-next"]').click()
|
||||
await page.waitForURL('**' + onboardingPaths.INTERACTIVE_NUMBERS, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
})
|
||||
// Test that the code is not empty when you click on the next step
|
||||
await page.locator('[data-testid="onboarding-next"]').hover()
|
||||
await page.locator('[data-testid="onboarding-next"]').click()
|
||||
await expect(page.locator('.cm-content')).toHaveText(/.+/)
|
||||
})
|
||||
|
||||
// Check that the code has been reset
|
||||
await expect(u.codeLocator).toHaveText(bracketNoNewLines)
|
||||
test('Onboarding code gets reset to demo on Interactive Numbers step', async ({
|
||||
page,
|
||||
homePage,
|
||||
tronApp,
|
||||
}) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
)
|
||||
await tronApp.cleanProjectDir({
|
||||
app: {
|
||||
onboarding_status: '/parametric-modeling',
|
||||
},
|
||||
})
|
||||
|
||||
const u = await getUtils(page)
|
||||
const badCode = `// This is bad code we shouldn't see`
|
||||
|
||||
await page.setBodyDimensions({ width: 1200, height: 1080 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
await expect
|
||||
.poll(() => page.url())
|
||||
.toContain(onboardingPaths.PARAMETRIC_MODELING)
|
||||
|
||||
const bracketNoNewLines = bracket.replace(/\n/g, '')
|
||||
|
||||
// Check the code got reset on load
|
||||
await expect(page.locator('#code-pane')).toBeVisible()
|
||||
await expect(u.codeLocator).toHaveText(bracketNoNewLines, {
|
||||
timeout: 10_000,
|
||||
})
|
||||
|
||||
// Mess with the code again
|
||||
await u.codeLocator.selectText()
|
||||
await u.codeLocator.fill(badCode)
|
||||
await expect(u.codeLocator).toHaveText(badCode)
|
||||
|
||||
// Click to the next step
|
||||
await page.locator('[data-testid="onboarding-next"]').hover()
|
||||
await page.locator('[data-testid="onboarding-next"]').click()
|
||||
await page.waitForURL('**' + onboardingPaths.INTERACTIVE_NUMBERS, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
})
|
||||
|
||||
// Check that the code has been reset
|
||||
await expect(u.codeLocator).toHaveText(bracketNoNewLines)
|
||||
})
|
||||
|
||||
// (lee) The two avatar tests are weird because even on main, we don't have
|
||||
// anything to do with the avatar inside the onboarding test. Due to the
|
||||
// low impact of an avatar not showing I'm changing this to fixme.
|
||||
test.fixme(
|
||||
'Avatar text updates depending on image load success',
|
||||
{
|
||||
appSettings: {
|
||||
async ({ context, page, homePage, tronApp }) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
|
||||
await tronApp.cleanProjectDir({
|
||||
app: {
|
||||
onboarding_status: '',
|
||||
},
|
||||
},
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
async ({ context, page, homePage }) => {
|
||||
})
|
||||
|
||||
// Override beforeEach test setup
|
||||
await context.addInitScript(
|
||||
async ({ settingsKey, settings }) => {
|
||||
@ -388,15 +396,16 @@ test.describe('Onboarding tests', () => {
|
||||
|
||||
test.fixme(
|
||||
"Avatar text doesn't mention avatar when no avatar",
|
||||
{
|
||||
appSettings: {
|
||||
async ({ context, page, homePage, tronApp }) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
|
||||
await tronApp.cleanProjectDir({
|
||||
app: {
|
||||
onboarding_status: '',
|
||||
},
|
||||
},
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
async ({ context, page, homePage }) => {
|
||||
})
|
||||
// Override beforeEach test setup
|
||||
await context.addInitScript(
|
||||
async ({ settingsKey, settings }) => {
|
||||
@ -444,15 +453,17 @@ test.describe('Onboarding tests', () => {
|
||||
|
||||
test.fixme(
|
||||
'Restarting onboarding on desktop takes one attempt',
|
||||
{
|
||||
appSettings: {
|
||||
async ({ context, page, tronApp }) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
|
||||
await tronApp.cleanProjectDir({
|
||||
app: {
|
||||
onboarding_status: 'dismissed',
|
||||
},
|
||||
},
|
||||
cleanProjectDir: true,
|
||||
},
|
||||
async ({ context, page }) => {
|
||||
})
|
||||
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const routerTemplateDir = join(dir, 'router-template-slate')
|
||||
await fsp.mkdir(routerTemplateDir, { recursive: true })
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { test, expect, Page } from './zoo-test'
|
||||
import { Page } from '@playwright/test'
|
||||
import { test, expect } from './zoo-test'
|
||||
import { EditorFixture } from './fixtures/editorFixture'
|
||||
import { SceneFixture } from './fixtures/sceneFixture'
|
||||
import { ToolbarFixture } from './fixtures/toolbarFixture'
|
||||
|
@ -163,7 +163,7 @@ test(
|
||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
|
||||
timeout: 10_000,
|
||||
})
|
||||
.toBeLessThan(15)
|
||||
.toBeLessThan(20)
|
||||
})
|
||||
|
||||
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
|
||||
@ -464,7 +464,11 @@ test.describe('Can export from electron app', () => {
|
||||
test(
|
||||
`Can export using ${method}`,
|
||||
{ tag: ['@electron', '@skipLocalEngine'] },
|
||||
async ({ context, page }, testInfo) => {
|
||||
async ({ context, page, tronApp }, testInfo) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
await fsp.mkdir(bracketDir, { recursive: true })
|
||||
@ -516,6 +520,7 @@ test.describe('Can export from electron app', () => {
|
||||
storage: 'embedded',
|
||||
presentation: 'pretty',
|
||||
},
|
||||
tronApp.projectDirName,
|
||||
page,
|
||||
method
|
||||
)
|
||||
@ -523,7 +528,7 @@ test.describe('Can export from electron app', () => {
|
||||
})
|
||||
|
||||
const filepath = path.resolve(
|
||||
getPlaywrightDownloadDir(page),
|
||||
getPlaywrightDownloadDir(tronApp.projectDirName),
|
||||
'main.gltf'
|
||||
)
|
||||
|
||||
@ -781,6 +786,7 @@ test(
|
||||
page.on('console', console.log)
|
||||
|
||||
await expect(page.getByText('router-template-slate')).toBeVisible()
|
||||
await expect(page.getByText('Loading your Projects...')).not.toBeVisible()
|
||||
await expect(page.getByText('Your Projects')).toBeVisible()
|
||||
|
||||
await page.keyboard.press('Delete')
|
||||
@ -858,7 +864,7 @@ test.describe(`Project management commands`, () => {
|
||||
test(
|
||||
`Delete from project page`,
|
||||
{ tag: '@electron' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||
const projectName = `my_project_to_delete`
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
|
||||
@ -887,6 +893,8 @@ test.describe(`Project management commands`, () => {
|
||||
|
||||
await projectHomeLink.click()
|
||||
await u.waitForPageLoad()
|
||||
await scene.connectionEstablished()
|
||||
await scene.settled(cmdBar)
|
||||
})
|
||||
|
||||
await test.step(`Run delete command via command palette`, async () => {
|
||||
@ -909,7 +917,7 @@ test.describe(`Project management commands`, () => {
|
||||
test(
|
||||
`Rename from home page`,
|
||||
{ tag: '@electron' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
async ({ context, page, homePage }, testInfo) => {
|
||||
const projectName = `my_project_to_rename`
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
|
||||
@ -936,6 +944,7 @@ test.describe(`Project management commands`, () => {
|
||||
await test.step(`Setup`, async () => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
page.on('console', console.log)
|
||||
await homePage.projectsLoaded()
|
||||
await expect(projectHomeLink).toBeVisible()
|
||||
})
|
||||
|
||||
@ -1682,7 +1691,11 @@ test(
|
||||
test(
|
||||
'You can change the root projects directory and nothing is lost',
|
||||
{ tag: '@electron' },
|
||||
async ({ context, page, electronApp }, testInfo) => {
|
||||
async ({ context, page, tronApp, homePage }, testInfo) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
await Promise.all([
|
||||
fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }),
|
||||
@ -1712,6 +1725,8 @@ test(
|
||||
await fsp.rm(newProjectDirName, { recursive: true })
|
||||
}
|
||||
|
||||
await homePage.projectsLoaded()
|
||||
|
||||
await test.step('We can change the root project directory', async () => {
|
||||
// expect to see the project directory settings link
|
||||
await expect(
|
||||
@ -1725,7 +1740,7 @@ test(
|
||||
.locator('section#projectDirectory input')
|
||||
.inputValue()
|
||||
|
||||
const handleFile = electronApp?.evaluate(
|
||||
const handleFile = tronApp.electron.evaluate(
|
||||
async ({ dialog }, filePaths) => {
|
||||
dialog.showOpenDialog = () =>
|
||||
Promise.resolve({ canceled: false, filePaths })
|
||||
@ -1741,6 +1756,8 @@ test(
|
||||
|
||||
await page.getByTestId('settings-close-button').click()
|
||||
|
||||
await homePage.projectsLoaded()
|
||||
|
||||
await expect(page.getByText('No Projects found')).toBeVisible()
|
||||
await createProject({ name: 'project-000', page, returnHome: true })
|
||||
await expect(
|
||||
@ -1755,7 +1772,7 @@ test(
|
||||
|
||||
await page.getByTestId('project-directory-settings-link').click()
|
||||
|
||||
const handleFile = electronApp?.evaluate(
|
||||
const handleFile = tronApp.electron.evaluate(
|
||||
async ({ dialog }, filePaths) => {
|
||||
dialog.showOpenDialog = () =>
|
||||
Promise.resolve({ canceled: false, filePaths })
|
||||
@ -1767,6 +1784,7 @@ test(
|
||||
await page.getByTestId('project-directory-button').click()
|
||||
await handleFile
|
||||
|
||||
await homePage.projectsLoaded()
|
||||
await expect(page.locator('section#projectDirectory input')).toHaveValue(
|
||||
originalProjectDirName
|
||||
)
|
||||
@ -2000,8 +2018,8 @@ test(
|
||||
|
||||
test(
|
||||
'Settings persist across restarts',
|
||||
{ tag: '@electron', cleanProjectDir: true },
|
||||
async ({ page }, testInfo) => {
|
||||
{ tag: '@electron' },
|
||||
async ({ page, scene, cmdBar }, testInfo) => {
|
||||
await test.step('We can change a user setting like theme', async () => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
@ -2014,6 +2032,10 @@ test(
|
||||
await expect(page.getByTestId('app-theme')).toHaveValue('dark')
|
||||
|
||||
await page.getByTestId('app-theme').selectOption('light')
|
||||
await expect(page.getByTestId('app-theme')).toHaveValue('light')
|
||||
|
||||
// Give time to system for writing to a persistent store
|
||||
await page.waitForTimeout(1000)
|
||||
})
|
||||
|
||||
await test.step('Starting the app again and we can see the same theme', async () => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { test, expect, Page } from './zoo-test'
|
||||
import { Page } from '@playwright/test'
|
||||
import { test, expect } from './zoo-test'
|
||||
import path from 'path'
|
||||
import * as fsp from 'fs/promises'
|
||||
import { getUtils, executorInputPath } from './test-utils'
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { test, expect, Page } from './zoo-test'
|
||||
import { Page } from '@playwright/test'
|
||||
import { test, expect } from './zoo-test'
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import { HomePageFixture } from './fixtures/homePageFixture'
|
||||
@ -2153,6 +2154,8 @@ extrude001 = extrude(profile003, length = 5)
|
||||
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
await page.waitForTimeout(5000)
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Start Sketch' })
|
||||
).not.toBeDisabled()
|
||||
@ -2165,7 +2168,7 @@ extrude001 = extrude(profile003, length = 5)
|
||||
await page.waitForTimeout(600)
|
||||
|
||||
await editor.expectEditor.toContain(`sketch001 = startSketchOn('XZ')`)
|
||||
await toolbar.exitSketchBtn.click()
|
||||
await toolbar.exitSketch()
|
||||
|
||||
await editor.expectEditor.not.toContain(`sketch001 = startSketchOn('XZ')`)
|
||||
|
||||
@ -2181,6 +2184,8 @@ extrude001 = extrude(profile003, length = 5)
|
||||
)`
|
||||
)
|
||||
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
await scene.expectPixelColor([255, 255, 255], { x: 633, y: 211 }, 15)
|
||||
})
|
||||
})
|
||||
|
@ -31,8 +31,7 @@ test.beforeEach(async ({ page, context }) => {
|
||||
// Help engine-manager: tear shit down.
|
||||
test.afterEach(async ({ page }) => {
|
||||
await page.evaluate(() => {
|
||||
// @ts-expect-error
|
||||
window.tearDown()
|
||||
window.engineCommandManager.tearDown()
|
||||
})
|
||||
})
|
||||
|
||||
@ -45,7 +44,11 @@ test.setTimeout(60_000)
|
||||
test.skip(
|
||||
'exports of each format should work',
|
||||
{ tag: ['@snapshot', '@skipWin', '@skipMacos'] },
|
||||
async ({ page, context, scene, cmdBar }) => {
|
||||
async ({ page, context, scene, cmdBar, tronApp }) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
|
||||
// FYI this test doesn't work with only engine running locally
|
||||
// And you will need to have the KittyCAD CLI installed
|
||||
const u = await getUtils(page)
|
||||
@ -134,6 +137,7 @@ part001 = startSketchOn('-XZ')
|
||||
storage: 'ascii',
|
||||
units: 'in',
|
||||
},
|
||||
tronApp.projectDirName,
|
||||
page
|
||||
)
|
||||
)
|
||||
@ -146,6 +150,7 @@ part001 = startSketchOn('-XZ')
|
||||
selection: { type: 'default_scene' },
|
||||
units: 'in',
|
||||
},
|
||||
tronApp.projectDirName,
|
||||
page
|
||||
)
|
||||
)
|
||||
@ -158,6 +163,7 @@ part001 = startSketchOn('-XZ')
|
||||
selection: { type: 'default_scene' },
|
||||
units: 'in',
|
||||
},
|
||||
tronApp.projectDirName,
|
||||
page
|
||||
)
|
||||
)
|
||||
@ -170,6 +176,7 @@ part001 = startSketchOn('-XZ')
|
||||
units: 'in',
|
||||
selection: { type: 'default_scene' },
|
||||
},
|
||||
tronApp.projectDirName,
|
||||
page
|
||||
)
|
||||
)
|
||||
@ -182,6 +189,7 @@ part001 = startSketchOn('-XZ')
|
||||
units: 'in',
|
||||
selection: { type: 'default_scene' },
|
||||
},
|
||||
tronApp.projectDirName,
|
||||
page
|
||||
)
|
||||
)
|
||||
@ -193,6 +201,7 @@ part001 = startSketchOn('-XZ')
|
||||
coords: sysType,
|
||||
units: 'in',
|
||||
},
|
||||
tronApp.projectDirName,
|
||||
page
|
||||
)
|
||||
)
|
||||
@ -203,6 +212,7 @@ part001 = startSketchOn('-XZ')
|
||||
storage: 'embedded',
|
||||
presentation: 'pretty',
|
||||
},
|
||||
tronApp.projectDirName,
|
||||
page
|
||||
)
|
||||
)
|
||||
@ -213,6 +223,7 @@ part001 = startSketchOn('-XZ')
|
||||
storage: 'binary',
|
||||
presentation: 'pretty',
|
||||
},
|
||||
tronApp.projectDirName,
|
||||
page
|
||||
)
|
||||
)
|
||||
@ -223,6 +234,7 @@ part001 = startSketchOn('-XZ')
|
||||
storage: 'standard',
|
||||
presentation: 'pretty',
|
||||
},
|
||||
tronApp.projectDirName,
|
||||
page
|
||||
)
|
||||
)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Binary file not shown.
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 54 KiB |
Binary file not shown.
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
@ -29,5 +29,5 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"kcl_version": "0.2.47"
|
||||
"kcl_version": "0.2.48"
|
||||
}
|
@ -84,7 +84,7 @@ test.describe('Test network and connection issues', () => {
|
||||
'Engine disconnect & reconnect in sketch mode',
|
||||
{ tag: '@skipLocalEngine' },
|
||||
async ({ page, homePage }) => {
|
||||
// TODO: Don't skip Mac for these. After `window.tearDown` is working in Safari, these should work on webkit
|
||||
// TODO: Don't skip Mac for these. After `window.engineCommandManager.tearDown` is working in Safari, these should work on webkit
|
||||
const networkToggle = page.getByTestId('network-toggle')
|
||||
|
||||
const u = await getUtils(page)
|
||||
|
@ -5,8 +5,9 @@ import {
|
||||
_electron as electron,
|
||||
ElectronApplication,
|
||||
Locator,
|
||||
Page,
|
||||
} from '@playwright/test'
|
||||
import { test, Page } from './zoo-test'
|
||||
import { test } from './zoo-test'
|
||||
import { EngineCommand } from 'lang/std/artifactGraph'
|
||||
import fsp from 'fs/promises'
|
||||
import fsSync from 'fs'
|
||||
@ -337,7 +338,7 @@ export const getMovementUtils = (opts: any) => {
|
||||
|
||||
async function waitForAuthAndLsp(page: Page) {
|
||||
const waitForLspPromise = page.waitForEvent('console', {
|
||||
predicate: async (message) => {
|
||||
predicate: async (message: any) => {
|
||||
// it would be better to wait for a message that the kcl lsp has started by looking for the message message.text().includes('[lsp] [window/logMessage]')
|
||||
// but that doesn't seem to make it to the console for macos/safari :(
|
||||
if (message.text().includes('start kcl lsp')) {
|
||||
@ -420,7 +421,7 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
||||
const overlay = page.locator(locator)
|
||||
const bbox = await overlay
|
||||
.boundingBox({ timeout: 5_000 })
|
||||
.then((box) => ({ ...box, x: box?.x || 0, y: box?.y || 0 }))
|
||||
.then((box: any) => ({ ...box, x: box?.x || 0, y: box?.y || 0 }))
|
||||
const angle = Number(await overlay.getAttribute('data-overlay-angle'))
|
||||
const angleXOffset = Math.cos(((angle - 180) * Math.PI) / 180) * px
|
||||
const angleYOffset = Math.sin(((angle - 180) * Math.PI) / 180) * px
|
||||
@ -437,7 +438,7 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
||||
page
|
||||
.locator(locator)
|
||||
.boundingBox({ timeout: 5_000 })
|
||||
.then((box) => ({ ...box, x: box?.x || 0, y: box?.y || 0 })),
|
||||
.then((box: any) => ({ ...box, x: box?.x || 0, y: box?.y || 0 })),
|
||||
codeLocator: page.locator('.cm-content'),
|
||||
crushKclCodeIntoOneLineAndThenMaybeSome: async () => {
|
||||
const code = await page.locator('.cm-content').innerText()
|
||||
@ -504,7 +505,7 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
||||
) => {
|
||||
if (cdpSession === null) {
|
||||
// Use a fail safe if we can't simulate disconnect (on Safari)
|
||||
return page.evaluate('window.tearDown()')
|
||||
return page.evaluate('window.engineCommandManager.tearDown()')
|
||||
}
|
||||
|
||||
return cdpSession?.send(
|
||||
@ -631,7 +632,7 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
||||
panesOpen: async (paneIds: PaneId[]) => {
|
||||
return test?.step(`Setting ${paneIds} panes to be open`, async () => {
|
||||
await page.addInitScript(
|
||||
({ PERSIST_MODELING_CONTEXT, paneIds }) => {
|
||||
({ PERSIST_MODELING_CONTEXT, paneIds }: any) => {
|
||||
localStorage.setItem(
|
||||
PERSIST_MODELING_CONTEXT,
|
||||
JSON.stringify({ openPanes: paneIds })
|
||||
@ -722,14 +723,14 @@ export const makeTemplate: (
|
||||
|
||||
const PLAYWRIGHT_DOWNLOAD_DIR = 'downloads-during-playwright'
|
||||
|
||||
export const getPlaywrightDownloadDir = (page: Page) => {
|
||||
return path.resolve(page.dir, PLAYWRIGHT_DOWNLOAD_DIR)
|
||||
export const getPlaywrightDownloadDir = (rootDir: string) => {
|
||||
return path.resolve(rootDir, PLAYWRIGHT_DOWNLOAD_DIR)
|
||||
}
|
||||
|
||||
const moveDownloadedFileTo = async (page: Page, toLocation: string) => {
|
||||
const moveDownloadedFileTo = async (rootDir: string, toLocation: string) => {
|
||||
await fsp.mkdir(path.dirname(toLocation), { recursive: true })
|
||||
|
||||
const downloadDir = getPlaywrightDownloadDir(page)
|
||||
const downloadDir = getPlaywrightDownloadDir(rootDir)
|
||||
|
||||
// Expect there to be at least one file
|
||||
await expect
|
||||
@ -756,6 +757,7 @@ export interface Paths {
|
||||
|
||||
export const doExport = async (
|
||||
output: Models['OutputFormat_type'],
|
||||
rootDir: string,
|
||||
page: Page,
|
||||
exportFrom: 'dropdown' | 'sidebarButton' | 'commandBar' = 'dropdown'
|
||||
): Promise<Paths> => {
|
||||
@ -836,7 +838,7 @@ export const doExport = async (
|
||||
// (declared in src/lib/exportSave)
|
||||
// To remain consistent with our old web tests, we want to move some downloads
|
||||
// (images) to another directory.
|
||||
await moveDownloadedFileTo(page, downloadLocation)
|
||||
await moveDownloadedFileTo(rootDir, downloadLocation)
|
||||
}
|
||||
|
||||
return {
|
||||
@ -859,12 +861,6 @@ export async function tearDown(page: Page, testInfo: TestInfo) {
|
||||
downloadThroughput: -1,
|
||||
uploadThroughput: -1,
|
||||
})
|
||||
|
||||
// It seems it's best to give the browser about 3s to close things
|
||||
// It's not super reliable but we have no real other choice for now
|
||||
await page.waitForTimeout(3000)
|
||||
|
||||
await testInfo.tronApp?.close()
|
||||
}
|
||||
|
||||
// settingsOverrides may need to be augmented to take more generic items,
|
||||
@ -936,107 +932,11 @@ let electronApp: ElectronApplication | undefined = undefined
|
||||
let context: BrowserContext | undefined = undefined
|
||||
let page: Page | undefined = undefined
|
||||
|
||||
export async function setupElectron({
|
||||
testInfo,
|
||||
cleanProjectDir = true,
|
||||
appSettings,
|
||||
viewport,
|
||||
}: {
|
||||
testInfo: TestInfo
|
||||
folderSetupFn?: (projectDirName: string) => Promise<void>
|
||||
cleanProjectDir?: boolean
|
||||
appSettings?: DeepPartial<Settings>
|
||||
viewport: {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
}): Promise<{
|
||||
electronApp: ElectronApplication
|
||||
context: BrowserContext
|
||||
page: Page
|
||||
dir: string
|
||||
}> {
|
||||
// create or otherwise clear the folder
|
||||
const projectDirName = testInfo.outputPath('electron-test-projects-dir')
|
||||
try {
|
||||
if (fsSync.existsSync(projectDirName) && cleanProjectDir) {
|
||||
await fsp.rm(projectDirName, { recursive: true })
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
if (cleanProjectDir) {
|
||||
await fsp.mkdir(projectDirName)
|
||||
}
|
||||
|
||||
const options = {
|
||||
args: ['.', '--no-sandbox'],
|
||||
env: {
|
||||
...process.env,
|
||||
TEST_SETTINGS_FILE_KEY: projectDirName,
|
||||
IS_PLAYWRIGHT: 'true',
|
||||
},
|
||||
...(process.env.ELECTRON_OVERRIDE_DIST_PATH
|
||||
? { executablePath: process.env.ELECTRON_OVERRIDE_DIST_PATH + 'electron' }
|
||||
: {}),
|
||||
...(process.env.PLAYWRIGHT_RECORD_VIDEO
|
||||
? {
|
||||
recordVideo: {
|
||||
dir: testInfo.snapshotPath(),
|
||||
size: viewport,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
}
|
||||
|
||||
// Do this once and then reuse window on subsequent calls.
|
||||
if (!electronApp) {
|
||||
electronApp = await electron.launch(options)
|
||||
}
|
||||
|
||||
if (!context || !page) {
|
||||
context = electronApp.context()
|
||||
page = await electronApp.firstWindow()
|
||||
context.on('console', console.log)
|
||||
page.on('console', console.log)
|
||||
}
|
||||
|
||||
if (cleanProjectDir) {
|
||||
const tempSettingsFilePath = path.join(projectDirName, SETTINGS_FILE_NAME)
|
||||
const settingsOverrides = settingsToToml(
|
||||
appSettings
|
||||
? {
|
||||
settings: {
|
||||
...TEST_SETTINGS,
|
||||
...appSettings,
|
||||
app: {
|
||||
...TEST_SETTINGS.app,
|
||||
project_directory: projectDirName,
|
||||
...appSettings.app,
|
||||
},
|
||||
},
|
||||
}
|
||||
: {
|
||||
settings: {
|
||||
...TEST_SETTINGS,
|
||||
app: {
|
||||
...TEST_SETTINGS.app,
|
||||
project_directory: projectDirName,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
await fsp.writeFile(tempSettingsFilePath, settingsOverrides)
|
||||
}
|
||||
|
||||
return { electronApp, page, context, dir: projectDirName }
|
||||
}
|
||||
|
||||
function failOnConsoleErrors(page: Page, testInfo?: TestInfo) {
|
||||
// enabled for chrome for now
|
||||
if (page.context().browser()?.browserType().name() === 'chromium') {
|
||||
page.on('pageerror', (exception) => {
|
||||
// No idea wtf exception is
|
||||
page.on('pageerror', (exception: any) => {
|
||||
if (isErrorWhitelisted(exception)) {
|
||||
return
|
||||
}
|
||||
|
@ -1127,7 +1127,6 @@ test.describe('Electron constraint tests', () => {
|
||||
path.join(bracketDir, 'main.kcl')
|
||||
)
|
||||
})
|
||||
const [clickHandler] = scene.makeMouseHelpers(600, 300)
|
||||
|
||||
await test.step('setup test', async () => {
|
||||
await homePage.expectState({
|
||||
@ -1144,8 +1143,12 @@ test.describe('Electron constraint tests', () => {
|
||||
})
|
||||
|
||||
await test.step('Double click to constrain', async () => {
|
||||
await clickHandler()
|
||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||
// Enter sketch edit mode via feature tree
|
||||
await toolbar.openPane('feature-tree')
|
||||
const op = await toolbar.getFeatureTreeOperation('Sketch', 0)
|
||||
await op.dblclick()
|
||||
await toolbar.closePane('feature-tree')
|
||||
|
||||
const child = page
|
||||
.locator('.segment-length-label-text')
|
||||
.first()
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { test, expect, Page } from './zoo-test'
|
||||
import { Page } from '@playwright/test'
|
||||
import { test, expect } from './zoo-test'
|
||||
|
||||
import { deg, getUtils, wiggleMove } from './test-utils'
|
||||
import { LineInputsType } from 'lang/std/sketchcombos'
|
||||
|
@ -257,6 +257,7 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
cmdBar,
|
||||
}) => {
|
||||
test.setTimeout(90_000)
|
||||
const u = await getUtils(page)
|
||||
@ -352,28 +353,15 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
await scene.waitForExecutionDone()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
await u.openAndClearDebugPanel()
|
||||
await u.sendCustomCmd({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_look_at',
|
||||
vantage: { x: 1139.49, y: -7053, z: 8597.31 },
|
||||
center: { x: -2206.68, y: -1298.36, z: 60 },
|
||||
up: { x: 0, y: 0, z: 1 },
|
||||
},
|
||||
})
|
||||
await page.waitForTimeout(100)
|
||||
await u.sendCustomCmd({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_get_settings',
|
||||
},
|
||||
})
|
||||
await page.waitForTimeout(100)
|
||||
const camPosition1 = async () => {
|
||||
await scene.moveCameraTo(
|
||||
{ x: 1139.49, y: -7053, z: 8597.31 },
|
||||
{ x: -2206.68, y: -1298.36, z: 60 }
|
||||
)
|
||||
}
|
||||
await camPosition1()
|
||||
|
||||
const revolve = { x: 635, y: 253 }
|
||||
const parentExtrude = { x: 915, y: 133 }
|
||||
@ -386,7 +374,7 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
||||
await expect(page.locator('.cm-activeLine')).toHaveText(
|
||||
'|> line(end = [0, -pipeLength])'
|
||||
)
|
||||
await u.clearCommandLogs()
|
||||
await u.openAndClearDebugPanel()
|
||||
await page.keyboard.press('Delete')
|
||||
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
|
||||
await page.waitForTimeout(200)
|
||||
@ -399,11 +387,12 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
||||
// and replace the sketch on face with a hard coded custom plane, but since there was a sketch on that plane maybe it
|
||||
// should have delete the sketch? it's broken atm, but not sure if worth fixing since desired behaviour is a little
|
||||
// vague
|
||||
// // DELETE PARENT EXTRUDE
|
||||
// DELETE PARENT EXTRUDE
|
||||
// await camPosition2()
|
||||
// await page.mouse.click(parentExtrude.x, parentExtrude.y)
|
||||
// await page.waitForTimeout(100)
|
||||
// await expect(page.locator('.cm-activeLine')).toHaveText(
|
||||
// '|> line(end = [170.36, -121.61], tag = $seg01)'
|
||||
// '|> line(end = [112.54, 127.64], tag = $seg02)'
|
||||
// )
|
||||
// await u.clearCommandLogs()
|
||||
// await page.keyboard.press('Backspace')
|
||||
@ -463,71 +452,77 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
||||
await page.waitForTimeout(200)
|
||||
await expect(u.codeLocator).not.toContainText(codeToBeDeletedSnippet)
|
||||
})
|
||||
test.fixme(
|
||||
"Deleting solid that the AST mod can't handle results in a toast message",
|
||||
async ({ page, homePage }) => {
|
||||
const u = await getUtils(page)
|
||||
await page.addInitScript(async () => {
|
||||
localStorage.setItem(
|
||||
'persistCode',
|
||||
`sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([-79.26, 95.04], %)
|
||||
|> line(end = [112.54, 127.64], tag = $seg02)
|
||||
|> line(end = [170.36, -121.61], tag = $seg01)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude001 = extrude(sketch001, length = 50)
|
||||
launderExtrudeThroughVar = extrude001
|
||||
sketch002 = startSketchOn(launderExtrudeThroughVar, seg02)
|
||||
|> startProfileAt([-100.54, 16.99], %)
|
||||
|> line(end = [0, 20.03])
|
||||
|> line(end = [62.61, 0], tag = $seg03)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
`
|
||||
)
|
||||
}, KCL_DEFAULT_LENGTH)
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
test('parent Solid should be select and deletable and uses custom planes to position children', async ({
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
cmdBar,
|
||||
editor,
|
||||
}) => {
|
||||
test.setTimeout(90_000)
|
||||
const u = await getUtils(page)
|
||||
await page.addInitScript(async () => {
|
||||
localStorage.setItem(
|
||||
'persistCode',
|
||||
`part001 = startSketchOn('XY')
|
||||
yo = startProfileAt([4.83, 12.56], part001)
|
||||
|> line(end = [15.1, 2.48])
|
||||
|> line(end = [3.15, -9.85], tag = $seg01)
|
||||
|> line(end = [-15.17, -4.1])
|
||||
|> angledLine([segAng(seg01), 12.35], %, $seg02)
|
||||
|> line(end = [-13.02, 10.03])
|
||||
|> close()
|
||||
yoo = extrude(yo, length = 4)
|
||||
sketch002 = startSketchOn(yoo, seg02)
|
||||
sketch001 = startSketchOn(yoo, 'END')
|
||||
profile002 = startProfileAt([-11.08, 2.39], sketch002)
|
||||
|> line(end = [4.89, 0.9])
|
||||
|> line(end = [-0.61, -2.41])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
extrude001 = extrude(profile002, length = 15)
|
||||
profile001 = startProfileAt([7.49, 9.96], sketch001)
|
||||
|> angledLine([0, 5.05], %, $rectangleSegmentA001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001) - 90,
|
||||
4.81
|
||||
], %)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001),
|
||||
-segLen(rectangleSegmentA001)
|
||||
], %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
await u.openDebugPanel()
|
||||
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
|
||||
await u.closeDebugPanel()
|
||||
|
||||
await u.openAndClearDebugPanel()
|
||||
await u.sendCustomCmd({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_look_at',
|
||||
vantage: { x: 1139.49, y: -7053, z: 8597.31 },
|
||||
center: { x: -2206.68, y: -1298.36, z: 60 },
|
||||
up: { x: 0, y: 0, z: 1 },
|
||||
},
|
||||
})
|
||||
await page.waitForTimeout(100)
|
||||
await u.sendCustomCmd({
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_get_settings',
|
||||
},
|
||||
})
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
// attempt delete
|
||||
await page.mouse.click(930, 139)
|
||||
await page.waitForTimeout(100)
|
||||
await expect(page.locator('.cm-activeLine')).toHaveText(
|
||||
'|> line(end = [170.36, -121.61], tag = $seg01)'
|
||||
`
|
||||
)
|
||||
await u.clearCommandLogs()
|
||||
await page.keyboard.press('Delete')
|
||||
}, KCL_DEFAULT_LENGTH)
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
|
||||
await expect(page.getByText('Unable to delete selection')).toBeVisible()
|
||||
}
|
||||
)
|
||||
await homePage.goToModelingScene()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
const extrudeWall = { x: 575, y: 238 }
|
||||
|
||||
// DELETE with selection on face of parent
|
||||
await page.mouse.click(extrudeWall.x, extrudeWall.y)
|
||||
await page.waitForTimeout(100)
|
||||
await expect(page.locator('.cm-activeLine')).toHaveText(
|
||||
'|> line(end = [-15.17, -4.1])'
|
||||
)
|
||||
await u.openAndClearDebugPanel()
|
||||
await page.keyboard.press('Delete')
|
||||
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
await editor.expectEditor.not.toContain(`yoo = extrude(yo, length = 4)`, {
|
||||
shouldNormalise: true,
|
||||
})
|
||||
await editor.expectEditor.toContain(`startSketchOn({plane={origin`, {
|
||||
shouldNormalise: true,
|
||||
})
|
||||
await editor.snapshot()
|
||||
})
|
||||
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
|
||||
page,
|
||||
homePage,
|
||||
|
@ -0,0 +1 @@
|
||||
part001 = startSketchOn('XY')yo = startProfileAt([4.83, 12.56], part001) |> line(end = [15.1, 2.48]) |> line(end = [3.15, -9.85], tag = $seg01) |> line(end = [-15.17, -4.1]) |> angledLine([segAng(seg01), 12.35], %, $seg02) |> line(end = [-13.02, 10.03]) |> close()sketch002 = startSketchOn({ plane = { origin = { x = 7.49, y = 2.4, z = 0 }, xAxis = { x = -0.3, y = 0.95, z = 0 }, yAxis = { x = 0, y = 0, z = 1 }, zAxis = { x = 0.95, y = 0.3, z = 0 } }})sketch001 = startSketchOn({ plane = { origin = { x = 0, y = 0, z = 4 }, xAxis = { x = 1, y = 0, z = 0 }, yAxis = { x = 0, y = 1, z = 0 }, zAxis = { x = 0, y = 0, z = 1 } }})profile002 = startProfileAt([-11.08, 2.39], sketch002) |> line(end = [4.89, 0.9]) |> line(end = [-0.61, -2.41]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()extrude001 = extrude(profile002, length = 15)profile001 = startProfileAt([7.49, 9.96], sketch001) |> angledLine([0, 5.05], %, $rectangleSegmentA001) |> angledLine([ segAng(rectangleSegmentA001) - 90, 4.81 ], %) |> angledLine([ segAng(rectangleSegmentA001), -segLen(rectangleSegmentA001) ], %) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()
|
@ -20,35 +20,40 @@ import { DeepPartial } from 'lib/types'
|
||||
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
||||
|
||||
test.describe('Testing settings', () => {
|
||||
test(
|
||||
'Stored settings are validated and fall back to defaults',
|
||||
test('Stored settings are validated and fall back to defaults', async ({
|
||||
page,
|
||||
homePage,
|
||||
tronApp,
|
||||
}) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
// Override beforeEach test setup
|
||||
// with corrupted settings
|
||||
{
|
||||
appSettings: TEST_SETTINGS_CORRUPTED as DeepPartial<Settings>,
|
||||
},
|
||||
async ({ page, homePage }) => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await tronApp.cleanProjectDir(
|
||||
TEST_SETTINGS_CORRUPTED as DeepPartial<Settings>
|
||||
)
|
||||
|
||||
// Check the settings were reset
|
||||
const storedSettings = tomlToSettings(
|
||||
await page.evaluate(
|
||||
({ settingsKey }) => localStorage.getItem(settingsKey) || '',
|
||||
{ settingsKey: TEST_SETTINGS_KEY }
|
||||
)
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
// Check the settings were reset
|
||||
const storedSettings = tomlToSettings(
|
||||
await page.evaluate(
|
||||
({ settingsKey }) => localStorage.getItem(settingsKey) || '',
|
||||
{ settingsKey: TEST_SETTINGS_KEY }
|
||||
)
|
||||
)
|
||||
|
||||
expect(storedSettings.settings?.app?.theme).toBe('dark')
|
||||
expect(storedSettings.settings?.app?.theme).toBe('dark')
|
||||
|
||||
// Check that the invalid settings were changed to good defaults
|
||||
expect(storedSettings.settings?.modeling?.base_unit).toBe('in')
|
||||
expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo')
|
||||
expect(storedSettings.settings?.app?.project_directory).toBe('')
|
||||
expect(storedSettings.settings?.project?.default_project_name).toBe(
|
||||
'project-$nnn'
|
||||
)
|
||||
}
|
||||
)
|
||||
// Check that the invalid settings were changed to good defaults
|
||||
expect(storedSettings.settings?.modeling?.base_unit).toBe('in')
|
||||
expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo')
|
||||
expect(storedSettings.settings?.app?.project_directory).toBe('')
|
||||
expect(storedSettings.settings?.project?.default_project_name).toBe(
|
||||
'project-$nnn'
|
||||
)
|
||||
})
|
||||
|
||||
// The behavior is actually broken. Parent always takes precedence
|
||||
test.fixme(
|
||||
@ -357,8 +362,6 @@ test.describe('Testing settings', () => {
|
||||
`Load desktop app with no settings file`,
|
||||
{
|
||||
tag: '@electron',
|
||||
// This is what makes no settings file get created
|
||||
cleanProjectDir: false,
|
||||
},
|
||||
async ({ page }, testInfo) => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
@ -379,13 +382,17 @@ test.describe('Testing settings', () => {
|
||||
`Load desktop app with a settings file, but no project directory setting`,
|
||||
{
|
||||
tag: '@electron',
|
||||
appSettings: {
|
||||
},
|
||||
async ({ context, page, tronApp }, testInfo) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
await tronApp.cleanProjectDir({
|
||||
app: {
|
||||
theme_color: '259',
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ context, page }, testInfo) => {
|
||||
})
|
||||
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
// Selectors and constants
|
||||
@ -405,15 +412,20 @@ test.describe('Testing settings', () => {
|
||||
'user settings reload on external change, on project and modeling view',
|
||||
{
|
||||
tag: '@electron',
|
||||
appSettings: {
|
||||
},
|
||||
async ({ context, page, tronApp }, testInfo) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
|
||||
await tronApp.cleanProjectDir({
|
||||
app: {
|
||||
// Doesn't matter what you set it to. It will
|
||||
// default to 264.5
|
||||
theme_color: '0',
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ context, page }, testInfo) => {
|
||||
})
|
||||
|
||||
const { dir: projectDirName } = await context.folderSetupFn(
|
||||
async () => {}
|
||||
)
|
||||
@ -783,128 +795,136 @@ test.describe('Testing settings', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test(
|
||||
`Changing system theme preferences (via media query) should update UI and stream`,
|
||||
{
|
||||
// Override the settings so that the theme is set to `system`
|
||||
appSettings: TEST_SETTINGS_DEFAULT_THEME,
|
||||
},
|
||||
async ({ page, homePage }) => {
|
||||
const u = await getUtils(page)
|
||||
|
||||
// Selectors and constants
|
||||
const darkBackgroundCss = 'oklch(0.3012 0 264.5)'
|
||||
const lightBackgroundCss = 'oklch(0.9911 0 264.5)'
|
||||
const darkBackgroundColor: [number, number, number] = [27, 27, 27]
|
||||
const lightBackgroundColor: [number, number, number] = [245, 245, 245]
|
||||
const streamBackgroundPixelIsColor = async (
|
||||
color: [number, number, number]
|
||||
) => {
|
||||
return u.getGreatestPixDiff({ x: 1000, y: 200 }, color)
|
||||
}
|
||||
const toolbar = page.locator('menu').filter({ hasText: 'Start Sketch' })
|
||||
|
||||
await test.step(`Test setup`, async () => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
await u.waitForPageLoad()
|
||||
await page.waitForTimeout(1000)
|
||||
await expect(toolbar).toBeVisible()
|
||||
})
|
||||
|
||||
await test.step(`Check the background color is light before`, async () => {
|
||||
await expect(toolbar).toHaveCSS('background-color', lightBackgroundCss)
|
||||
await expect
|
||||
.poll(() => streamBackgroundPixelIsColor(lightBackgroundColor))
|
||||
.toBeLessThan(15)
|
||||
})
|
||||
|
||||
await test.step(`Change media query preference to dark, emulating dusk with system theme`, async () => {
|
||||
await page.emulateMedia({ colorScheme: 'dark' })
|
||||
})
|
||||
|
||||
await test.step(`Check the background color is dark after`, async () => {
|
||||
await expect(toolbar).toHaveCSS('background-color', darkBackgroundCss)
|
||||
await expect
|
||||
.poll(() => streamBackgroundPixelIsColor(darkBackgroundColor))
|
||||
.toBeLessThan(15)
|
||||
})
|
||||
test(`Changing system theme preferences (via media query) should update UI and stream`, async ({
|
||||
page,
|
||||
homePage,
|
||||
tronApp,
|
||||
}) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
`Turning off "Show debug panel" with debug panel open leaves no phantom panel`,
|
||||
{
|
||||
await tronApp.cleanProjectDir({
|
||||
// Override the settings so that the theme is set to `system`
|
||||
...TEST_SETTINGS_DEFAULT_THEME,
|
||||
})
|
||||
|
||||
const u = await getUtils(page)
|
||||
|
||||
// Selectors and constants
|
||||
const darkBackgroundCss = 'oklch(0.3012 0 264.5)'
|
||||
const lightBackgroundCss = 'oklch(0.9911 0 264.5)'
|
||||
const darkBackgroundColor: [number, number, number] = [27, 27, 27]
|
||||
const lightBackgroundColor: [number, number, number] = [245, 245, 245]
|
||||
const streamBackgroundPixelIsColor = async (
|
||||
color: [number, number, number]
|
||||
) => {
|
||||
return u.getGreatestPixDiff({ x: 1000, y: 200 }, color)
|
||||
}
|
||||
const toolbar = page.locator('menu').filter({ hasText: 'Start Sketch' })
|
||||
|
||||
await test.step(`Test setup`, async () => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
await u.waitForPageLoad()
|
||||
await page.waitForTimeout(1000)
|
||||
await expect(toolbar).toBeVisible()
|
||||
})
|
||||
|
||||
await test.step(`Check the background color is light before`, async () => {
|
||||
await expect(toolbar).toHaveCSS('background-color', lightBackgroundCss)
|
||||
await expect
|
||||
.poll(() => streamBackgroundPixelIsColor(lightBackgroundColor))
|
||||
.toBeLessThan(15)
|
||||
})
|
||||
|
||||
await test.step(`Change media query preference to dark, emulating dusk with system theme`, async () => {
|
||||
await page.emulateMedia({ colorScheme: 'dark' })
|
||||
})
|
||||
|
||||
await test.step(`Check the background color is dark after`, async () => {
|
||||
await expect(toolbar).toHaveCSS('background-color', darkBackgroundCss)
|
||||
await expect
|
||||
.poll(() => streamBackgroundPixelIsColor(darkBackgroundColor))
|
||||
.toBeLessThan(15)
|
||||
})
|
||||
})
|
||||
|
||||
test(`Turning off "Show debug panel" with debug panel open leaves no phantom panel`, async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
tronApp,
|
||||
}) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
}
|
||||
|
||||
await tronApp.cleanProjectDir({
|
||||
// Override beforeEach test setup
|
||||
// with debug panel open
|
||||
// but "show debug panel" set to false
|
||||
appSettings: {
|
||||
...TEST_SETTINGS,
|
||||
app: { ...TEST_SETTINGS.app, show_debug_panel: false },
|
||||
modeling: { ...TEST_SETTINGS.modeling },
|
||||
},
|
||||
},
|
||||
async ({ context, page, homePage }) => {
|
||||
const u = await getUtils(page)
|
||||
...TEST_SETTINGS,
|
||||
app: { ...TEST_SETTINGS.app, show_debug_panel: false },
|
||||
modeling: { ...TEST_SETTINGS.modeling },
|
||||
})
|
||||
|
||||
await context.addInitScript(async () => {
|
||||
localStorage.setItem(
|
||||
'persistModelingContext',
|
||||
'{"openPanes":["debug"]}'
|
||||
const u = await getUtils(page)
|
||||
|
||||
await context.addInitScript(async () => {
|
||||
localStorage.setItem('persistModelingContext', '{"openPanes":["debug"]}')
|
||||
})
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
// Constants and locators
|
||||
const resizeHandle = page.locator('.sidebar-resize-handles > div.block')
|
||||
const debugPaneButton = page.getByTestId('debug-pane-button')
|
||||
const commandsButton = page.getByRole('button', { name: 'Commands' })
|
||||
const debugPaneOption = page.getByRole('option', {
|
||||
name: 'Settings · app · show debug panel',
|
||||
})
|
||||
|
||||
async function setShowDebugPanelTo(value: 'On' | 'Off') {
|
||||
await commandsButton.click()
|
||||
await debugPaneOption.click()
|
||||
await page.getByRole('option', { name: value }).click()
|
||||
await expect(
|
||||
page.getByText(
|
||||
`Set show debug panel to "${value === 'On'}" for this project`
|
||||
)
|
||||
})
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
|
||||
// Constants and locators
|
||||
const resizeHandle = page.locator('.sidebar-resize-handles > div.block')
|
||||
const debugPaneButton = page.getByTestId('debug-pane-button')
|
||||
const commandsButton = page.getByRole('button', { name: 'Commands' })
|
||||
const debugPaneOption = page.getByRole('option', {
|
||||
name: 'Settings · app · show debug panel',
|
||||
})
|
||||
|
||||
async function setShowDebugPanelTo(value: 'On' | 'Off') {
|
||||
await commandsButton.click()
|
||||
await debugPaneOption.click()
|
||||
await page.getByRole('option', { name: value }).click()
|
||||
await expect(
|
||||
page.getByText(
|
||||
`Set show debug panel to "${value === 'On'}" for this project`
|
||||
)
|
||||
).toBeVisible()
|
||||
}
|
||||
|
||||
await test.step(`Initial load with corrupted settings`, async () => {
|
||||
// Check that the debug panel is not visible
|
||||
await expect(debugPaneButton).not.toBeVisible()
|
||||
// Check the pane resize handle wrapper is not visible
|
||||
await expect(resizeHandle).not.toBeVisible()
|
||||
})
|
||||
|
||||
await test.step(`Open code pane to verify we see the resize handles`, async () => {
|
||||
await u.openKclCodePanel()
|
||||
await expect(resizeHandle).toBeVisible()
|
||||
await u.closeKclCodePanel()
|
||||
})
|
||||
|
||||
await test.step(`Turn on debug panel, open it`, async () => {
|
||||
await setShowDebugPanelTo('On')
|
||||
await expect(debugPaneButton).toBeVisible()
|
||||
// We want the logic to clear the phantom panel, so we shouldn't see
|
||||
// the real panel (and therefore the resize handle) yet
|
||||
await expect(resizeHandle).not.toBeVisible()
|
||||
await u.openDebugPanel()
|
||||
await expect(resizeHandle).toBeVisible()
|
||||
})
|
||||
|
||||
await test.step(`Turn off debug panel setting with it open`, async () => {
|
||||
await setShowDebugPanelTo('Off')
|
||||
await expect(debugPaneButton).not.toBeVisible()
|
||||
await expect(resizeHandle).not.toBeVisible()
|
||||
})
|
||||
).toBeVisible()
|
||||
}
|
||||
)
|
||||
|
||||
await test.step(`Initial load with corrupted settings`, async () => {
|
||||
// Check that the debug panel is not visible
|
||||
await expect(debugPaneButton).not.toBeVisible()
|
||||
// Check the pane resize handle wrapper is not visible
|
||||
await expect(resizeHandle).not.toBeVisible()
|
||||
})
|
||||
|
||||
await test.step(`Open code pane to verify we see the resize handles`, async () => {
|
||||
await u.openKclCodePanel()
|
||||
await expect(resizeHandle).toBeVisible()
|
||||
await u.closeKclCodePanel()
|
||||
})
|
||||
|
||||
await test.step(`Turn on debug panel, open it`, async () => {
|
||||
await setShowDebugPanelTo('On')
|
||||
await expect(debugPaneButton).toBeVisible()
|
||||
// We want the logic to clear the phantom panel, so we shouldn't see
|
||||
// the real panel (and therefore the resize handle) yet
|
||||
await expect(resizeHandle).not.toBeVisible()
|
||||
await u.openDebugPanel()
|
||||
await expect(resizeHandle).toBeVisible()
|
||||
})
|
||||
|
||||
await test.step(`Turn off debug panel setting with it open`, async () => {
|
||||
await setShowDebugPanelTo('Off')
|
||||
await expect(debugPaneButton).not.toBeVisible()
|
||||
await expect(resizeHandle).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
test(`Change inline units setting`, async ({
|
||||
page,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { test, expect, Page } from './zoo-test'
|
||||
import { Page } from '@playwright/test'
|
||||
import { test, expect } from './zoo-test'
|
||||
import { getUtils, createProject } from './test-utils'
|
||||
import { join } from 'path'
|
||||
import fs from 'fs'
|
||||
|
@ -35,7 +35,7 @@ test.fixme('Units menu', async ({ page, homePage }) => {
|
||||
test(
|
||||
'Successful export shows a success toast',
|
||||
{ tag: '@skipLocalEngine' },
|
||||
async ({ page, homePage }) => {
|
||||
async ({ page, homePage, tronApp }) => {
|
||||
// FYI this test doesn't work with only engine running locally
|
||||
// And you will need to have the KittyCAD CLI installed
|
||||
const u = await getUtils(page)
|
||||
@ -92,12 +92,17 @@ part001 = startSketchOn('-XZ')
|
||||
await page.waitForTimeout(1000)
|
||||
await u.clearAndCloseDebugPanel()
|
||||
|
||||
if (!tronApp?.projectDirName) {
|
||||
fail()
|
||||
}
|
||||
|
||||
await doExport(
|
||||
{
|
||||
type: 'gltf',
|
||||
storage: 'embedded',
|
||||
presentation: 'pretty',
|
||||
},
|
||||
tronApp?.projectDirName,
|
||||
page
|
||||
)
|
||||
}
|
||||
@ -465,7 +470,7 @@ test('Delete key does not navigate back', async ({ page, homePage }) => {
|
||||
await expect.poll(() => page.url()).not.toContain('/settings')
|
||||
})
|
||||
|
||||
test('Sketch on face', async ({ page, homePage, scene, cmdBar }) => {
|
||||
test('Sketch on face', async ({ page, homePage, scene, cmdBar, toolbar }) => {
|
||||
test.setTimeout(90_000)
|
||||
const u = await getUtils(page)
|
||||
await page.addInitScript(async () => {
|
||||
@ -491,25 +496,22 @@ extrude001 = extrude(sketch001, length = 5 + 7)`
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
await scene.waitForExecutionDone()
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Start Sketch' })
|
||||
).not.toBeDisabled()
|
||||
|
||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||
await page.waitForTimeout(300)
|
||||
await scene.connectionEstablished()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
let previousCodeContent = await page.locator('.cm-content').innerText()
|
||||
|
||||
await u.openAndClearDebugPanel()
|
||||
await u.doAndWaitForCmd(
|
||||
() => page.mouse.click(625, 165),
|
||||
'default_camera_get_settings',
|
||||
true
|
||||
)
|
||||
await page.waitForTimeout(150)
|
||||
await u.closeDebugPanel()
|
||||
await toolbar.startSketchThenCallbackThenWaitUntilReady(async () => {
|
||||
await u.openAndClearDebugPanel()
|
||||
await u.doAndWaitForCmd(
|
||||
() => page.mouse.click(625, 165),
|
||||
'default_camera_get_settings',
|
||||
true
|
||||
)
|
||||
await page.waitForTimeout(150)
|
||||
await u.closeDebugPanel()
|
||||
})
|
||||
await page.waitForTimeout(300)
|
||||
|
||||
const firstClickPosition = [612, 238]
|
||||
const secondClickPosition = [661, 242]
|
||||
|
@ -1,21 +1,11 @@
|
||||
import {
|
||||
test as playwrightTestFn,
|
||||
TestInfo as TestInfoPlaywright,
|
||||
BrowserContext as BrowserContextPlaywright,
|
||||
Page as PagePlaywright,
|
||||
TestDetails as TestDetailsPlaywright,
|
||||
PlaywrightTestArgs,
|
||||
PlaywrightTestOptions,
|
||||
PlaywrightWorkerArgs,
|
||||
PlaywrightWorkerOptions,
|
||||
ElectronApplication,
|
||||
} from '@playwright/test'
|
||||
/* eslint-disable react-hooks/rules-of-hooks */
|
||||
|
||||
import { test as playwrightTestFn, ElectronApplication } from '@playwright/test'
|
||||
|
||||
import {
|
||||
fixtures,
|
||||
fixturesBasedOnProcessEnvPlatform,
|
||||
Fixtures,
|
||||
AuthenticatedTronApp,
|
||||
AuthenticatedApp,
|
||||
ElectronZoo,
|
||||
} from './fixtures/fixtureSetup'
|
||||
|
||||
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
||||
@ -23,9 +13,6 @@ import { DeepPartial } from 'lib/types'
|
||||
export { expect } from '@playwright/test'
|
||||
|
||||
declare module '@playwright/test' {
|
||||
interface TestInfo {
|
||||
tronApp?: AuthenticatedTronApp
|
||||
}
|
||||
interface BrowserContext {
|
||||
folderSetupFn: (
|
||||
cb: (dir: string) => Promise<void>
|
||||
@ -41,288 +28,29 @@ declare module '@playwright/test' {
|
||||
}
|
||||
}
|
||||
|
||||
export type TestInfo = TestInfoPlaywright
|
||||
export type BrowserContext = BrowserContextPlaywright
|
||||
export type Page = PagePlaywright
|
||||
export type TestDetails = TestDetailsPlaywright & {
|
||||
cleanProjectDir?: boolean
|
||||
appSettings?: DeepPartial<Settings>
|
||||
}
|
||||
// Each worker spawns a new thread, which will spawn its own ElectronZoo.
|
||||
// So in some sense there is an implicit pool.
|
||||
// For example, the variable just beneath this text is reused many times
|
||||
// *for one worker*.
|
||||
const electronZooInstance = new ElectronZoo()
|
||||
|
||||
// Our custom decorated Zoo test object. Makes it easier to add fixtures, and
|
||||
// switch between web and electron if needed.
|
||||
const pwTestFnWithFixtures = playwrightTestFn.extend<Fixtures>(fixtures)
|
||||
|
||||
// In JavaScript you cannot replace a function's body only (despite functions
|
||||
// are themselves objects, which you'd expect a body property or something...)
|
||||
// So we must redefine the function and then re-attach properties.
|
||||
type PWFunction = (
|
||||
args: PlaywrightTestArgs &
|
||||
Fixtures &
|
||||
PlaywrightWorkerArgs &
|
||||
PlaywrightTestOptions &
|
||||
PlaywrightWorkerOptions & {
|
||||
electronApp?: ElectronApplication
|
||||
},
|
||||
testInfo: TestInfo
|
||||
) => void | Promise<void>
|
||||
|
||||
let firstUrl = ''
|
||||
|
||||
export const test = (
|
||||
desc: string,
|
||||
objOrFn: PWFunction | TestDetails,
|
||||
fnMaybe?: PWFunction
|
||||
) => {
|
||||
const hasTestConf = typeof objOrFn === 'object'
|
||||
const fn = hasTestConf ? fnMaybe : objOrFn
|
||||
|
||||
return pwTestFnWithFixtures(
|
||||
desc,
|
||||
hasTestConf ? objOrFn : {},
|
||||
async (
|
||||
{
|
||||
page,
|
||||
context,
|
||||
cmdBar,
|
||||
editor,
|
||||
toolbar,
|
||||
scene,
|
||||
homePage,
|
||||
request,
|
||||
playwright,
|
||||
browser,
|
||||
acceptDownloads,
|
||||
bypassCSP,
|
||||
colorScheme,
|
||||
clientCertificates,
|
||||
deviceScaleFactor,
|
||||
extraHTTPHeaders,
|
||||
geolocation,
|
||||
hasTouch,
|
||||
httpCredentials,
|
||||
ignoreHTTPSErrors,
|
||||
isMobile,
|
||||
javaScriptEnabled,
|
||||
locale,
|
||||
offline,
|
||||
permissions,
|
||||
proxy,
|
||||
storageState,
|
||||
timezoneId,
|
||||
userAgent,
|
||||
viewport,
|
||||
baseURL,
|
||||
contextOptions,
|
||||
actionTimeout,
|
||||
navigationTimeout,
|
||||
serviceWorkers,
|
||||
testIdAttribute,
|
||||
browserName,
|
||||
defaultBrowserType,
|
||||
headless,
|
||||
channel,
|
||||
launchOptions,
|
||||
connectOptions,
|
||||
screenshot,
|
||||
trace,
|
||||
video,
|
||||
},
|
||||
testInfo
|
||||
) => {
|
||||
// To switch to web, use PLATFORM=web environment variable.
|
||||
// Only use this for debugging, since the playwright tracer is busted
|
||||
// for electron.
|
||||
|
||||
let tronApp
|
||||
|
||||
if (process.env.PLATFORM === 'web') {
|
||||
tronApp = new AuthenticatedApp(context, page, testInfo)
|
||||
} else {
|
||||
tronApp = new AuthenticatedTronApp(context, page, testInfo)
|
||||
}
|
||||
|
||||
const fixtures: Fixtures = { cmdBar, editor, toolbar, scene, homePage }
|
||||
if (tronApp instanceof AuthenticatedTronApp) {
|
||||
const options = {
|
||||
fixtures,
|
||||
}
|
||||
if (hasTestConf) {
|
||||
Object.assign(options, {
|
||||
appSettings: objOrFn?.appSettings,
|
||||
cleanProjectDir: objOrFn?.cleanProjectDir,
|
||||
})
|
||||
}
|
||||
await tronApp.initialise(options)
|
||||
} else {
|
||||
await tronApp.initialise('')
|
||||
}
|
||||
|
||||
// We need to patch this because addInitScript will bind too late in our
|
||||
// electron tests, never running. We need to call reload() after each call
|
||||
// to guarantee it runs.
|
||||
const oldContextAddInitScript = tronApp.context.addInitScript
|
||||
tronApp.context.addInitScript = async function (a, b) {
|
||||
// @ts-ignore pretty sure way out of tsc's type checking capabilities.
|
||||
// This code works perfectly fine.
|
||||
await oldContextAddInitScript.apply(this, [a, b])
|
||||
await tronApp.page.reload()
|
||||
}
|
||||
|
||||
// No idea why we mix and match page and context's addInitScript but we do
|
||||
const oldPageAddInitScript = tronApp.page.addInitScript
|
||||
tronApp.page.addInitScript = async function (a: any, b: any) {
|
||||
// @ts-ignore pretty sure way out of tsc's type checking capabilities.
|
||||
// This code works perfectly fine.
|
||||
await oldPageAddInitScript.apply(this, [a, b])
|
||||
await tronApp.page.reload()
|
||||
}
|
||||
|
||||
// Create a consistent way to resize the page across electron and web.
|
||||
// (lee) I had to do everything in the book to make electron change its
|
||||
// damn window size. I succeeded in making it consistently and reliably
|
||||
// do it after a whole afternoon.
|
||||
tronApp.page.setBodyDimensions = async function (dims: {
|
||||
width: number
|
||||
height: number
|
||||
}) {
|
||||
await tronApp.page.setViewportSize(dims)
|
||||
|
||||
if (!(tronApp instanceof AuthenticatedTronApp)) {
|
||||
return
|
||||
}
|
||||
|
||||
await tronApp.electronApp?.evaluateHandle(async ({ app }, dims) => {
|
||||
// @ts-ignore sorry jon but see comment in main.ts why this is ignored
|
||||
await app.resizeWindow(dims.width, dims.height)
|
||||
}, dims)
|
||||
|
||||
return tronApp.page.evaluate(
|
||||
async (dims: { width: number; height: number }) => {
|
||||
await window.electron.resizeWindow(dims.width, dims.height)
|
||||
window.document.body.style.width = dims.width + 'px'
|
||||
window.document.body.style.height = dims.height + 'px'
|
||||
window.document.documentElement.style.width = dims.width + 'px'
|
||||
window.document.documentElement.style.height = dims.height + 'px'
|
||||
},
|
||||
dims
|
||||
)
|
||||
}
|
||||
|
||||
await tronApp.page.setBodyDimensions(tronApp.viewPortSize)
|
||||
|
||||
// We need to expose this in order for some tests that require folder
|
||||
// creation. Before they used to do this by their own electronSetup({...})
|
||||
// calls.
|
||||
if (tronApp instanceof AuthenticatedTronApp) {
|
||||
tronApp.context.folderSetupFn = async function (fn) {
|
||||
return fn(tronApp.dir)
|
||||
.then(() => tronApp.page.reload())
|
||||
.then(() => ({
|
||||
dir: tronApp.dir,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
if (!firstUrl) {
|
||||
await tronApp.page.getByText('Your Projects').count()
|
||||
firstUrl = tronApp.page.url()
|
||||
}
|
||||
|
||||
// Due to the app controlling its own window context we need to inject new
|
||||
// options and context here.
|
||||
// NOTE TO LEE: Seems to destroy page context when calling an electron loadURL.
|
||||
// await tronApp.electronApp.evaluate(({ app }) => {
|
||||
// return app.reuseWindowForTest();
|
||||
// });
|
||||
|
||||
await tronApp.electronApp?.evaluate(({ app }, projectDirName) => {
|
||||
// @ts-ignore can't declaration merge see main.ts
|
||||
app.testProperty['TEST_SETTINGS_FILE_KEY'] = projectDirName
|
||||
}, tronApp.dir)
|
||||
|
||||
// Always start at the root view
|
||||
await tronApp.page.goto(firstUrl)
|
||||
|
||||
// Force a hard reload, destroying the stream and other state
|
||||
await tronApp.page.reload()
|
||||
|
||||
// tsc aint smart enough to know this'll never be undefined
|
||||
// but I dont blame it, the logic to know is complex
|
||||
if (fn) {
|
||||
await fn(
|
||||
{
|
||||
context: tronApp.context,
|
||||
page: tronApp.page,
|
||||
electronApp:
|
||||
tronApp instanceof AuthenticatedTronApp
|
||||
? tronApp.electronApp
|
||||
: undefined,
|
||||
...fixtures,
|
||||
request,
|
||||
playwright,
|
||||
browser,
|
||||
acceptDownloads,
|
||||
bypassCSP,
|
||||
colorScheme,
|
||||
clientCertificates,
|
||||
deviceScaleFactor,
|
||||
extraHTTPHeaders,
|
||||
geolocation,
|
||||
hasTouch,
|
||||
httpCredentials,
|
||||
ignoreHTTPSErrors,
|
||||
isMobile,
|
||||
javaScriptEnabled,
|
||||
locale,
|
||||
offline,
|
||||
permissions,
|
||||
proxy,
|
||||
storageState,
|
||||
timezoneId,
|
||||
userAgent,
|
||||
viewport,
|
||||
baseURL,
|
||||
contextOptions,
|
||||
actionTimeout,
|
||||
navigationTimeout,
|
||||
serviceWorkers,
|
||||
testIdAttribute,
|
||||
browserName,
|
||||
defaultBrowserType,
|
||||
headless,
|
||||
channel,
|
||||
launchOptions,
|
||||
connectOptions,
|
||||
screenshot,
|
||||
trace,
|
||||
video,
|
||||
},
|
||||
testInfo
|
||||
)
|
||||
}
|
||||
|
||||
testInfo.tronApp =
|
||||
tronApp instanceof AuthenticatedTronApp ? tronApp : undefined
|
||||
const playwrightTestFnWithFixtures_ = playwrightTestFn.extend<{
|
||||
tronApp?: ElectronZoo
|
||||
}>({
|
||||
tronApp: async ({}, use, testInfo) => {
|
||||
if (process.env.PLATFORM === 'web') {
|
||||
await use(undefined)
|
||||
return
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
type ZooTest = typeof test
|
||||
await use(electronZooInstance)
|
||||
},
|
||||
})
|
||||
|
||||
test.describe = pwTestFnWithFixtures.describe
|
||||
test.beforeEach = pwTestFnWithFixtures.beforeEach
|
||||
test.afterEach = pwTestFnWithFixtures.afterEach
|
||||
test.step = pwTestFnWithFixtures.step
|
||||
test.skip = pwTestFnWithFixtures.skip
|
||||
test.setTimeout = pwTestFnWithFixtures.setTimeout
|
||||
test.fixme = pwTestFnWithFixtures.fixme as unknown as ZooTest
|
||||
test.only = pwTestFnWithFixtures.only
|
||||
test.fail = pwTestFnWithFixtures.fail
|
||||
test.slow = pwTestFnWithFixtures.slow
|
||||
test.beforeAll = pwTestFnWithFixtures.beforeAll
|
||||
test.afterAll = pwTestFnWithFixtures.afterAll
|
||||
test.use = pwTestFnWithFixtures.use
|
||||
test.expect = pwTestFnWithFixtures.expect
|
||||
test.extend = pwTestFnWithFixtures.extend
|
||||
test.info = pwTestFnWithFixtures.info
|
||||
const test = playwrightTestFnWithFixtures_.extend<Fixtures>(
|
||||
fixturesBasedOnProcessEnvPlatform
|
||||
)
|
||||
|
||||
export { test }
|
||||
|
@ -106,7 +106,7 @@
|
||||
"files:flip-to-nightly:windows": "./scripts/flip-files-to-nightly.ps1",
|
||||
"files:invalidate-bucket": "./scripts/invalidate-files-bucket.sh",
|
||||
"files:invalidate-bucket:nightly": "./scripts/invalidate-files-bucket.sh --nightly",
|
||||
"postinstall": "./node_modules/.bin/electron-rebuild",
|
||||
"postinstall": "yarn --cwd ./rust/kcl-language-server --modules-folder node_modules install && ./node_modules/.bin/electron-rebuild",
|
||||
"make:dev": "make dev",
|
||||
"generate:machine-api": "npx openapi-typescript ./openapi/machine-api.json -o src/lib/machine-api.d.ts",
|
||||
"generate:samples-manifest": "cd public/kcl-samples && node generate-manifest.js",
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -29,17 +29,17 @@ DATA;
|
||||
#13 = VERTEX_POINT('NONE', #12);
|
||||
#14 = CARTESIAN_POINT('NONE', (-0.004400550000000005, 0.027303023818752777, 0.0142875));
|
||||
#15 = VERTEX_POINT('NONE', #14);
|
||||
#16 = CARTESIAN_POINT('NONE', (-0.008801100000000001, 0.034925000000000005, 0.0206375));
|
||||
#16 = CARTESIAN_POINT('NONE', (-0.008801100000000003, 0.034925000000000005, 0.0206375));
|
||||
#17 = VERTEX_POINT('NONE', #16);
|
||||
#18 = CARTESIAN_POINT('NONE', (-0.008801100000000001, 0.034925000000000005, 0.0142875));
|
||||
#18 = CARTESIAN_POINT('NONE', (-0.008801100000000003, 0.034925000000000005, 0.0142875));
|
||||
#19 = VERTEX_POINT('NONE', #18);
|
||||
#20 = CARTESIAN_POINT('NONE', (-0.00440055, 0.042546976181247226, 0.0206375));
|
||||
#20 = CARTESIAN_POINT('NONE', (-0.004400550000000001, 0.042546976181247226, 0.0206375));
|
||||
#21 = VERTEX_POINT('NONE', #20);
|
||||
#22 = CARTESIAN_POINT('NONE', (-0.00440055, 0.042546976181247226, 0.0142875));
|
||||
#22 = CARTESIAN_POINT('NONE', (-0.004400550000000001, 0.042546976181247226, 0.0142875));
|
||||
#23 = VERTEX_POINT('NONE', #22);
|
||||
#24 = CARTESIAN_POINT('NONE', (0.004400550000000001, 0.042546976181247226, 0.0206375));
|
||||
#24 = CARTESIAN_POINT('NONE', (0.00440055, 0.042546976181247226, 0.0206375));
|
||||
#25 = VERTEX_POINT('NONE', #24);
|
||||
#26 = CARTESIAN_POINT('NONE', (0.004400550000000001, 0.042546976181247226, 0.0142875));
|
||||
#26 = CARTESIAN_POINT('NONE', (0.00440055, 0.042546976181247226, 0.0142875));
|
||||
#27 = VERTEX_POINT('NONE', #26);
|
||||
#28 = CARTESIAN_POINT('NONE', (-0.0000000000000000011975821048861966, 0.039814499999999996, 0.0206375));
|
||||
#29 = VERTEX_POINT('NONE', #28);
|
||||
@ -57,17 +57,17 @@ DATA;
|
||||
#41 = VERTEX_POINT('NONE', #40);
|
||||
#42 = CARTESIAN_POINT('NONE', (0.01860266554050596, 0.020463645441073146, 0.0142875));
|
||||
#43 = VERTEX_POINT('NONE', #42);
|
||||
#44 = CARTESIAN_POINT('NONE', (0.02181806843005704, 0.028656358390265653, 0.0206375));
|
||||
#44 = CARTESIAN_POINT('NONE', (0.02181806843005704, 0.028656358390265656, 0.0206375));
|
||||
#45 = VERTEX_POINT('NONE', #44);
|
||||
#46 = CARTESIAN_POINT('NONE', (0.02181806843005704, 0.028656358390265653, 0.0142875));
|
||||
#46 = CARTESIAN_POINT('NONE', (0.02181806843005704, 0.028656358390265656, 0.0142875));
|
||||
#47 = VERTEX_POINT('NONE', #46);
|
||||
#48 = CARTESIAN_POINT('NONE', (0.030520867414747018, 0.029968094279108775, 0.0206375));
|
||||
#48 = CARTESIAN_POINT('NONE', (0.030520867414747015, 0.02996809427910878, 0.0206375));
|
||||
#49 = VERTEX_POINT('NONE', #48);
|
||||
#50 = CARTESIAN_POINT('NONE', (0.030520867414747018, 0.029968094279108775, 0.0142875));
|
||||
#50 = CARTESIAN_POINT('NONE', (0.030520867414747015, 0.02996809427910878, 0.0142875));
|
||||
#51 = VERTEX_POINT('NONE', #50);
|
||||
#52 = CARTESIAN_POINT('NONE', (0.036008263509885924, 0.0230871172187594, 0.0206375));
|
||||
#52 = CARTESIAN_POINT('NONE', (0.036008263509885924, 0.023087117218759404, 0.0206375));
|
||||
#53 = VERTEX_POINT('NONE', #52);
|
||||
#54 = CARTESIAN_POINT('NONE', (0.036008263509885924, 0.0230871172187594, 0.0142875));
|
||||
#54 = CARTESIAN_POINT('NONE', (0.036008263509885924, 0.023087117218759404, 0.0142875));
|
||||
#55 = VERTEX_POINT('NONE', #54);
|
||||
#56 = CARTESIAN_POINT('NONE', (0.03112822955872337, 0.024823934716104546, 0.0206375));
|
||||
#57 = VERTEX_POINT('NONE', #56);
|
||||
@ -85,13 +85,13 @@ DATA;
|
||||
#69 = VERTEX_POINT('NONE', #68);
|
||||
#70 = CARTESIAN_POINT('NONE', (0.027597694503788704, -0.0017852753360286355, 0.0142875));
|
||||
#71 = VERTEX_POINT('NONE', #70);
|
||||
#72 = CARTESIAN_POINT('NONE', (0.036007786324793116, 0.00080889442947917, 0.0206375));
|
||||
#72 = CARTESIAN_POINT('NONE', (0.036007786324793116, 0.0008088944294791717, 0.0206375));
|
||||
#73 = VERTEX_POINT('NONE', #72);
|
||||
#74 = CARTESIAN_POINT('NONE', (0.036007786324793116, 0.00080889442947917, 0.0142875));
|
||||
#74 = CARTESIAN_POINT('NONE', (0.036007786324793116, 0.0008088944294791717, 0.0142875));
|
||||
#75 = VERTEX_POINT('NONE', #74);
|
||||
#76 = CARTESIAN_POINT('NONE', (0.042459449153954595, -0.005177373852916468, 0.0206375));
|
||||
#76 = CARTESIAN_POINT('NONE', (0.042459449153954595, -0.0051773738529164665, 0.0206375));
|
||||
#77 = VERTEX_POINT('NONE', #76);
|
||||
#78 = CARTESIAN_POINT('NONE', (0.042459449153954595, -0.005177373852916468, 0.0142875));
|
||||
#78 = CARTESIAN_POINT('NONE', (0.042459449153954595, -0.0051773738529164665, 0.0142875));
|
||||
#79 = VERTEX_POINT('NONE', #78);
|
||||
#80 = CARTESIAN_POINT('NONE', (0.04050102016211167, -0.013757811900819917, 0.0206375));
|
||||
#81 = VERTEX_POINT('NONE', #80);
|
||||
@ -113,17 +113,17 @@ DATA;
|
||||
#97 = VERTEX_POINT('NONE', #96);
|
||||
#98 = CARTESIAN_POINT('NONE', (0.015811096615344203, -0.022689847372120698, 0.0142875));
|
||||
#99 = VERTEX_POINT('NONE', #98);
|
||||
#100 = CARTESIAN_POINT('NONE', (0.023082906691976702, -0.027647683535144445, 0.0206375));
|
||||
#100 = CARTESIAN_POINT('NONE', (0.023082906691976705, -0.027647683535144445, 0.0206375));
|
||||
#101 = VERTEX_POINT('NONE', #100);
|
||||
#102 = CARTESIAN_POINT('NONE', (0.023082906691976702, -0.027647683535144445, 0.0142875));
|
||||
#102 = CARTESIAN_POINT('NONE', (0.023082906691976705, -0.027647683535144445, 0.0142875));
|
||||
#103 = VERTEX_POINT('NONE', #102);
|
||||
#104 = CARTESIAN_POINT('NONE', (0.02242519966531322, -0.03642417387451573, 0.0206375));
|
||||
#104 = CARTESIAN_POINT('NONE', (0.022425199665313224, -0.03642417387451573, 0.0206375));
|
||||
#105 = VERTEX_POINT('NONE', #104);
|
||||
#106 = CARTESIAN_POINT('NONE', (0.02242519966531322, -0.03642417387451573, 0.0142875));
|
||||
#106 = CARTESIAN_POINT('NONE', (0.022425199665313224, -0.03642417387451573, 0.0142875));
|
||||
#107 = VERTEX_POINT('NONE', #106);
|
||||
#108 = CARTESIAN_POINT('NONE', (0.014495682562017243, -0.040242828050863266, 0.0206375));
|
||||
#108 = CARTESIAN_POINT('NONE', (0.014495682562017245, -0.040242828050863266, 0.0206375));
|
||||
#109 = VERTEX_POINT('NONE', #108);
|
||||
#110 = CARTESIAN_POINT('NONE', (0.014495682562017243, -0.040242828050863266, 0.0142875));
|
||||
#110 = CARTESIAN_POINT('NONE', (0.014495682562017245, -0.040242828050863266, 0.0142875));
|
||||
#111 = VERTEX_POINT('NONE', #110);
|
||||
#112 = CARTESIAN_POINT('NONE', (0.01727486413109602, -0.03587162499110086, 0.0206375));
|
||||
#113 = VERTEX_POINT('NONE', #112);
|
||||
@ -141,17 +141,17 @@ DATA;
|
||||
#125 = VERTEX_POINT('NONE', #124);
|
||||
#126 = CARTESIAN_POINT('NONE', (-0.007881579512048209, -0.026508501548468247, 0.014287499999999998));
|
||||
#127 = VERTEX_POINT('NONE', #126);
|
||||
#128 = CARTESIAN_POINT('NONE', (-0.0072238724853847325, -0.03528499188783953, 0.020637499999999996));
|
||||
#128 = CARTESIAN_POINT('NONE', (-0.007223872485384732, -0.03528499188783953, 0.020637499999999996));
|
||||
#129 = VERTEX_POINT('NONE', #128);
|
||||
#130 = CARTESIAN_POINT('NONE', (-0.0072238724853847325, -0.03528499188783953, 0.014287499999999998));
|
||||
#130 = CARTESIAN_POINT('NONE', (-0.007223872485384732, -0.03528499188783953, 0.014287499999999998));
|
||||
#131 = VERTEX_POINT('NONE', #130);
|
||||
#132 = CARTESIAN_POINT('NONE', (-0.014495682562017234, -0.04024282805086327, 0.020637499999999996));
|
||||
#132 = CARTESIAN_POINT('NONE', (-0.014495682562017232, -0.04024282805086327, 0.020637499999999996));
|
||||
#133 = VERTEX_POINT('NONE', #132);
|
||||
#134 = CARTESIAN_POINT('NONE', (-0.014495682562017234, -0.04024282805086327, 0.014287499999999998));
|
||||
#134 = CARTESIAN_POINT('NONE', (-0.014495682562017232, -0.04024282805086327, 0.014287499999999998));
|
||||
#135 = VERTEX_POINT('NONE', #134);
|
||||
#136 = CARTESIAN_POINT('NONE', (-0.022425199665313218, -0.036424173874515735, 0.020637499999999996));
|
||||
#136 = CARTESIAN_POINT('NONE', (-0.022425199665313214, -0.036424173874515735, 0.020637499999999996));
|
||||
#137 = VERTEX_POINT('NONE', #136);
|
||||
#138 = CARTESIAN_POINT('NONE', (-0.022425199665313218, -0.036424173874515735, 0.014287499999999998));
|
||||
#138 = CARTESIAN_POINT('NONE', (-0.022425199665313214, -0.036424173874515735, 0.014287499999999998));
|
||||
#139 = VERTEX_POINT('NONE', #138);
|
||||
#140 = CARTESIAN_POINT('NONE', (-0.01727486413109601, -0.035871624991100866, 0.020637499999999996));
|
||||
#141 = VERTEX_POINT('NONE', #140);
|
||||
@ -173,13 +173,13 @@ DATA;
|
||||
#157 = VERTEX_POINT('NONE', #156);
|
||||
#158 = CARTESIAN_POINT('NONE', (-0.032090928341107286, -0.01635198166632771, 0.0142875));
|
||||
#159 = VERTEX_POINT('NONE', #158);
|
||||
#160 = CARTESIAN_POINT('NONE', (-0.040501020162111684, -0.01375781190081989, 0.0206375));
|
||||
#160 = CARTESIAN_POINT('NONE', (-0.040501020162111684, -0.013757811900819893, 0.0206375));
|
||||
#161 = VERTEX_POINT('NONE', #160);
|
||||
#162 = CARTESIAN_POINT('NONE', (-0.040501020162111684, -0.01375781190081989, 0.0142875));
|
||||
#162 = CARTESIAN_POINT('NONE', (-0.040501020162111684, -0.013757811900819893, 0.0142875));
|
||||
#163 = VERTEX_POINT('NONE', #162);
|
||||
#164 = CARTESIAN_POINT('NONE', (-0.042459449153954595, -0.005177373852916439, 0.0206375));
|
||||
#164 = CARTESIAN_POINT('NONE', (-0.042459449153954595, -0.0051773738529164405, 0.0206375));
|
||||
#165 = VERTEX_POINT('NONE', #164);
|
||||
#166 = CARTESIAN_POINT('NONE', (-0.042459449153954595, -0.005177373852916439, 0.0142875));
|
||||
#166 = CARTESIAN_POINT('NONE', (-0.042459449153954595, -0.0051773738529164405, 0.0142875));
|
||||
#167 = VERTEX_POINT('NONE', #166);
|
||||
#168 = CARTESIAN_POINT('NONE', (-0.038816267359563214, -0.008859559725003652, 0.0206375));
|
||||
#169 = VERTEX_POINT('NONE', #168);
|
||||
@ -201,9 +201,9 @@ DATA;
|
||||
#185 = VERTEX_POINT('NONE', #184);
|
||||
#186 = CARTESIAN_POINT('NONE', (-0.032792860620334846, 0.014894404269566884, 0.0142875));
|
||||
#187 = VERTEX_POINT('NONE', #186);
|
||||
#188 = CARTESIAN_POINT('NONE', (-0.036008263509885924, 0.02308711721875939, 0.0206375));
|
||||
#188 = CARTESIAN_POINT('NONE', (-0.03600826350988593, 0.02308711721875939, 0.0206375));
|
||||
#189 = VERTEX_POINT('NONE', #188);
|
||||
#190 = CARTESIAN_POINT('NONE', (-0.036008263509885924, 0.02308711721875939, 0.0142875));
|
||||
#190 = CARTESIAN_POINT('NONE', (-0.03600826350988593, 0.02308711721875939, 0.0142875));
|
||||
#191 = VERTEX_POINT('NONE', #190);
|
||||
#192 = CARTESIAN_POINT('NONE', (-0.03052086741474703, 0.029968094279108768, 0.0206375));
|
||||
#193 = VERTEX_POINT('NONE', #192);
|
||||
@ -715,49 +715,49 @@ DATA;
|
||||
#699 = VECTOR('NONE', #698, 1);
|
||||
#700 = CARTESIAN_POINT('NONE', (0.004400549999999997, 0.027303023818752777, 0.0142875));
|
||||
#701 = LINE('NONE', #700, #699);
|
||||
#702 = DIRECTION('NONE', (-0.49999999999999944, 0.866025403784439, 0));
|
||||
#702 = DIRECTION('NONE', (-0.49999999999999956, 0.8660254037844389, 0));
|
||||
#703 = VECTOR('NONE', #702, 1);
|
||||
#704 = CARTESIAN_POINT('NONE', (-0.004400550000000005, 0.027303023818752777, 0.0206375));
|
||||
#705 = LINE('NONE', #704, #703);
|
||||
#706 = DIRECTION('NONE', (0, 0, -1));
|
||||
#707 = VECTOR('NONE', #706, 1);
|
||||
#708 = CARTESIAN_POINT('NONE', (-0.008801100000000001, 0.034925000000000005, 0.0206375));
|
||||
#708 = CARTESIAN_POINT('NONE', (-0.008801100000000003, 0.034925000000000005, 0.0206375));
|
||||
#709 = LINE('NONE', #708, #707);
|
||||
#710 = DIRECTION('NONE', (-0.49999999999999944, 0.866025403784439, 0));
|
||||
#710 = DIRECTION('NONE', (-0.49999999999999956, 0.8660254037844389, 0));
|
||||
#711 = VECTOR('NONE', #710, 1);
|
||||
#712 = CARTESIAN_POINT('NONE', (-0.004400550000000005, 0.027303023818752777, 0.0142875));
|
||||
#713 = LINE('NONE', #712, #711);
|
||||
#714 = DIRECTION('NONE', (0.5000000000000002, 0.8660254037844386, 0));
|
||||
#715 = VECTOR('NONE', #714, 1);
|
||||
#716 = CARTESIAN_POINT('NONE', (-0.008801100000000001, 0.034925000000000005, 0.0206375));
|
||||
#716 = CARTESIAN_POINT('NONE', (-0.008801100000000003, 0.034925000000000005, 0.0206375));
|
||||
#717 = LINE('NONE', #716, #715);
|
||||
#718 = DIRECTION('NONE', (0, 0, -1));
|
||||
#719 = VECTOR('NONE', #718, 1);
|
||||
#720 = CARTESIAN_POINT('NONE', (-0.00440055, 0.042546976181247226, 0.0206375));
|
||||
#720 = CARTESIAN_POINT('NONE', (-0.004400550000000001, 0.042546976181247226, 0.0206375));
|
||||
#721 = LINE('NONE', #720, #719);
|
||||
#722 = DIRECTION('NONE', (0.5000000000000002, 0.8660254037844386, 0));
|
||||
#723 = VECTOR('NONE', #722, 1);
|
||||
#724 = CARTESIAN_POINT('NONE', (-0.008801100000000001, 0.034925000000000005, 0.0142875));
|
||||
#724 = CARTESIAN_POINT('NONE', (-0.008801100000000003, 0.034925000000000005, 0.0142875));
|
||||
#725 = LINE('NONE', #724, #723);
|
||||
#726 = DIRECTION('NONE', (1, 0, 0));
|
||||
#727 = VECTOR('NONE', #726, 1);
|
||||
#728 = CARTESIAN_POINT('NONE', (-0.00440055, 0.042546976181247226, 0.0206375));
|
||||
#728 = CARTESIAN_POINT('NONE', (-0.004400550000000001, 0.042546976181247226, 0.0206375));
|
||||
#729 = LINE('NONE', #728, #727);
|
||||
#730 = DIRECTION('NONE', (0, 0, -1));
|
||||
#731 = VECTOR('NONE', #730, 1);
|
||||
#732 = CARTESIAN_POINT('NONE', (0.004400550000000001, 0.042546976181247226, 0.0206375));
|
||||
#732 = CARTESIAN_POINT('NONE', (0.00440055, 0.042546976181247226, 0.0206375));
|
||||
#733 = LINE('NONE', #732, #731);
|
||||
#734 = DIRECTION('NONE', (1, 0, 0));
|
||||
#735 = VECTOR('NONE', #734, 1);
|
||||
#736 = CARTESIAN_POINT('NONE', (-0.00440055, 0.042546976181247226, 0.0142875));
|
||||
#736 = CARTESIAN_POINT('NONE', (-0.004400550000000001, 0.042546976181247226, 0.0142875));
|
||||
#737 = LINE('NONE', #736, #735);
|
||||
#738 = DIRECTION('NONE', (0.4999999999999997, -0.8660254037844388, 0));
|
||||
#738 = DIRECTION('NONE', (0.4999999999999999, -0.8660254037844388, 0));
|
||||
#739 = VECTOR('NONE', #738, 1);
|
||||
#740 = CARTESIAN_POINT('NONE', (0.004400550000000001, 0.042546976181247226, 0.0206375));
|
||||
#740 = CARTESIAN_POINT('NONE', (0.00440055, 0.042546976181247226, 0.0206375));
|
||||
#741 = LINE('NONE', #740, #739);
|
||||
#742 = DIRECTION('NONE', (0.4999999999999997, -0.8660254037844388, 0));
|
||||
#742 = DIRECTION('NONE', (0.4999999999999999, -0.8660254037844388, 0));
|
||||
#743 = VECTOR('NONE', #742, 1);
|
||||
#744 = CARTESIAN_POINT('NONE', (0.004400550000000001, 0.042546976181247226, 0.0142875));
|
||||
#744 = CARTESIAN_POINT('NONE', (0.00440055, 0.042546976181247226, 0.0142875));
|
||||
#745 = LINE('NONE', #744, #743);
|
||||
#746 = DIRECTION('NONE', (-0.0000000000000002449293598294707, 1, -0));
|
||||
#747 = DIRECTION('NONE', (-0, 0, 1));
|
||||
@ -801,49 +801,49 @@ DATA;
|
||||
#785 = VECTOR('NONE', #784, 1);
|
||||
#786 = CARTESIAN_POINT('NONE', (0.024090061635644863, 0.013582668380723768, 0.0142875));
|
||||
#787 = LINE('NONE', #786, #785);
|
||||
#788 = DIRECTION('NONE', (0.3653410243663952, 0.9308737486442042, 0));
|
||||
#788 = DIRECTION('NONE', (0.3653410243663951, 0.9308737486442044, 0));
|
||||
#789 = VECTOR('NONE', #788, 1);
|
||||
#790 = CARTESIAN_POINT('NONE', (0.01860266554050596, 0.020463645441073146, 0.0206375));
|
||||
#791 = LINE('NONE', #790, #789);
|
||||
#792 = DIRECTION('NONE', (0, 0, -1));
|
||||
#793 = VECTOR('NONE', #792, 1);
|
||||
#794 = CARTESIAN_POINT('NONE', (0.02181806843005704, 0.028656358390265653, 0.0206375));
|
||||
#794 = CARTESIAN_POINT('NONE', (0.02181806843005704, 0.028656358390265656, 0.0206375));
|
||||
#795 = LINE('NONE', #794, #793);
|
||||
#796 = DIRECTION('NONE', (0.3653410243663952, 0.9308737486442042, 0));
|
||||
#796 = DIRECTION('NONE', (0.3653410243663951, 0.9308737486442044, 0));
|
||||
#797 = VECTOR('NONE', #796, 1);
|
||||
#798 = CARTESIAN_POINT('NONE', (0.01860266554050596, 0.020463645441073146, 0.0142875));
|
||||
#799 = LINE('NONE', #798, #797);
|
||||
#800 = DIRECTION('NONE', (0.9888308262251287, 0.14904226617617372, 0));
|
||||
#800 = DIRECTION('NONE', (0.9888308262251287, 0.1490422661761738, 0));
|
||||
#801 = VECTOR('NONE', #800, 1);
|
||||
#802 = CARTESIAN_POINT('NONE', (0.02181806843005704, 0.028656358390265653, 0.0206375));
|
||||
#802 = CARTESIAN_POINT('NONE', (0.02181806843005704, 0.028656358390265656, 0.0206375));
|
||||
#803 = LINE('NONE', #802, #801);
|
||||
#804 = DIRECTION('NONE', (0, 0, -1));
|
||||
#805 = VECTOR('NONE', #804, 1);
|
||||
#806 = CARTESIAN_POINT('NONE', (0.030520867414747018, 0.029968094279108775, 0.0206375));
|
||||
#806 = CARTESIAN_POINT('NONE', (0.030520867414747015, 0.02996809427910878, 0.0206375));
|
||||
#807 = LINE('NONE', #806, #805);
|
||||
#808 = DIRECTION('NONE', (0.9888308262251287, 0.14904226617617372, 0));
|
||||
#808 = DIRECTION('NONE', (0.9888308262251287, 0.1490422661761738, 0));
|
||||
#809 = VECTOR('NONE', #808, 1);
|
||||
#810 = CARTESIAN_POINT('NONE', (0.02181806843005704, 0.028656358390265653, 0.0142875));
|
||||
#810 = CARTESIAN_POINT('NONE', (0.02181806843005704, 0.028656358390265656, 0.0142875));
|
||||
#811 = LINE('NONE', #810, #809);
|
||||
#812 = DIRECTION('NONE', (0.6234898018587341, -0.7818314824680294, 0));
|
||||
#812 = DIRECTION('NONE', (0.6234898018587344, -0.7818314824680292, 0));
|
||||
#813 = VECTOR('NONE', #812, 1);
|
||||
#814 = CARTESIAN_POINT('NONE', (0.030520867414747018, 0.029968094279108775, 0.0206375));
|
||||
#814 = CARTESIAN_POINT('NONE', (0.030520867414747015, 0.02996809427910878, 0.0206375));
|
||||
#815 = LINE('NONE', #814, #813);
|
||||
#816 = DIRECTION('NONE', (0, 0, -1));
|
||||
#817 = VECTOR('NONE', #816, 1);
|
||||
#818 = CARTESIAN_POINT('NONE', (0.036008263509885924, 0.0230871172187594, 0.0206375));
|
||||
#818 = CARTESIAN_POINT('NONE', (0.036008263509885924, 0.023087117218759404, 0.0206375));
|
||||
#819 = LINE('NONE', #818, #817);
|
||||
#820 = DIRECTION('NONE', (0.6234898018587341, -0.7818314824680294, 0));
|
||||
#820 = DIRECTION('NONE', (0.6234898018587344, -0.7818314824680292, 0));
|
||||
#821 = VECTOR('NONE', #820, 1);
|
||||
#822 = CARTESIAN_POINT('NONE', (0.030520867414747018, 0.029968094279108775, 0.0142875));
|
||||
#822 = CARTESIAN_POINT('NONE', (0.030520867414747015, 0.02996809427910878, 0.0142875));
|
||||
#823 = LINE('NONE', #822, #821);
|
||||
#824 = DIRECTION('NONE', (-0.36534102436639604, -0.9308737486442038, 0));
|
||||
#824 = DIRECTION('NONE', (-0.36534102436639593, -0.9308737486442038, 0));
|
||||
#825 = VECTOR('NONE', #824, 1);
|
||||
#826 = CARTESIAN_POINT('NONE', (0.036008263509885924, 0.0230871172187594, 0.0206375));
|
||||
#826 = CARTESIAN_POINT('NONE', (0.036008263509885924, 0.023087117218759404, 0.0206375));
|
||||
#827 = LINE('NONE', #826, #825);
|
||||
#828 = DIRECTION('NONE', (-0.36534102436639604, -0.9308737486442038, 0));
|
||||
#828 = DIRECTION('NONE', (-0.36534102436639593, -0.9308737486442038, 0));
|
||||
#829 = VECTOR('NONE', #828, 1);
|
||||
#830 = CARTESIAN_POINT('NONE', (0.036008263509885924, 0.0230871172187594, 0.0142875));
|
||||
#830 = CARTESIAN_POINT('NONE', (0.036008263509885924, 0.023087117218759404, 0.0142875));
|
||||
#831 = LINE('NONE', #830, #829);
|
||||
#832 = DIRECTION('NONE', (0.78183148246803, 0.6234898018587336, -0));
|
||||
#833 = DIRECTION('NONE', (0, 0, 1.0000000000000002));
|
||||
@ -887,41 +887,41 @@ DATA;
|
||||
#871 = VECTOR('NONE', #870, 1);
|
||||
#872 = CARTESIAN_POINT('NONE', (0.025639265511945786, -0.010365713383932086, 0.0142875));
|
||||
#873 = LINE('NONE', #872, #871);
|
||||
#874 = DIRECTION('NONE', (0.955572805786141, 0.2947551744109036, 0));
|
||||
#874 = DIRECTION('NONE', (0.9555728057861409, 0.29475517441090376, 0));
|
||||
#875 = VECTOR('NONE', #874, 1);
|
||||
#876 = CARTESIAN_POINT('NONE', (0.027597694503788704, -0.0017852753360286355, 0.0206375));
|
||||
#877 = LINE('NONE', #876, #875);
|
||||
#878 = DIRECTION('NONE', (0, 0, -1));
|
||||
#879 = VECTOR('NONE', #878, 1);
|
||||
#880 = CARTESIAN_POINT('NONE', (0.036007786324793116, 0.00080889442947917, 0.0206375));
|
||||
#880 = CARTESIAN_POINT('NONE', (0.036007786324793116, 0.0008088944294791717, 0.0206375));
|
||||
#881 = LINE('NONE', #880, #879);
|
||||
#882 = DIRECTION('NONE', (0.955572805786141, 0.2947551744109036, 0));
|
||||
#882 = DIRECTION('NONE', (0.9555728057861409, 0.29475517441090376, 0));
|
||||
#883 = VECTOR('NONE', #882, 1);
|
||||
#884 = CARTESIAN_POINT('NONE', (0.027597694503788704, -0.0017852753360286355, 0.0142875));
|
||||
#885 = LINE('NONE', #884, #883);
|
||||
#886 = DIRECTION('NONE', (0.7330518718298261, -0.6801727377709197, 0));
|
||||
#887 = VECTOR('NONE', #886, 1);
|
||||
#888 = CARTESIAN_POINT('NONE', (0.036007786324793116, 0.00080889442947917, 0.0206375));
|
||||
#888 = CARTESIAN_POINT('NONE', (0.036007786324793116, 0.0008088944294791717, 0.0206375));
|
||||
#889 = LINE('NONE', #888, #887);
|
||||
#890 = DIRECTION('NONE', (0, 0, -1));
|
||||
#891 = VECTOR('NONE', #890, 1);
|
||||
#892 = CARTESIAN_POINT('NONE', (0.042459449153954595, -0.005177373852916468, 0.0206375));
|
||||
#892 = CARTESIAN_POINT('NONE', (0.042459449153954595, -0.0051773738529164665, 0.0206375));
|
||||
#893 = LINE('NONE', #892, #891);
|
||||
#894 = DIRECTION('NONE', (0.7330518718298261, -0.6801727377709197, 0));
|
||||
#895 = VECTOR('NONE', #894, 1);
|
||||
#896 = CARTESIAN_POINT('NONE', (0.036007786324793116, 0.00080889442947917, 0.0142875));
|
||||
#896 = CARTESIAN_POINT('NONE', (0.036007786324793116, 0.0008088944294791717, 0.0142875));
|
||||
#897 = LINE('NONE', #896, #895);
|
||||
#898 = DIRECTION('NONE', (-0.22252093395631514, -0.9749279121818235, 0));
|
||||
#898 = DIRECTION('NONE', (-0.22252093395631506, -0.9749279121818235, 0));
|
||||
#899 = VECTOR('NONE', #898, 1);
|
||||
#900 = CARTESIAN_POINT('NONE', (0.042459449153954595, -0.005177373852916468, 0.0206375));
|
||||
#900 = CARTESIAN_POINT('NONE', (0.042459449153954595, -0.0051773738529164665, 0.0206375));
|
||||
#901 = LINE('NONE', #900, #899);
|
||||
#902 = DIRECTION('NONE', (0, 0, -1));
|
||||
#903 = VECTOR('NONE', #902, 1);
|
||||
#904 = CARTESIAN_POINT('NONE', (0.04050102016211167, -0.013757811900819917, 0.0206375));
|
||||
#905 = LINE('NONE', #904, #903);
|
||||
#906 = DIRECTION('NONE', (-0.22252093395631514, -0.9749279121818235, 0));
|
||||
#906 = DIRECTION('NONE', (-0.22252093395631506, -0.9749279121818235, 0));
|
||||
#907 = VECTOR('NONE', #906, 1);
|
||||
#908 = CARTESIAN_POINT('NONE', (0.042459449153954595, -0.005177373852916468, 0.0142875));
|
||||
#908 = CARTESIAN_POINT('NONE', (0.042459449153954595, -0.0051773738529164665, 0.0142875));
|
||||
#909 = LINE('NONE', #908, #907);
|
||||
#910 = DIRECTION('NONE', (-0.9555728057861407, -0.2947551744109045, 0));
|
||||
#911 = VECTOR('NONE', #910, 1);
|
||||
@ -973,49 +973,49 @@ DATA;
|
||||
#957 = VECTOR('NONE', #956, 1);
|
||||
#958 = CARTESIAN_POINT('NONE', (0.007881579512048221, -0.02650850154846824, 0.0142875));
|
||||
#959 = LINE('NONE', #958, #957);
|
||||
#960 = DIRECTION('NONE', (0.8262387743159946, -0.5633200580636225, 0));
|
||||
#960 = DIRECTION('NONE', (0.8262387743159947, -0.5633200580636224, 0));
|
||||
#961 = VECTOR('NONE', #960, 1);
|
||||
#962 = CARTESIAN_POINT('NONE', (0.015811096615344203, -0.022689847372120698, 0.0206375));
|
||||
#963 = LINE('NONE', #962, #961);
|
||||
#964 = DIRECTION('NONE', (0, 0, -1));
|
||||
#965 = VECTOR('NONE', #964, 1);
|
||||
#966 = CARTESIAN_POINT('NONE', (0.023082906691976702, -0.027647683535144445, 0.0206375));
|
||||
#966 = CARTESIAN_POINT('NONE', (0.023082906691976705, -0.027647683535144445, 0.0206375));
|
||||
#967 = LINE('NONE', #966, #965);
|
||||
#968 = DIRECTION('NONE', (0.8262387743159946, -0.5633200580636225, 0));
|
||||
#968 = DIRECTION('NONE', (0.8262387743159947, -0.5633200580636224, 0));
|
||||
#969 = VECTOR('NONE', #968, 1);
|
||||
#970 = CARTESIAN_POINT('NONE', (0.015811096615344203, -0.022689847372120698, 0.0142875));
|
||||
#971 = LINE('NONE', #970, #969);
|
||||
#972 = DIRECTION('NONE', (-0.07473009358642455, -0.9972037971811801, 0));
|
||||
#973 = VECTOR('NONE', #972, 1);
|
||||
#974 = CARTESIAN_POINT('NONE', (0.023082906691976702, -0.027647683535144445, 0.0206375));
|
||||
#974 = CARTESIAN_POINT('NONE', (0.023082906691976705, -0.027647683535144445, 0.0206375));
|
||||
#975 = LINE('NONE', #974, #973);
|
||||
#976 = DIRECTION('NONE', (0, 0, -1));
|
||||
#977 = VECTOR('NONE', #976, 1);
|
||||
#978 = CARTESIAN_POINT('NONE', (0.02242519966531322, -0.03642417387451573, 0.0206375));
|
||||
#978 = CARTESIAN_POINT('NONE', (0.022425199665313224, -0.03642417387451573, 0.0206375));
|
||||
#979 = LINE('NONE', #978, #977);
|
||||
#980 = DIRECTION('NONE', (-0.07473009358642455, -0.9972037971811801, 0));
|
||||
#981 = VECTOR('NONE', #980, 1);
|
||||
#982 = CARTESIAN_POINT('NONE', (0.023082906691976702, -0.027647683535144445, 0.0142875));
|
||||
#982 = CARTESIAN_POINT('NONE', (0.023082906691976705, -0.027647683535144445, 0.0142875));
|
||||
#983 = LINE('NONE', #982, #981);
|
||||
#984 = DIRECTION('NONE', (-0.9009688679024193, -0.43388373911755806, 0));
|
||||
#984 = DIRECTION('NONE', (-0.9009688679024193, -0.43388373911755795, 0));
|
||||
#985 = VECTOR('NONE', #984, 1);
|
||||
#986 = CARTESIAN_POINT('NONE', (0.02242519966531322, -0.03642417387451573, 0.0206375));
|
||||
#986 = CARTESIAN_POINT('NONE', (0.022425199665313224, -0.03642417387451573, 0.0206375));
|
||||
#987 = LINE('NONE', #986, #985);
|
||||
#988 = DIRECTION('NONE', (0, 0, -1));
|
||||
#989 = VECTOR('NONE', #988, 1);
|
||||
#990 = CARTESIAN_POINT('NONE', (0.014495682562017243, -0.040242828050863266, 0.0206375));
|
||||
#990 = CARTESIAN_POINT('NONE', (0.014495682562017245, -0.040242828050863266, 0.0206375));
|
||||
#991 = LINE('NONE', #990, #989);
|
||||
#992 = DIRECTION('NONE', (-0.9009688679024193, -0.43388373911755806, 0));
|
||||
#992 = DIRECTION('NONE', (-0.9009688679024193, -0.43388373911755795, 0));
|
||||
#993 = VECTOR('NONE', #992, 1);
|
||||
#994 = CARTESIAN_POINT('NONE', (0.02242519966531322, -0.03642417387451573, 0.0142875));
|
||||
#994 = CARTESIAN_POINT('NONE', (0.022425199665313224, -0.03642417387451573, 0.0142875));
|
||||
#995 = LINE('NONE', #994, #993);
|
||||
#996 = DIRECTION('NONE', (-0.8262387743159952, 0.5633200580636217, 0));
|
||||
#996 = DIRECTION('NONE', (-0.8262387743159951, 0.5633200580636216, 0));
|
||||
#997 = VECTOR('NONE', #996, 1);
|
||||
#998 = CARTESIAN_POINT('NONE', (0.014495682562017243, -0.040242828050863266, 0.0206375));
|
||||
#998 = CARTESIAN_POINT('NONE', (0.014495682562017245, -0.040242828050863266, 0.0206375));
|
||||
#999 = LINE('NONE', #998, #997);
|
||||
#1000 = DIRECTION('NONE', (-0.8262387743159952, 0.5633200580636217, 0));
|
||||
#1000 = DIRECTION('NONE', (-0.8262387743159951, 0.5633200580636216, 0));
|
||||
#1001 = VECTOR('NONE', #1000, 1);
|
||||
#1002 = CARTESIAN_POINT('NONE', (0.014495682562017243, -0.040242828050863266, 0.0142875));
|
||||
#1002 = CARTESIAN_POINT('NONE', (0.014495682562017245, -0.040242828050863266, 0.0142875));
|
||||
#1003 = LINE('NONE', #1002, #1001);
|
||||
#1004 = DIRECTION('NONE', (0.4338837391175578, -0.9009688679024195, -0));
|
||||
#1005 = DIRECTION('NONE', (0, 0, 1.0000000000000002));
|
||||
@ -1059,49 +1059,49 @@ DATA;
|
||||
#1043 = VECTOR('NONE', #1042, 1);
|
||||
#1044 = CARTESIAN_POINT('NONE', (-0.015811096615344192, -0.022689847372120705, 0.014287499999999998));
|
||||
#1045 = LINE('NONE', #1044, #1043);
|
||||
#1046 = DIRECTION('NONE', (0.07473009358642402, -0.9972037971811802, 0));
|
||||
#1046 = DIRECTION('NONE', (0.07473009358642413, -0.9972037971811802, 0));
|
||||
#1047 = VECTOR('NONE', #1046, 1);
|
||||
#1048 = CARTESIAN_POINT('NONE', (-0.007881579512048209, -0.026508501548468247, 0.020637499999999996));
|
||||
#1049 = LINE('NONE', #1048, #1047);
|
||||
#1050 = DIRECTION('NONE', (0, 0, -1));
|
||||
#1051 = VECTOR('NONE', #1050, 1);
|
||||
#1052 = CARTESIAN_POINT('NONE', (-0.0072238724853847325, -0.03528499188783953, 0.020637499999999996));
|
||||
#1052 = CARTESIAN_POINT('NONE', (-0.007223872485384732, -0.03528499188783953, 0.020637499999999996));
|
||||
#1053 = LINE('NONE', #1052, #1051);
|
||||
#1054 = DIRECTION('NONE', (0.07473009358642402, -0.9972037971811802, 0));
|
||||
#1054 = DIRECTION('NONE', (0.07473009358642413, -0.9972037971811802, 0));
|
||||
#1055 = VECTOR('NONE', #1054, 1);
|
||||
#1056 = CARTESIAN_POINT('NONE', (-0.007881579512048209, -0.026508501548468247, 0.014287499999999998));
|
||||
#1057 = LINE('NONE', #1056, #1055);
|
||||
#1058 = DIRECTION('NONE', (-0.826238774315995, -0.5633200580636218, 0));
|
||||
#1058 = DIRECTION('NONE', (-0.826238774315995, -0.563320058063622, 0));
|
||||
#1059 = VECTOR('NONE', #1058, 1);
|
||||
#1060 = CARTESIAN_POINT('NONE', (-0.0072238724853847325, -0.03528499188783953, 0.020637499999999996));
|
||||
#1060 = CARTESIAN_POINT('NONE', (-0.007223872485384732, -0.03528499188783953, 0.020637499999999996));
|
||||
#1061 = LINE('NONE', #1060, #1059);
|
||||
#1062 = DIRECTION('NONE', (0, 0, -1));
|
||||
#1063 = VECTOR('NONE', #1062, 1);
|
||||
#1064 = CARTESIAN_POINT('NONE', (-0.014495682562017234, -0.04024282805086327, 0.020637499999999996));
|
||||
#1064 = CARTESIAN_POINT('NONE', (-0.014495682562017232, -0.04024282805086327, 0.020637499999999996));
|
||||
#1065 = LINE('NONE', #1064, #1063);
|
||||
#1066 = DIRECTION('NONE', (-0.826238774315995, -0.5633200580636218, 0));
|
||||
#1066 = DIRECTION('NONE', (-0.826238774315995, -0.563320058063622, 0));
|
||||
#1067 = VECTOR('NONE', #1066, 1);
|
||||
#1068 = CARTESIAN_POINT('NONE', (-0.0072238724853847325, -0.03528499188783953, 0.014287499999999998));
|
||||
#1068 = CARTESIAN_POINT('NONE', (-0.007223872485384732, -0.03528499188783953, 0.014287499999999998));
|
||||
#1069 = LINE('NONE', #1068, #1067);
|
||||
#1070 = DIRECTION('NONE', (-0.9009688679024193, 0.4338837391175578, 0));
|
||||
#1070 = DIRECTION('NONE', (-0.9009688679024194, 0.4338837391175579, 0));
|
||||
#1071 = VECTOR('NONE', #1070, 1);
|
||||
#1072 = CARTESIAN_POINT('NONE', (-0.014495682562017234, -0.04024282805086327, 0.020637499999999996));
|
||||
#1072 = CARTESIAN_POINT('NONE', (-0.014495682562017232, -0.04024282805086327, 0.020637499999999996));
|
||||
#1073 = LINE('NONE', #1072, #1071);
|
||||
#1074 = DIRECTION('NONE', (0, 0, -1));
|
||||
#1075 = VECTOR('NONE', #1074, 1);
|
||||
#1076 = CARTESIAN_POINT('NONE', (-0.022425199665313218, -0.036424173874515735, 0.020637499999999996));
|
||||
#1076 = CARTESIAN_POINT('NONE', (-0.022425199665313214, -0.036424173874515735, 0.020637499999999996));
|
||||
#1077 = LINE('NONE', #1076, #1075);
|
||||
#1078 = DIRECTION('NONE', (-0.9009688679024193, 0.4338837391175578, 0));
|
||||
#1078 = DIRECTION('NONE', (-0.9009688679024194, 0.4338837391175579, 0));
|
||||
#1079 = VECTOR('NONE', #1078, 1);
|
||||
#1080 = CARTESIAN_POINT('NONE', (-0.014495682562017234, -0.04024282805086327, 0.014287499999999998));
|
||||
#1080 = CARTESIAN_POINT('NONE', (-0.014495682562017232, -0.04024282805086327, 0.014287499999999998));
|
||||
#1081 = LINE('NONE', #1080, #1079);
|
||||
#1082 = DIRECTION('NONE', (-0.07473009358642409, 0.9972037971811802, 0));
|
||||
#1082 = DIRECTION('NONE', (-0.07473009358642449, 0.9972037971811801, 0));
|
||||
#1083 = VECTOR('NONE', #1082, 1);
|
||||
#1084 = CARTESIAN_POINT('NONE', (-0.022425199665313218, -0.036424173874515735, 0.020637499999999996));
|
||||
#1084 = CARTESIAN_POINT('NONE', (-0.022425199665313214, -0.036424173874515735, 0.020637499999999996));
|
||||
#1085 = LINE('NONE', #1084, #1083);
|
||||
#1086 = DIRECTION('NONE', (-0.07473009358642409, 0.9972037971811802, 0));
|
||||
#1086 = DIRECTION('NONE', (-0.07473009358642449, 0.9972037971811801, 0));
|
||||
#1087 = VECTOR('NONE', #1086, 1);
|
||||
#1088 = CARTESIAN_POINT('NONE', (-0.022425199665313218, -0.036424173874515735, 0.014287499999999998));
|
||||
#1088 = CARTESIAN_POINT('NONE', (-0.022425199665313214, -0.036424173874515735, 0.014287499999999998));
|
||||
#1089 = LINE('NONE', #1088, #1087);
|
||||
#1090 = DIRECTION('NONE', (-0.43388373911755884, -0.9009688679024187, -0));
|
||||
#1091 = DIRECTION('NONE', (0, -0, 0.9999999999999999));
|
||||
@ -1157,37 +1157,37 @@ DATA;
|
||||
#1141 = VECTOR('NONE', #1140, 1);
|
||||
#1142 = CARTESIAN_POINT('NONE', (-0.02563926551194579, -0.010365713383932076, 0.0142875));
|
||||
#1143 = LINE('NONE', #1142, #1141);
|
||||
#1144 = DIRECTION('NONE', (-0.9555728057861403, 0.29475517441090565, 0));
|
||||
#1144 = DIRECTION('NONE', (-0.9555728057861405, 0.29475517441090526, 0));
|
||||
#1145 = VECTOR('NONE', #1144, 1);
|
||||
#1146 = CARTESIAN_POINT('NONE', (-0.032090928341107286, -0.01635198166632771, 0.0206375));
|
||||
#1147 = LINE('NONE', #1146, #1145);
|
||||
#1148 = DIRECTION('NONE', (0, 0, -1));
|
||||
#1149 = VECTOR('NONE', #1148, 1);
|
||||
#1150 = CARTESIAN_POINT('NONE', (-0.040501020162111684, -0.01375781190081989, 0.0206375));
|
||||
#1150 = CARTESIAN_POINT('NONE', (-0.040501020162111684, -0.013757811900819893, 0.0206375));
|
||||
#1151 = LINE('NONE', #1150, #1149);
|
||||
#1152 = DIRECTION('NONE', (-0.9555728057861403, 0.29475517441090565, 0));
|
||||
#1152 = DIRECTION('NONE', (-0.9555728057861405, 0.29475517441090526, 0));
|
||||
#1153 = VECTOR('NONE', #1152, 1);
|
||||
#1154 = CARTESIAN_POINT('NONE', (-0.032090928341107286, -0.01635198166632771, 0.0142875));
|
||||
#1155 = LINE('NONE', #1154, #1153);
|
||||
#1156 = DIRECTION('NONE', (-0.22252093395631356, 0.9749279121818238, 0));
|
||||
#1157 = VECTOR('NONE', #1156, 1);
|
||||
#1158 = CARTESIAN_POINT('NONE', (-0.040501020162111684, -0.01375781190081989, 0.0206375));
|
||||
#1158 = CARTESIAN_POINT('NONE', (-0.040501020162111684, -0.013757811900819893, 0.0206375));
|
||||
#1159 = LINE('NONE', #1158, #1157);
|
||||
#1160 = DIRECTION('NONE', (0, 0, -1));
|
||||
#1161 = VECTOR('NONE', #1160, 1);
|
||||
#1162 = CARTESIAN_POINT('NONE', (-0.042459449153954595, -0.005177373852916439, 0.0206375));
|
||||
#1162 = CARTESIAN_POINT('NONE', (-0.042459449153954595, -0.0051773738529164405, 0.0206375));
|
||||
#1163 = LINE('NONE', #1162, #1161);
|
||||
#1164 = DIRECTION('NONE', (-0.22252093395631356, 0.9749279121818238, 0));
|
||||
#1165 = VECTOR('NONE', #1164, 1);
|
||||
#1166 = CARTESIAN_POINT('NONE', (-0.040501020162111684, -0.01375781190081989, 0.0142875));
|
||||
#1166 = CARTESIAN_POINT('NONE', (-0.040501020162111684, -0.013757811900819893, 0.0142875));
|
||||
#1167 = LINE('NONE', #1166, #1165);
|
||||
#1168 = DIRECTION('NONE', (0.7330518718298267, 0.680172737770919, 0));
|
||||
#1168 = DIRECTION('NONE', (0.7330518718298267, 0.6801727377709191, 0));
|
||||
#1169 = VECTOR('NONE', #1168, 1);
|
||||
#1170 = CARTESIAN_POINT('NONE', (-0.042459449153954595, -0.005177373852916439, 0.0206375));
|
||||
#1170 = CARTESIAN_POINT('NONE', (-0.042459449153954595, -0.0051773738529164405, 0.0206375));
|
||||
#1171 = LINE('NONE', #1170, #1169);
|
||||
#1172 = DIRECTION('NONE', (0.7330518718298267, 0.680172737770919, 0));
|
||||
#1172 = DIRECTION('NONE', (0.7330518718298267, 0.6801727377709191, 0));
|
||||
#1173 = VECTOR('NONE', #1172, 1);
|
||||
#1174 = CARTESIAN_POINT('NONE', (-0.042459449153954595, -0.005177373852916439, 0.0142875));
|
||||
#1174 = CARTESIAN_POINT('NONE', (-0.042459449153954595, -0.0051773738529164405, 0.0142875));
|
||||
#1175 = LINE('NONE', #1174, #1173);
|
||||
#1176 = DIRECTION('NONE', (-0.9749279121818236, -0.22252093395631475, -0));
|
||||
#1177 = DIRECTION('NONE', (0, -0, 1.0000000000000002));
|
||||
@ -1243,29 +1243,29 @@ DATA;
|
||||
#1227 = VECTOR('NONE', #1226, 1);
|
||||
#1228 = CARTESIAN_POINT('NONE', (-0.02409006163564487, 0.013582668380723755, 0.0142875));
|
||||
#1229 = LINE('NONE', #1228, #1227);
|
||||
#1230 = DIRECTION('NONE', (-0.36534102436639493, 0.9308737486442044, 0));
|
||||
#1230 = DIRECTION('NONE', (-0.3653410243663956, 0.930873748644204, 0));
|
||||
#1231 = VECTOR('NONE', #1230, 1);
|
||||
#1232 = CARTESIAN_POINT('NONE', (-0.032792860620334846, 0.014894404269566884, 0.0206375));
|
||||
#1233 = LINE('NONE', #1232, #1231);
|
||||
#1234 = DIRECTION('NONE', (0, 0, -1));
|
||||
#1235 = VECTOR('NONE', #1234, 1);
|
||||
#1236 = CARTESIAN_POINT('NONE', (-0.036008263509885924, 0.02308711721875939, 0.0206375));
|
||||
#1236 = CARTESIAN_POINT('NONE', (-0.03600826350988593, 0.02308711721875939, 0.0206375));
|
||||
#1237 = LINE('NONE', #1236, #1235);
|
||||
#1238 = DIRECTION('NONE', (-0.36534102436639493, 0.9308737486442044, 0));
|
||||
#1238 = DIRECTION('NONE', (-0.3653410243663956, 0.930873748644204, 0));
|
||||
#1239 = VECTOR('NONE', #1238, 1);
|
||||
#1240 = CARTESIAN_POINT('NONE', (-0.032792860620334846, 0.014894404269566884, 0.0142875));
|
||||
#1241 = LINE('NONE', #1240, #1239);
|
||||
#1242 = DIRECTION('NONE', (0.6234898018587333, 0.7818314824680301, 0));
|
||||
#1242 = DIRECTION('NONE', (0.6234898018587336, 0.7818314824680297, 0));
|
||||
#1243 = VECTOR('NONE', #1242, 1);
|
||||
#1244 = CARTESIAN_POINT('NONE', (-0.036008263509885924, 0.02308711721875939, 0.0206375));
|
||||
#1244 = CARTESIAN_POINT('NONE', (-0.03600826350988593, 0.02308711721875939, 0.0206375));
|
||||
#1245 = LINE('NONE', #1244, #1243);
|
||||
#1246 = DIRECTION('NONE', (0, 0, -1));
|
||||
#1247 = VECTOR('NONE', #1246, 1);
|
||||
#1248 = CARTESIAN_POINT('NONE', (-0.03052086741474703, 0.029968094279108768, 0.0206375));
|
||||
#1249 = LINE('NONE', #1248, #1247);
|
||||
#1250 = DIRECTION('NONE', (0.6234898018587333, 0.7818314824680301, 0));
|
||||
#1250 = DIRECTION('NONE', (0.6234898018587336, 0.7818314824680297, 0));
|
||||
#1251 = VECTOR('NONE', #1250, 1);
|
||||
#1252 = CARTESIAN_POINT('NONE', (-0.036008263509885924, 0.02308711721875939, 0.0142875));
|
||||
#1252 = CARTESIAN_POINT('NONE', (-0.03600826350988593, 0.02308711721875939, 0.0142875));
|
||||
#1253 = LINE('NONE', #1252, #1251);
|
||||
#1254 = DIRECTION('NONE', (0.9888308262251286, -0.14904226617617397, 0));
|
||||
#1255 = VECTOR('NONE', #1254, 1);
|
||||
@ -3385,20 +3385,20 @@ DATA;
|
||||
#3369 = DIRECTION('NONE', (-0, -1, 0));
|
||||
#3370 = AXIS2_PLACEMENT_3D('NONE', #3368, #3369, $);
|
||||
#3371 = PLANE('NONE', #3370);
|
||||
#3372 = CARTESIAN_POINT('NONE', (-0.006600825000000002, 0.031114011909376384, 0.0174625));
|
||||
#3373 = DIRECTION('NONE', (-0.866025403784439, -0.49999999999999956, -0.000000000000000000000000000000006162975822039155));
|
||||
#3372 = CARTESIAN_POINT('NONE', (-0.006600825000000004, 0.031114011909376387, 0.0174625));
|
||||
#3373 = DIRECTION('NONE', (-0.8660254037844388, -0.49999999999999967, -0));
|
||||
#3374 = AXIS2_PLACEMENT_3D('NONE', #3372, #3373, $);
|
||||
#3375 = PLANE('NONE', #3374);
|
||||
#3376 = CARTESIAN_POINT('NONE', (-0.006600824999999999, 0.038735988090623605, 0.0174625));
|
||||
#3377 = DIRECTION('NONE', (-0.8660254037844386, 0.5000000000000001, 0));
|
||||
#3376 = CARTESIAN_POINT('NONE', (-0.006600825000000002, 0.038735988090623605, 0.017462499999999995));
|
||||
#3377 = DIRECTION('NONE', (-0.8660254037844386, 0.5000000000000001, -0));
|
||||
#3378 = AXIS2_PLACEMENT_3D('NONE', #3376, #3377, $);
|
||||
#3379 = PLANE('NONE', #3378);
|
||||
#3380 = CARTESIAN_POINT('NONE', (0.000000000000000003996802888650563, 0.04254697618124722, 0.017462499999999995));
|
||||
#3380 = CARTESIAN_POINT('NONE', (-0.0000000000000000008881784197001253, 0.04254697618124722, 0.0174625));
|
||||
#3381 = DIRECTION('NONE', (0, 1, 0));
|
||||
#3382 = AXIS2_PLACEMENT_3D('NONE', #3380, #3381, $);
|
||||
#3383 = PLANE('NONE', #3382);
|
||||
#3384 = CARTESIAN_POINT('NONE', (0.006600825, 0.0387359880906236, 0.0174625));
|
||||
#3385 = DIRECTION('NONE', (0.8660254037844388, 0.4999999999999995, 0));
|
||||
#3384 = CARTESIAN_POINT('NONE', (0.0066008249999999985, 0.0387359880906236, 0.0174625));
|
||||
#3385 = DIRECTION('NONE', (0.8660254037844388, 0.49999999999999967, 0));
|
||||
#3386 = AXIS2_PLACEMENT_3D('NONE', #3384, #3385, $);
|
||||
#3387 = PLANE('NONE', #3386);
|
||||
#3388 = CARTESIAN_POINT('NONE', (0, 0.034925, 0.0174625));
|
||||
@ -3422,20 +3422,20 @@ DATA;
|
||||
#3406 = DIRECTION('NONE', (-0.7818314824680298, -0.6234898018587336, 0));
|
||||
#3407 = AXIS2_PLACEMENT_3D('NONE', #3405, #3406, $);
|
||||
#3408 = PLANE('NONE', #3407);
|
||||
#3409 = CARTESIAN_POINT('NONE', (0.020210366985281496, 0.024560001915669396, 0.0174625));
|
||||
#3410 = DIRECTION('NONE', (-0.9308737486442041, 0.36534102436639554, -0.000000000000000000000000000000006162975822039155));
|
||||
#3409 = CARTESIAN_POINT('NONE', (0.020210366985281496, 0.0245600019156694, 0.0174625));
|
||||
#3410 = DIRECTION('NONE', (-0.9308737486442044, 0.36534102436639515, -0));
|
||||
#3411 = AXIS2_PLACEMENT_3D('NONE', #3409, #3410, $);
|
||||
#3412 = PLANE('NONE', #3411);
|
||||
#3413 = CARTESIAN_POINT('NONE', (0.026169467922402028, 0.02931222633468721, 0.0174625));
|
||||
#3414 = DIRECTION('NONE', (-0.1490422661761737, 0.9888308262251286, 0));
|
||||
#3413 = CARTESIAN_POINT('NONE', (0.026169467922402025, 0.02931222633468721, 0.017462499999999995));
|
||||
#3414 = DIRECTION('NONE', (-0.14904226617617383, 0.9888308262251286, -0));
|
||||
#3415 = AXIS2_PLACEMENT_3D('NONE', #3413, #3414, $);
|
||||
#3416 = PLANE('NONE', #3415);
|
||||
#3417 = CARTESIAN_POINT('NONE', (0.03326456546231646, 0.026527605748934077, 0.017462499999999995));
|
||||
#3418 = DIRECTION('NONE', (0.7818314824680298, 0.6234898018587336, 0));
|
||||
#3417 = CARTESIAN_POINT('NONE', (0.03326456546231646, 0.026527605748934088, 0.0174625));
|
||||
#3418 = DIRECTION('NONE', (0.7818314824680295, 0.6234898018587338, 0));
|
||||
#3419 = AXIS2_PLACEMENT_3D('NONE', #3417, #3418, $);
|
||||
#3420 = PLANE('NONE', #3419);
|
||||
#3421 = CARTESIAN_POINT('NONE', (0.03440056206511037, 0.018990760744163143, 0.0174625));
|
||||
#3422 = DIRECTION('NONE', (0.9308737486442041, -0.3653410243663953, 0));
|
||||
#3422 = DIRECTION('NONE', (0.9308737486442044, -0.36534102436639526, 0));
|
||||
#3423 = AXIS2_PLACEMENT_3D('NONE', #3421, #3422, $);
|
||||
#3424 = PLANE('NONE', #3423);
|
||||
#3425 = CARTESIAN_POINT('NONE', (0.02730546452519594, 0.02177538132991627, 0.0174625));
|
||||
@ -3459,16 +3459,16 @@ DATA;
|
||||
#3443 = DIRECTION('NONE', (-0.9749279121818235, 0.22252093395631442, -0.0000000000000000000000000000000030814879110195774));
|
||||
#3444 = AXIS2_PLACEMENT_3D('NONE', #3442, #3443, $);
|
||||
#3445 = PLANE('NONE', #3444);
|
||||
#3446 = CARTESIAN_POINT('NONE', (0.0318027404142909, -0.00048819045327473263, 0.0174625));
|
||||
#3447 = DIRECTION('NONE', (-0.2947551744109037, 0.955572805786141, -0.000000000000000000000000000000006162975822039155));
|
||||
#3446 = CARTESIAN_POINT('NONE', (0.03180274041429091, -0.0004881904532747314, 0.0174625));
|
||||
#3447 = DIRECTION('NONE', (-0.2947551744109037, 0.9555728057861408, -0));
|
||||
#3448 = AXIS2_PLACEMENT_3D('NONE', #3446, #3447, $);
|
||||
#3449 = PLANE('NONE', #3448);
|
||||
#3450 = CARTESIAN_POINT('NONE', (0.039233617739373845, -0.0021842397117186486, 0.0174625));
|
||||
#3451 = DIRECTION('NONE', (0.6801727377709197, 0.733051871829826, 0));
|
||||
#3450 = CARTESIAN_POINT('NONE', (0.039233617739373845, -0.002184239711718646, 0.017462499999999995));
|
||||
#3451 = DIRECTION('NONE', (0.6801727377709199, 0.7330518718298258, 0));
|
||||
#3452 = AXIS2_PLACEMENT_3D('NONE', #3450, #3451, $);
|
||||
#3453 = PLANE('NONE', #3452);
|
||||
#3454 = CARTESIAN_POINT('NONE', (0.041480234658033126, -0.009467592876868191, 0.017462499999999995));
|
||||
#3455 = DIRECTION('NONE', (0.9749279121818237, -0.22252093395631437, 0));
|
||||
#3454 = CARTESIAN_POINT('NONE', (0.041480234658033126, -0.00946759287686819, 0.0174625));
|
||||
#3455 = DIRECTION('NONE', (0.9749279121818235, -0.22252093395631442, 0));
|
||||
#3456 = AXIS2_PLACEMENT_3D('NONE', #3454, #3455, $);
|
||||
#3457 = PLANE('NONE', #3456);
|
||||
#3458 = CARTESIAN_POINT('NONE', (0.036295974251609464, -0.015054896783573819, 0.0174625));
|
||||
@ -3496,20 +3496,20 @@ DATA;
|
||||
#3480 = DIRECTION('NONE', (-0.43388373911755784, 0.9009688679024194, 0.000000000000000000000000000000006162975822039155));
|
||||
#3481 = AXIS2_PLACEMENT_3D('NONE', #3479, #3480, $);
|
||||
#3482 = PLANE('NONE', #3481);
|
||||
#3483 = CARTESIAN_POINT('NONE', (0.01944700165366045, -0.025168765453632568, 0.0174625));
|
||||
#3484 = DIRECTION('NONE', (0.5633200580636224, 0.8262387743159947, 0));
|
||||
#3483 = CARTESIAN_POINT('NONE', (0.01944700165366045, -0.02516876545363257, 0.0174625));
|
||||
#3484 = DIRECTION('NONE', (0.5633200580636222, 0.8262387743159947, 0));
|
||||
#3485 = AXIS2_PLACEMENT_3D('NONE', #3483, #3484, $);
|
||||
#3486 = PLANE('NONE', #3485);
|
||||
#3487 = CARTESIAN_POINT('NONE', (0.02275405317864496, -0.03203592870483008, 0.0174625));
|
||||
#3488 = DIRECTION('NONE', (0.9972037971811802, -0.07473009358642456, 0.0000000000000000000000000000000015407439555097887));
|
||||
#3487 = CARTESIAN_POINT('NONE', (0.022754053178644963, -0.032035928704830074, 0.017462499999999995));
|
||||
#3488 = DIRECTION('NONE', (0.9972037971811802, -0.07473009358642414, 0));
|
||||
#3489 = AXIS2_PLACEMENT_3D('NONE', #3487, #3488, $);
|
||||
#3490 = PLANE('NONE', #3489);
|
||||
#3491 = CARTESIAN_POINT('NONE', (0.018460441113665228, -0.03833350096268949, 0.017462499999999995));
|
||||
#3492 = DIRECTION('NONE', (0.43388373911755723, -0.9009688679024195, 0));
|
||||
#3491 = CARTESIAN_POINT('NONE', (0.018460441113665235, -0.03833350096268949, 0.0174625));
|
||||
#3492 = DIRECTION('NONE', (0.4338837391175577, -0.9009688679024195, 0));
|
||||
#3493 = AXIS2_PLACEMENT_3D('NONE', #3491, #3492, $);
|
||||
#3494 = PLANE('NONE', #3493);
|
||||
#3495 = CARTESIAN_POINT('NONE', (0.01085977752370099, -0.03776390996935139, 0.0174625));
|
||||
#3496 = DIRECTION('NONE', (-0.5633200580636213, -0.8262387743159954, -0));
|
||||
#3496 = DIRECTION('NONE', (-0.5633200580636212, -0.8262387743159955, -0));
|
||||
#3497 = AXIS2_PLACEMENT_3D('NONE', #3495, #3496, $);
|
||||
#3498 = PLANE('NONE', #3497);
|
||||
#3499 = CARTESIAN_POINT('NONE', (0.015153389588680722, -0.03146633771149198, 0.0174625));
|
||||
@ -3533,20 +3533,20 @@ DATA;
|
||||
#3517 = DIRECTION('NONE', (0.43388373911755823, 0.9009688679024191, 0));
|
||||
#3518 = AXIS2_PLACEMENT_3D('NONE', #3516, #3517, $);
|
||||
#3519 = PLANE('NONE', #3518);
|
||||
#3520 = CARTESIAN_POINT('NONE', (-0.00755272599871647, -0.030896746718153883, 0.017462499999999995));
|
||||
#3521 = DIRECTION('NONE', (0.9972037971811802, 0.074730093586424, 0));
|
||||
#3520 = CARTESIAN_POINT('NONE', (-0.007552725998716469, -0.030896746718153886, 0.017462499999999992));
|
||||
#3521 = DIRECTION('NONE', (0.9972037971811802, 0.07473009358642403, 0));
|
||||
#3522 = AXIS2_PLACEMENT_3D('NONE', #3520, #3521, $);
|
||||
#3523 = PLANE('NONE', #3522);
|
||||
#3524 = CARTESIAN_POINT('NONE', (-0.010859777523700983, -0.037763909969351396, 0.017462499999999995));
|
||||
#3525 = DIRECTION('NONE', (0.5633200580636216, -0.8262387743159952, 0));
|
||||
#3524 = CARTESIAN_POINT('NONE', (-0.01085977752370098, -0.037763909969351396, 0.017462499999999995));
|
||||
#3525 = DIRECTION('NONE', (0.563320058063622, -0.8262387743159951, 0));
|
||||
#3526 = AXIS2_PLACEMENT_3D('NONE', #3524, #3525, $);
|
||||
#3527 = PLANE('NONE', #3526);
|
||||
#3528 = CARTESIAN_POINT('NONE', (-0.018460441113665228, -0.03833350096268949, 0.017462499999999992));
|
||||
#3529 = DIRECTION('NONE', (-0.4338837391175573, -0.9009688679024197, -0));
|
||||
#3528 = CARTESIAN_POINT('NONE', (-0.018460441113665224, -0.0383335009626895, 0.017462499999999995));
|
||||
#3529 = DIRECTION('NONE', (-0.43388373911755745, -0.9009688679024194, 0.000000000000000000000000000000006162975822039155));
|
||||
#3530 = AXIS2_PLACEMENT_3D('NONE', #3528, #3529, $);
|
||||
#3531 = PLANE('NONE', #3530);
|
||||
#3532 = CARTESIAN_POINT('NONE', (-0.022754053178644953, -0.03203592870483008, 0.017462499999999995));
|
||||
#3533 = DIRECTION('NONE', (-0.9972037971811802, -0.07473009358642368, 0));
|
||||
#3533 = DIRECTION('NONE', (-0.9972037971811802, -0.07473009358642413, -0.0000000000000000000000000000000015407439555097887));
|
||||
#3534 = AXIS2_PLACEMENT_3D('NONE', #3532, #3533, $);
|
||||
#3535 = PLANE('NONE', #3534);
|
||||
#3536 = CARTESIAN_POINT('NONE', (-0.015153389588680708, -0.031466337711491994, 0.017462499999999995));
|
||||
@ -3570,20 +3570,20 @@ DATA;
|
||||
#3554 = DIRECTION('NONE', (0.9749279121818237, 0.22252093395631356, 0));
|
||||
#3555 = AXIS2_PLACEMENT_3D('NONE', #3553, #3554, $);
|
||||
#3556 = PLANE('NONE', #3555);
|
||||
#3557 = CARTESIAN_POINT('NONE', (-0.028865096926526532, -0.01335884752512989, 0.0174625));
|
||||
#3558 = DIRECTION('NONE', (0.6801727377709186, -0.7330518718298271, 0.000000000000000000000000000000006162975822039155));
|
||||
#3557 = CARTESIAN_POINT('NONE', (-0.028865096926526532, -0.013358847525129893, 0.0174625));
|
||||
#3558 = DIRECTION('NONE', (0.6801727377709185, -0.7330518718298272, 0));
|
||||
#3559 = AXIS2_PLACEMENT_3D('NONE', #3557, #3558, $);
|
||||
#3560 = PLANE('NONE', #3559);
|
||||
#3561 = CARTESIAN_POINT('NONE', (-0.03629597425160948, -0.015054896783573798, 0.0174625));
|
||||
#3562 = DIRECTION('NONE', (-0.2947551744109055, -0.9555728057861405, -0.000000000000000000000000000000006162975822039155));
|
||||
#3561 = CARTESIAN_POINT('NONE', (-0.03629597425160948, -0.0150548967835738, 0.017462499999999995));
|
||||
#3562 = DIRECTION('NONE', (-0.2947551744109054, -0.9555728057861405, -0));
|
||||
#3563 = AXIS2_PLACEMENT_3D('NONE', #3561, #3562, $);
|
||||
#3564 = PLANE('NONE', #3563);
|
||||
#3565 = CARTESIAN_POINT('NONE', (-0.041480234658033126, -0.009467592876868158, 0.017462499999999995));
|
||||
#3566 = DIRECTION('NONE', (-0.974927912181824, -0.22252093395631345, 0));
|
||||
#3565 = CARTESIAN_POINT('NONE', (-0.04148023465803313, -0.009467592876868165, 0.0174625));
|
||||
#3566 = DIRECTION('NONE', (-0.974927912181824, -0.2225209339563127, -0));
|
||||
#3567 = AXIS2_PLACEMENT_3D('NONE', #3565, #3566, $);
|
||||
#3568 = PLANE('NONE', #3567);
|
||||
#3569 = CARTESIAN_POINT('NONE', (-0.03923361773937384, -0.0021842397117186212, 0.0174625));
|
||||
#3570 = DIRECTION('NONE', (-0.6801727377709191, 0.7330518718298266, -0));
|
||||
#3569 = CARTESIAN_POINT('NONE', (-0.03923361773937384, -0.002184239711718622, 0.0174625));
|
||||
#3570 = DIRECTION('NONE', (-0.6801727377709194, 0.7330518718298266, -0));
|
||||
#3571 = AXIS2_PLACEMENT_3D('NONE', #3569, #3570, $);
|
||||
#3572 = PLANE('NONE', #3571);
|
||||
#3573 = CARTESIAN_POINT('NONE', (-0.0340493573329502, -0.007771543618424253, 0.0174625));
|
||||
@ -3608,15 +3608,15 @@ DATA;
|
||||
#3592 = AXIS2_PLACEMENT_3D('NONE', #3590, #3591, $);
|
||||
#3593 = PLANE('NONE', #3592);
|
||||
#3594 = CARTESIAN_POINT('NONE', (-0.028441461127989853, 0.014238536325145318, 0.0174625));
|
||||
#3595 = DIRECTION('NONE', (-0.1490422661761743, -0.9888308262251286, 0.0000000000000000000000000000000030814879110195774));
|
||||
#3595 = DIRECTION('NONE', (-0.14904226617617458, -0.9888308262251286, -0));
|
||||
#3596 = AXIS2_PLACEMENT_3D('NONE', #3594, #3595, $);
|
||||
#3597 = PLANE('NONE', #3596);
|
||||
#3598 = CARTESIAN_POINT('NONE', (-0.03440056206511038, 0.018990760744163133, 0.0174625));
|
||||
#3599 = DIRECTION('NONE', (-0.9308737486442047, -0.3653410243663939, 0));
|
||||
#3598 = CARTESIAN_POINT('NONE', (-0.03440056206511038, 0.018990760744163133, 0.017462499999999995));
|
||||
#3599 = DIRECTION('NONE', (-0.9308737486442044, -0.36534102436639526, -0));
|
||||
#3600 = AXIS2_PLACEMENT_3D('NONE', #3598, #3599, $);
|
||||
#3601 = PLANE('NONE', #3600);
|
||||
#3602 = CARTESIAN_POINT('NONE', (-0.03326456546231646, 0.026527605748934074, 0.017462499999999995));
|
||||
#3603 = DIRECTION('NONE', (-0.7818314824680305, 0.6234898018587326, -0.00000000000000000000000000000001232595164407831));
|
||||
#3602 = CARTESIAN_POINT('NONE', (-0.033264565462316466, 0.026527605748934074, 0.0174625));
|
||||
#3603 = DIRECTION('NONE', (-0.7818314824680298, 0.6234898018587336, -0));
|
||||
#3604 = AXIS2_PLACEMENT_3D('NONE', #3602, #3603, $);
|
||||
#3605 = PLANE('NONE', #3604);
|
||||
#3606 = CARTESIAN_POINT('NONE', (-0.02616946792240203, 0.029312226334687202, 0.0174625));
|
||||
|
@ -2571,21 +2571,21 @@ DATA;
|
||||
#2555 = VERTEX_POINT('NONE', #2554);
|
||||
#2556 = CARTESIAN_POINT('NONE', (-0.007619999999999999, -0.04635499999999999, 0.0254));
|
||||
#2557 = VERTEX_POINT('NONE', #2556);
|
||||
#2558 = CARTESIAN_POINT('NONE', (0.0020980400000000002, -0.04167632, 0.0238125));
|
||||
#2558 = CARTESIAN_POINT('NONE', (0.0020980400000000007, -0.04167632, 0.0238125));
|
||||
#2559 = VERTEX_POINT('NONE', #2558);
|
||||
#2560 = CARTESIAN_POINT('NONE', (0.0012729244244215345, -0.0425658054737599, 0.0238125));
|
||||
#2560 = CARTESIAN_POINT('NONE', (0.0012729244244215347, -0.0425658054737599, 0.0238125));
|
||||
#2561 = VERTEX_POINT('NONE', #2560);
|
||||
#2562 = CARTESIAN_POINT('NONE', (0.0012729244244215345, -0.0425658054737599, 0.0254));
|
||||
#2562 = CARTESIAN_POINT('NONE', (0.0012729244244215347, -0.0425658054737599, 0.0254));
|
||||
#2563 = VERTEX_POINT('NONE', #2562);
|
||||
#2564 = CARTESIAN_POINT('NONE', (0.0020980400000000002, -0.04167632, 0.0254));
|
||||
#2564 = CARTESIAN_POINT('NONE', (0.0020980400000000007, -0.04167632, 0.0254));
|
||||
#2565 = VERTEX_POINT('NONE', #2564);
|
||||
#2566 = CARTESIAN_POINT('NONE', (-0.0006804866009285434, -0.0446716083246068, 0.0238125));
|
||||
#2566 = CARTESIAN_POINT('NONE', (-0.000680486600928543, -0.0446716083246068, 0.0238125));
|
||||
#2567 = VERTEX_POINT('NONE', #2566);
|
||||
#2568 = CARTESIAN_POINT('NONE', (-0.0006804866009285434, -0.0446716083246068, 0.0254));
|
||||
#2568 = CARTESIAN_POINT('NONE', (-0.000680486600928543, -0.0446716083246068, 0.0254));
|
||||
#2569 = VERTEX_POINT('NONE', #2568);
|
||||
#2570 = CARTESIAN_POINT('NONE', (-0.0015096417774425879, -0.045565448541457644, 0.0238125));
|
||||
#2570 = CARTESIAN_POINT('NONE', (-0.0015096417774425877, -0.045565448541457644, 0.0238125));
|
||||
#2571 = VERTEX_POINT('NONE', #2570);
|
||||
#2572 = CARTESIAN_POINT('NONE', (-0.0015096417774425879, -0.045565448541457644, 0.0254));
|
||||
#2572 = CARTESIAN_POINT('NONE', (-0.0015096417774425877, -0.045565448541457644, 0.0254));
|
||||
#2573 = VERTEX_POINT('NONE', #2572);
|
||||
#2574 = CARTESIAN_POINT('NONE', (-0.0010921999999999998, -0.04595367999999999, 0.0238125));
|
||||
#2575 = VERTEX_POINT('NONE', #2574);
|
||||
@ -10417,58 +10417,58 @@ DATA;
|
||||
#10401 = VECTOR('NONE', #10400, 1);
|
||||
#10402 = CARTESIAN_POINT('NONE', (-0.007619999999999999, -0.04635499999999999, 0.0254));
|
||||
#10403 = LINE('NONE', #10402, #10401);
|
||||
#10404 = DIRECTION('NONE', (-0.6800813455659818, -0.7331366608028573, 0));
|
||||
#10404 = DIRECTION('NONE', (-0.6800813455659819, -0.7331366608028572, 0));
|
||||
#10405 = VECTOR('NONE', #10404, 1);
|
||||
#10406 = CARTESIAN_POINT('NONE', (0.0020980400000000002, -0.04167632, 0.0238125));
|
||||
#10406 = CARTESIAN_POINT('NONE', (0.0020980400000000007, -0.04167632, 0.0238125));
|
||||
#10407 = LINE('NONE', #10406, #10405);
|
||||
#10408 = DIRECTION('NONE', (0, 0, 1));
|
||||
#10409 = VECTOR('NONE', #10408, 1);
|
||||
#10410 = CARTESIAN_POINT('NONE', (0.0012729244244215345, -0.0425658054737599, 0.0238125));
|
||||
#10410 = CARTESIAN_POINT('NONE', (0.0012729244244215347, -0.0425658054737599, 0.0238125));
|
||||
#10411 = LINE('NONE', #10410, #10409);
|
||||
#10412 = DIRECTION('NONE', (-0.6800813455659818, -0.7331366608028573, 0));
|
||||
#10412 = DIRECTION('NONE', (-0.6800813455659819, -0.7331366608028572, 0));
|
||||
#10413 = VECTOR('NONE', #10412, 1);
|
||||
#10414 = CARTESIAN_POINT('NONE', (0.0020980400000000002, -0.04167632, 0.0254));
|
||||
#10414 = CARTESIAN_POINT('NONE', (0.0020980400000000007, -0.04167632, 0.0254));
|
||||
#10415 = LINE('NONE', #10414, #10413);
|
||||
#10416 = DIRECTION('NONE', (0, 0, 1));
|
||||
#10417 = VECTOR('NONE', #10416, 1);
|
||||
#10418 = CARTESIAN_POINT('NONE', (0.0020980400000000002, -0.04167632, 0.0238125));
|
||||
#10418 = CARTESIAN_POINT('NONE', (0.0020980400000000007, -0.04167632, 0.0238125));
|
||||
#10419 = LINE('NONE', #10418, #10417);
|
||||
#10420 = DIRECTION('NONE', (0.5276972660417225, 0.8494325137479091, -0));
|
||||
#10421 = DIRECTION('NONE', (0.0000000000000025022368681948567, -0.000000000000001554477292738876, 1));
|
||||
#10422 = CARTESIAN_POINT('NONE', (0.0005008822163118523, -0.04380855921867364, 0.0238125));
|
||||
#10420 = DIRECTION('NONE', (0.5276972660417221, 0.8494325137479093, -0));
|
||||
#10421 = DIRECTION('NONE', (0.0000000000000025022368681948575, -0.0000000000000015544772927388748, 1));
|
||||
#10422 = CARTESIAN_POINT('NONE', (0.0005008822163118532, -0.04380855921867364, 0.0238125));
|
||||
#10423 = AXIS2_PLACEMENT_3D('NONE', #10422, #10421, #10420);
|
||||
#10424 = CIRCLE('NONE', #10423, 0.001463040000000001);
|
||||
#10424 = CIRCLE('NONE', #10423, 0.0014630400000000007);
|
||||
#10425 = DIRECTION('NONE', (0, 0, 1));
|
||||
#10426 = VECTOR('NONE', #10425, 1);
|
||||
#10427 = CARTESIAN_POINT('NONE', (-0.0006804866009285434, -0.0446716083246068, 0.0238125));
|
||||
#10427 = CARTESIAN_POINT('NONE', (-0.000680486600928543, -0.0446716083246068, 0.0238125));
|
||||
#10428 = LINE('NONE', #10427, #10426);
|
||||
#10429 = DIRECTION('NONE', (0.5276972660417225, 0.8494325137479091, -0));
|
||||
#10430 = DIRECTION('NONE', (-0.0000000000000025022368681948567, 0.000000000000001554477292738876, 1));
|
||||
#10429 = DIRECTION('NONE', (0.5276972660417224, 0.8494325137479088, -0));
|
||||
#10430 = DIRECTION('NONE', (-0.0000000000000025022368681948563, 0.0000000000000015544772927388758, 0.9999999999999998));
|
||||
#10431 = CARTESIAN_POINT('NONE', (0.0005008822163118523, -0.04380855921867364, 0.0254));
|
||||
#10432 = AXIS2_PLACEMENT_3D('NONE', #10431, #10430, #10429);
|
||||
#10433 = CIRCLE('NONE', #10432, 0.001463040000000001);
|
||||
#10433 = CIRCLE('NONE', #10432, 0.0014630400000000014);
|
||||
#10434 = DIRECTION('NONE', (-0.6800813455659821, -0.733136660802857, 0));
|
||||
#10435 = VECTOR('NONE', #10434, 1);
|
||||
#10436 = CARTESIAN_POINT('NONE', (-0.000680486600928543, -0.0446716083246068, 0.0238125));
|
||||
#10436 = CARTESIAN_POINT('NONE', (-0.0006804866009285428, -0.0446716083246068, 0.0238125));
|
||||
#10437 = LINE('NONE', #10436, #10435);
|
||||
#10438 = DIRECTION('NONE', (0, 0, 1));
|
||||
#10439 = VECTOR('NONE', #10438, 1);
|
||||
#10440 = CARTESIAN_POINT('NONE', (-0.0015096417774425879, -0.045565448541457644, 0.0238125));
|
||||
#10440 = CARTESIAN_POINT('NONE', (-0.0015096417774425877, -0.045565448541457644, 0.0238125));
|
||||
#10441 = LINE('NONE', #10440, #10439);
|
||||
#10442 = DIRECTION('NONE', (-0.6800813455659821, -0.733136660802857, 0));
|
||||
#10443 = VECTOR('NONE', #10442, 1);
|
||||
#10444 = CARTESIAN_POINT('NONE', (-0.000680486600928543, -0.0446716083246068, 0.0254));
|
||||
#10444 = CARTESIAN_POINT('NONE', (-0.0006804866009285428, -0.0446716083246068, 0.0254));
|
||||
#10445 = LINE('NONE', #10444, #10443);
|
||||
#10446 = DIRECTION('NONE', (-0.7529894373157879, -0.6580326035166139, -0));
|
||||
#10446 = DIRECTION('NONE', (-0.7529894373157879, -0.6580326035166137, -0));
|
||||
#10447 = DIRECTION('NONE', (0, 0, -1));
|
||||
#10448 = CARTESIAN_POINT('NONE', (0.0004985810518786167, -0.04381047558787883, 0.0238125));
|
||||
#10448 = CARTESIAN_POINT('NONE', (0.0004985810518786172, -0.04381047558787883, 0.0238125));
|
||||
#10449 = AXIS2_PLACEMENT_3D('NONE', #10448, #10447, #10446);
|
||||
#10450 = CIRCLE('NONE', #10449, 0.0026669999999999975);
|
||||
#10451 = DIRECTION('NONE', (-0.7529894373157879, -0.6580326035166139, -0));
|
||||
#10450 = CIRCLE('NONE', #10449, 0.002666999999999998);
|
||||
#10451 = DIRECTION('NONE', (-0.7529894373157879, -0.6580326035166137, -0));
|
||||
#10452 = DIRECTION('NONE', (0, 0, -1));
|
||||
#10453 = CARTESIAN_POINT('NONE', (0.0004985810518786167, -0.04381047558787883, 0.0254));
|
||||
#10453 = CARTESIAN_POINT('NONE', (0.0004985810518786172, -0.04381047558787883, 0.0254));
|
||||
#10454 = AXIS2_PLACEMENT_3D('NONE', #10453, #10452, #10451);
|
||||
#10455 = CIRCLE('NONE', #10454, 0.0026669999999999975);
|
||||
#10455 = CIRCLE('NONE', #10454, 0.002666999999999998);
|
||||
#10456 = DIRECTION('NONE', (0.6800813455659818, 0.7331366608028573, 0));
|
||||
#10457 = VECTOR('NONE', #10456, 1);
|
||||
#10458 = CARTESIAN_POINT('NONE', (-0.0010921999999999998, -0.04595367999999999, 0.0238125));
|
||||
@ -15570,24 +15570,24 @@ DATA;
|
||||
#15554 = DIRECTION('NONE', (1, 0, -0));
|
||||
#15555 = AXIS2_PLACEMENT_3D('NONE', #15553, #15554, $);
|
||||
#15556 = PLANE('NONE', #15555);
|
||||
#15557 = CARTESIAN_POINT('NONE', (0.001685482212210767, -0.04212106273687995, 0.024606250000000003));
|
||||
#15558 = DIRECTION('NONE', (-0.7331366608028554, 0.6800813455659833, -0));
|
||||
#15557 = CARTESIAN_POINT('NONE', (0.0016854822122107677, -0.04212106273687995, 0.024606250000000003));
|
||||
#15558 = DIRECTION('NONE', (-0.7331366608028557, 0.6800813455659834, -0));
|
||||
#15559 = AXIS2_PLACEMENT_3D('NONE', #15557, #15558, $);
|
||||
#15560 = PLANE('NONE', #15559);
|
||||
#15561 = CARTESIAN_POINT('NONE', (0.0005008822163118532, -0.04380855921867364, 0.02460625));
|
||||
#15562 = DIRECTION('NONE', (0, 0, 1));
|
||||
#15563 = DIRECTION('NONE', (0.527697266041722, 0.8494325137479093, -0));
|
||||
#15563 = DIRECTION('NONE', (0.5276972660417221, 0.8494325137479093, -0));
|
||||
#15564 = AXIS2_PLACEMENT_3D('NONE', #15561, #15562, #15563);
|
||||
#15565 = CYLINDRICAL_SURFACE('NONE', #15564, 0.0014630400000000007);
|
||||
#15566 = CARTESIAN_POINT('NONE', (-0.0010950641891855268, -0.045118528433032185, 0.02460625));
|
||||
#15566 = CARTESIAN_POINT('NONE', (-0.0010950641891855266, -0.045118528433032185, 0.02460625));
|
||||
#15567 = DIRECTION('NONE', (-0.733136660802859, 0.6800813455659798, -0));
|
||||
#15568 = AXIS2_PLACEMENT_3D('NONE', #15566, #15567, $);
|
||||
#15569 = PLANE('NONE', #15568);
|
||||
#15570 = CARTESIAN_POINT('NONE', (0.0004985810518786167, -0.04381047558787883, 0.02460625));
|
||||
#15570 = CARTESIAN_POINT('NONE', (0.0004985810518786172, -0.04381047558787883, 0.02460625));
|
||||
#15571 = DIRECTION('NONE', (0, 0, -1));
|
||||
#15572 = DIRECTION('NONE', (-0.7529894373157879, -0.6580326035166139, -0));
|
||||
#15572 = DIRECTION('NONE', (-0.7529894373157879, -0.6580326035166137, -0));
|
||||
#15573 = AXIS2_PLACEMENT_3D('NONE', #15570, #15571, #15572);
|
||||
#15574 = CYLINDRICAL_SURFACE('NONE', #15573, 0.0026669999999999975);
|
||||
#15574 = CYLINDRICAL_SURFACE('NONE', #15573, 0.002666999999999998);
|
||||
#15575 = CARTESIAN_POINT('NONE', (-0.0006796422122107669, -0.045508937263120046, 0.024606250000000003));
|
||||
#15576 = DIRECTION('NONE', (0.7331366608028589, -0.68008134556598, 0));
|
||||
#15577 = AXIS2_PLACEMENT_3D('NONE', #15575, #15576, $);
|
||||
|
@ -3,7 +3,7 @@
|
||||
# This way we don't start and stop too many engine instances, putting pressure on our cloud.
|
||||
uses-engine = { max-threads = 4 }
|
||||
# If a test must run after the engine tests, we want to make sure the engine tests are done first.
|
||||
after-engine = { depends-on = ["uses-engine"], max-threads = 12 }
|
||||
after-engine = { max-threads = 12 }
|
||||
|
||||
[profile.default]
|
||||
slow-timeout = { period = "30s", terminate-after = 1 }
|
||||
|
55
rust/Cargo.lock
generated
55
rust/Cargo.lock
generated
@ -1783,7 +1783,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-bumper"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1794,7 +1794,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-derive-docs"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"anyhow",
|
||||
@ -1813,7 +1813,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-directory-test-macro"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1822,7 +1822,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-language-server"
|
||||
version = "0.2.47"
|
||||
version = "0.2.49"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1843,7 +1843,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-language-server-release"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1863,7 +1863,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.2.47"
|
||||
version = "0.2.49"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx 0.5.1",
|
||||
@ -1931,7 +1931,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-python-bindings"
|
||||
version = "0.3.47"
|
||||
version = "0.3.49"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kcl-lib",
|
||||
@ -1946,7 +1946,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-test-server"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hyper 0.14.32",
|
||||
@ -1959,7 +1959,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-to-core"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1973,7 +1973,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-wasm-lib"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
dependencies = [
|
||||
"bson",
|
||||
"console_error_panic_hook",
|
||||
@ -2751,9 +2751,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3"
|
||||
version = "0.22.6"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f402062616ab18202ae8319da13fa4279883a2b8a9d9f83f20dbade813ce1884"
|
||||
checksum = "7f1c6c3591120564d64db2261bec5f910ae454f01def849b9c22835a84695e86"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"indoc",
|
||||
@ -2770,9 +2770,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-build-config"
|
||||
version = "0.22.6"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b14b5775b5ff446dd1056212d778012cbe8a0fbffd368029fd9e25b514479c38"
|
||||
checksum = "e9b6c2b34cf71427ea37c7001aefbaeb85886a074795e35f161f5aecc7620a7a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"target-lexicon",
|
||||
@ -2780,9 +2780,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-ffi"
|
||||
version = "0.22.6"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ab5bcf04a2cdcbb50c7d6105de943f543f9ed92af55818fd17b660390fc8636"
|
||||
checksum = "5507651906a46432cdda02cd02dd0319f6064f1374c9147c45b978621d2c3a9c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pyo3-build-config",
|
||||
@ -2790,9 +2790,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-macros"
|
||||
version = "0.22.6"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fd24d897903a9e6d80b968368a34e1525aeb719d568dba8b3d4bfa5dc67d453"
|
||||
checksum = "b0d394b5b4fd8d97d48336bb0dd2aebabad39f1d294edd6bcd2cccf2eefe6f42"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"pyo3-macros-backend",
|
||||
@ -2802,9 +2802,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-macros-backend"
|
||||
version = "0.22.6"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36c011a03ba1e50152b4b394b479826cad97e7a21eb52df179cd91ac411cbfbe"
|
||||
checksum = "fd72da09cfa943b1080f621f024d2ef7e2773df7badd51aa30a2be1f8caa7c8e"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@ -3097,15 +3097,14 @@ checksum = "e6cd655523701785087f69900df39892fb7b9b0721aa67682f571c38c32ac58a"
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.8"
|
||||
version = "0.17.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
|
||||
checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.15",
|
||||
"libc",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
@ -3560,12 +3559,6 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
@ -3735,9 +3728,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.16"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
||||
checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
|
@ -38,7 +38,7 @@ kittycad = { version = "0.3.28", default-features = false, features = ["js", "re
|
||||
kittycad-modeling-cmds = { version = "0.2.100", features = ["ts-rs", "websocket"] }
|
||||
lazy_static = "1.5.0"
|
||||
miette = "7.5.0"
|
||||
pyo3 = { version = "0.22.6" }
|
||||
pyo3 = { version = "0.24.0" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = { version = "1" }
|
||||
slog = "2.7.0"
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
[package]
|
||||
name = "kcl-bumper"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/KittyCAD/modeling-api"
|
||||
rust-version = "1.76"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-derive-docs"
|
||||
description = "A tool for generating documentation from Rust derive macros"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-directory-test-macro"
|
||||
description = "A tool for generating tests from a directory of kcl files"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "kcl-language-server-release"
|
||||
version = "0.1.47"
|
||||
version = "0.1.49"
|
||||
edition = "2021"
|
||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||
publish = false
|
||||
|
@ -72,7 +72,7 @@ impl Build {
|
||||
}
|
||||
|
||||
fn build_client(sh: &Shell, version: &str, release_tag: &str, target: &Target) -> anyhow::Result<()> {
|
||||
let bundle_path = Path::new("server");
|
||||
let bundle_path = Path::new("kcl-language-server/server");
|
||||
sh.create_dir(bundle_path)?;
|
||||
sh.copy_file(&target.server_path, bundle_path)?;
|
||||
if let Some(symbols_path) = &target.symbols_path {
|
||||
|
@ -2,7 +2,7 @@
|
||||
name = "kcl-language-server"
|
||||
description = "A language server for KCL."
|
||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||
version = "0.2.47"
|
||||
version = "0.2.49"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@ -42,13 +42,3 @@ tower-lsp = { version = "0.20.0", default-features = false, features = [
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[profile.dev]
|
||||
# Disabling debug info speeds up builds a bunch,
|
||||
# and we don't rely on it for debugging that much.
|
||||
debug = 0
|
||||
|
||||
[profile.release]
|
||||
incremental = true
|
||||
# Set this to 1 or 2 to get more useful backtraces in debugger.
|
||||
debug = 0
|
||||
|
@ -97,7 +97,7 @@ async function getServer(
|
||||
'You need to manually clone the kcl-lsp repository and ' +
|
||||
'run `cargo install` to build the language server from sources. ' +
|
||||
'If you feel that your platform should be supported, please create an issue ' +
|
||||
'about that [here](https://github.com/kittycad/kcl-lsp/issues) and we ' +
|
||||
'about that [here](https://github.com/kittycad/modeling-app/issues) and we ' +
|
||||
'will consider it.'
|
||||
)
|
||||
return undefined
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-lib"
|
||||
description = "KittyCAD Language implementation and tools"
|
||||
version = "0.2.47"
|
||||
version = "0.2.49"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
@ -145,10 +145,6 @@ name = "lsp_semantic_tokens_benchmark_criterion"
|
||||
harness = false
|
||||
required-features = ["lsp-test-util"]
|
||||
|
||||
[[bench]]
|
||||
name = "executor_benchmark_criterion"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "benchmark_kcl_samples"
|
||||
harness = false
|
||||
|
@ -4,7 +4,6 @@ use std::{
|
||||
};
|
||||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
const IGNORE_DIRS: [&str; 2] = ["step", "screenshots"];
|
||||
|
||||
@ -46,7 +45,7 @@ fn run_benchmarks(c: &mut Criterion) {
|
||||
|
||||
let benchmark_dirs = discover_benchmark_dirs(&base_dir);
|
||||
|
||||
let rt = Runtime::new().unwrap();
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
|
||||
for dir in benchmark_dirs {
|
||||
let dir_name = dir.file_name().unwrap().to_string_lossy().to_string();
|
||||
@ -70,20 +69,21 @@ fn run_benchmarks(c: &mut Criterion) {
|
||||
|
||||
let program = kcl_lib::Program::parse_no_errs(&input_content).unwrap();
|
||||
|
||||
group.bench_function("parse", |b| {
|
||||
group.bench_function(format!("parse_{}", dir_name), |b| {
|
||||
b.iter(|| kcl_lib::Program::parse_no_errs(black_box(&input_content)).unwrap())
|
||||
});
|
||||
|
||||
group.bench_function("execute", |b| {
|
||||
group.bench_function(format!("execute_{}", dir_name), |b| {
|
||||
b.iter(|| {
|
||||
rt.block_on(async {
|
||||
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
if let Err(err) = rt.block_on(async {
|
||||
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()).await?;
|
||||
let mut exec_state = kcl_lib::ExecState::new(&ctx.settings);
|
||||
ctx.run(black_box(&program), &mut exec_state).await.unwrap();
|
||||
ctx.run(black_box(&program), &mut exec_state).await?;
|
||||
ctx.close().await;
|
||||
})
|
||||
Ok::<(), anyhow::Error>(())
|
||||
}) {
|
||||
panic!("Failed to execute program: {}", err);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -1,63 +0,0 @@
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use kcl_lib::{test_server, UnitLength::Mm};
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
pub fn bench_execute(c: &mut Criterion) {
|
||||
for (name, code) in [
|
||||
("big_kitt", KITT_PROGRAM),
|
||||
("cube", CUBE_PROGRAM),
|
||||
("server_rack_lite", SERVER_RACK_LITE_PROGRAM),
|
||||
("server_rack_heavy", SERVER_RACK_HEAVY_PROGRAM),
|
||||
("lsystem", LSYSTEM_PROGRAM),
|
||||
] {
|
||||
let mut group = c.benchmark_group("executor");
|
||||
// Configure Criterion.rs to detect smaller differences and increase sample size to improve
|
||||
// precision and counteract the resulting noise.
|
||||
group
|
||||
.sample_size(10)
|
||||
.measurement_time(std::time::Duration::from_secs(1)); // Short
|
||||
// measurement
|
||||
// time to keep
|
||||
// it from
|
||||
// running in
|
||||
// parallel
|
||||
group.bench_with_input(BenchmarkId::new("execute", name), &code, |b, &s| {
|
||||
let rt = Runtime::new().unwrap();
|
||||
// Spawn a future onto the runtime
|
||||
b.iter(|| {
|
||||
rt.block_on(test_server::execute_and_snapshot(s, Mm, None)).unwrap();
|
||||
});
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bench_lego(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("executor_lego_pattern");
|
||||
// Configure Criterion.rs to detect smaller differences and increase sample size to improve
|
||||
// precision and counteract the resulting noise.
|
||||
group.sample_size(10);
|
||||
// Create lego bricks with N x 10 bumps, where N is each element of `sizes`.
|
||||
let sizes = vec![1, 2, 4];
|
||||
for size in sizes {
|
||||
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
|
||||
let rt = Runtime::new().unwrap();
|
||||
let code = LEGO_PROGRAM.replace("{{N}}", &size.to_string());
|
||||
// Spawn a future onto the runtime
|
||||
b.iter(|| {
|
||||
rt.block_on(test_server::execute_and_snapshot(&code, Mm, None)).unwrap();
|
||||
});
|
||||
});
|
||||
}
|
||||
group.finish();
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_lego, bench_execute);
|
||||
criterion_main!(benches);
|
||||
|
||||
const KITT_PROGRAM: &str = include_str!("../e2e/executor/inputs/kittycad_svg.kcl");
|
||||
const CUBE_PROGRAM: &str = include_str!("../e2e/executor/inputs/cube.kcl");
|
||||
const SERVER_RACK_HEAVY_PROGRAM: &str = include_str!("../e2e/executor/inputs/server-rack-heavy.kcl");
|
||||
const SERVER_RACK_LITE_PROGRAM: &str = include_str!("../e2e/executor/inputs/server-rack-lite.kcl");
|
||||
const LEGO_PROGRAM: &str = include_str!("../e2e/executor/inputs/slow_lego.kcl.tmpl");
|
||||
const LSYSTEM_PROGRAM: &str = include_str!("../e2e/executor/inputs/lsystem.kcl");
|
@ -1,8 +1,15 @@
|
||||
const part001 = startSketchOn('XY')
|
||||
|> startProfileAt([0,0], %)
|
||||
|> line(end = [0, 10], tag = $thing)
|
||||
|> line(end = [10, 0])
|
||||
|> line(end = [0, -10], tag = $thing2)
|
||||
|> close()
|
||||
|> extrude(length = 10)
|
||||
|> fillet(radius = 0.5, tags = [thing, thing])
|
||||
startProfileAt([0, 0], startSketchOn("XY"))
|
||||
|> xLine(length = 10, tag = $line000)
|
||||
|> yLine(length = 10, tag = $line001)
|
||||
|> xLine(endAbsolute = profileStartX(%), tag = $line002)
|
||||
|> close(tag = $line003)
|
||||
|> extrude(length = 10)
|
||||
|> fillet(
|
||||
radius = 1,
|
||||
tags = [
|
||||
line003,
|
||||
getNextAdjacentEdge(line000),
|
||||
getPreviousAdjacentEdge(line001)
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -27,11 +27,14 @@ async fn kcl_test_fillet_duplicate_tags() {
|
||||
let code = kcl_input!("fillet_duplicate_tags");
|
||||
|
||||
let result = execute_and_snapshot(code, UnitLength::Mm, None).await;
|
||||
assert!(result.is_err());
|
||||
let err = result.expect_err("Code should have failed due to the duplicate edges being filletted");
|
||||
|
||||
let err = err.as_kcl_error().unwrap();
|
||||
assert_eq!(
|
||||
result.err().unwrap().to_string(),
|
||||
r#"type: KclErrorDetails { source_ranges: [SourceRange([229, 272, 0])], message: "Duplicate tags are not allowed." }"#,
|
||||
err.message(),
|
||||
"The same edge ID is being referenced multiple times, which is not allowed. Please select a different edge"
|
||||
);
|
||||
assert_eq!(err.source_ranges().len(), 2);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
@ -857,7 +860,7 @@ part = rectShape([0, 0], 20, 20)
|
||||
};
|
||||
assert_eq!(
|
||||
err.error.message(),
|
||||
"This function expected this argument to be of type SketchOrSurface but it's actually of type string (text)"
|
||||
"This function expected the input argument to be of type SketchOrSurface but it's actually of type string (text)"
|
||||
);
|
||||
}
|
||||
|
||||
@ -2103,7 +2106,7 @@ async fn kcl_test_better_type_names() {
|
||||
},
|
||||
None => todo!(),
|
||||
};
|
||||
assert_eq!(err, "This function expected this argument to be of type SolidSet but it's actually of type Sketch. You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`");
|
||||
assert_eq!(err, "This function expected the input argument to be of type SolidSet but it's actually of type Sketch. You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||
};
|
||||
|
||||
const TYPES_DIR: &str = "../../docs/kcl/types";
|
||||
const LANG_TOPICS: [&str; 4] = ["Types", "Modules", "Settings", "Known Issues"];
|
||||
const LANG_TOPICS: [&str; 5] = ["Types", "Modules", "Settings", "Known Issues", "Constants"];
|
||||
// These types are declared in std.
|
||||
const DECLARED_TYPES: [&str; 7] = ["number", "string", "tag", "bool", "Sketch", "Solid", "Plane"];
|
||||
|
||||
@ -298,6 +298,7 @@ fn init_handlebars() -> Result<handlebars::Handlebars<'static>> {
|
||||
hbs.register_template_string("propertyType", include_str!("templates/propertyType.hbs"))?;
|
||||
hbs.register_template_string("schema", include_str!("templates/schema.hbs"))?;
|
||||
hbs.register_template_string("index", include_str!("templates/index.hbs"))?;
|
||||
hbs.register_template_string("consts-index", include_str!("templates/consts-index.hbs"))?;
|
||||
hbs.register_template_string("function", include_str!("templates/function.hbs"))?;
|
||||
hbs.register_template_string("const", include_str!("templates/const.hbs"))?;
|
||||
hbs.register_template_string("type", include_str!("templates/type.hbs"))?;
|
||||
@ -312,6 +313,9 @@ fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>, kcl_lib: &[Doc
|
||||
let mut functions = HashMap::new();
|
||||
functions.insert("std".to_owned(), Vec::new());
|
||||
|
||||
let mut constants = HashMap::new();
|
||||
constants.insert("std".to_owned(), Vec::new());
|
||||
|
||||
for key in combined.keys() {
|
||||
let internal_fn = combined
|
||||
.get(key)
|
||||
@ -337,6 +341,13 @@ fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>, kcl_lib: &[Doc
|
||||
DocData::Const(c) => (c.name.clone(), d.file_name()),
|
||||
DocData::Ty(t) => (t.name.clone(), d.file_name()),
|
||||
});
|
||||
|
||||
if let DocData::Const(c) = d {
|
||||
constants
|
||||
.entry(d.mod_name())
|
||||
.or_default()
|
||||
.push((c.name.clone(), d.file_name()));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO we should sub-divide into types, constants, and functions.
|
||||
@ -362,7 +373,7 @@ fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>, kcl_lib: &[Doc
|
||||
.map(|name| {
|
||||
json!({
|
||||
"name": name,
|
||||
"file_name": name.to_lowercase().replace(' ', "-"),
|
||||
"file_name": name.to_lowercase().replace(' ', "-").replace("constants", "consts"),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
@ -375,6 +386,31 @@ fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>, kcl_lib: &[Doc
|
||||
|
||||
expectorate::assert_contents("../../docs/kcl/index.md", &output);
|
||||
|
||||
// Generate the index for the constants.
|
||||
let mut sorted_consts: Vec<_> = constants
|
||||
.into_iter()
|
||||
.map(|(m, mut consts)| {
|
||||
consts.sort();
|
||||
let val = json!({
|
||||
"name": m,
|
||||
"consts": consts.into_iter().map(|(n, f)| json!({
|
||||
"name": n,
|
||||
"file_name": f,
|
||||
})).collect::<Vec<_>>(),
|
||||
});
|
||||
(m, val)
|
||||
})
|
||||
.collect();
|
||||
sorted_consts.sort_by(|t1, t2| t1.0.cmp(&t2.0));
|
||||
let data: Vec<_> = sorted_consts.into_iter().map(|(_, val)| val).collect();
|
||||
let data = json!({
|
||||
"consts": data,
|
||||
});
|
||||
|
||||
let output = hbs.render("consts-index", &data)?;
|
||||
|
||||
expectorate::assert_contents("../../docs/kcl/consts.md", &output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -405,7 +441,7 @@ fn generate_example(index: usize, src: &str, props: &ExampleProperties, file_nam
|
||||
}))
|
||||
}
|
||||
|
||||
fn generate_type_from_kcl(ty: &TyData, file_name: String) -> Result<()> {
|
||||
fn generate_type_from_kcl(ty: &TyData, file_name: String, example_name: String) -> Result<()> {
|
||||
if ty.properties.doc_hidden {
|
||||
return Ok(());
|
||||
}
|
||||
@ -416,7 +452,7 @@ fn generate_type_from_kcl(ty: &TyData, file_name: String) -> Result<()> {
|
||||
.examples
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(index, example)| generate_example(index, &example.0, &example.1, &file_name))
|
||||
.filter_map(|(index, example)| generate_example(index, &example.0, &example.1, &example_name))
|
||||
.collect();
|
||||
|
||||
let data = json!({
|
||||
@ -428,7 +464,7 @@ fn generate_type_from_kcl(ty: &TyData, file_name: String) -> Result<()> {
|
||||
});
|
||||
|
||||
let output = hbs.render("kclType", &data)?;
|
||||
expectorate::assert_contents(format!("../../docs/kcl/types/{}.md", file_name), &output);
|
||||
expectorate::assert_contents(format!("../../docs/kcl/{}.md", file_name), &output);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -480,7 +516,7 @@ fn generate_function_from_kcl(function: &FnData, file_name: String) -> Result<()
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_const_from_kcl(cnst: &ConstData, file_name: String) -> Result<()> {
|
||||
fn generate_const_from_kcl(cnst: &ConstData, file_name: String, example_name: String) -> Result<()> {
|
||||
if cnst.properties.doc_hidden {
|
||||
return Ok(());
|
||||
}
|
||||
@ -490,7 +526,7 @@ fn generate_const_from_kcl(cnst: &ConstData, file_name: String) -> Result<()> {
|
||||
.examples
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(index, example)| generate_example(index, &example.0, &example.1, &file_name))
|
||||
.filter_map(|(index, example)| generate_example(index, &example.0, &example.1, &example_name))
|
||||
.collect();
|
||||
|
||||
let data = json!({
|
||||
@ -1028,8 +1064,8 @@ fn test_generate_stdlib_markdown_docs() {
|
||||
for d in &kcl_std {
|
||||
match d {
|
||||
DocData::Fn(f) => generate_function_from_kcl(f, d.file_name()).unwrap(),
|
||||
DocData::Const(c) => generate_const_from_kcl(c, d.file_name()).unwrap(),
|
||||
DocData::Ty(t) => generate_type_from_kcl(t, d.file_name()).unwrap(),
|
||||
DocData::Const(c) => generate_const_from_kcl(c, d.file_name(), d.example_name()).unwrap(),
|
||||
DocData::Ty(t) => generate_type_from_kcl(t, d.file_name(), d.example_name()).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1061,7 +1097,8 @@ fn test_generate_stdlib_json_schema() {
|
||||
async fn test_code_in_topics() {
|
||||
let mut join_set = JoinSet::new();
|
||||
for name in LANG_TOPICS {
|
||||
let filename = format!("../../docs/kcl/{}.md", name.to_lowercase().replace(' ', "-"));
|
||||
let filename =
|
||||
format!("../../docs/kcl/{}.md", name.to_lowercase().replace(' ', "-")).replace("constants", "consts");
|
||||
let mut file = File::open(&filename).unwrap();
|
||||
let mut text = String::new();
|
||||
file.read_to_string(&mut text).unwrap();
|
||||
|
@ -116,10 +116,18 @@ impl DocData {
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn file_name(&self) -> String {
|
||||
match self {
|
||||
DocData::Fn(f) => f.qual_name.replace("::", "-"),
|
||||
DocData::Const(c) => format!("consts/{}", c.qual_name.replace("::", "-")),
|
||||
DocData::Ty(t) => format!("types/{}", t.name.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn example_name(&self) -> String {
|
||||
match self {
|
||||
DocData::Fn(f) => f.qual_name.replace("::", "-"),
|
||||
DocData::Const(c) => format!("const_{}", c.qual_name.replace("::", "-")),
|
||||
// TODO might want to change this
|
||||
DocData::Ty(t) => t.name.clone(),
|
||||
}
|
||||
}
|
||||
@ -872,7 +880,7 @@ mod test {
|
||||
Ok(img) => img,
|
||||
};
|
||||
twenty_twenty::assert_image(
|
||||
format!("tests/outputs/serial_test_example_{}{i}.png", d.file_name()),
|
||||
format!("tests/outputs/serial_test_example_{}{i}.png", d.example_name()),
|
||||
&result,
|
||||
0.99,
|
||||
);
|
||||
|
@ -133,6 +133,7 @@ impl StdLibFnArg {
|
||||
|| self.type_ == "SolidSet"
|
||||
|| self.type_ == "SketchSurface"
|
||||
|| self.type_ == "SketchOrSurface"
|
||||
|| self.type_ == "SolidOrImportedGeometry"
|
||||
{
|
||||
return Ok(Some((index, format!("{label}${{{}:{}}}", index, "%"))));
|
||||
} else if (self.type_ == "TagDeclarator" || self.type_ == "TagNode") && self.required {
|
||||
|
17
rust/kcl-lib/src/docs/templates/consts-index.hbs
vendored
Normal file
17
rust/kcl-lib/src/docs/templates/consts-index.hbs
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
title: "KCL Constants"
|
||||
excerpt: "Documentation for the KCL constants."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
{{#each consts}}
|
||||
|
||||
### `{{name}}`
|
||||
|
||||
{{#each consts}}
|
||||
- [`{{name}}`](/docs/kcl/{{file_name}})
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
|
@ -228,6 +228,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
cmd: &ModelingCmd,
|
||||
) -> Result<(), crate::errors::KclError> {
|
||||
// In isolated mode, we don't send the command to the engine.
|
||||
//
|
||||
// Note: It's important to allow commands through for the mock engine
|
||||
// because it needs the commands to build the artifact graph in sketch
|
||||
// mode.
|
||||
if self.execution_kind().await.is_isolated() {
|
||||
return Ok(());
|
||||
}
|
||||
@ -253,6 +257,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
cmd: &ModelingCmd,
|
||||
) -> Result<(), crate::errors::KclError> {
|
||||
// In isolated mode, we don't send the command to the engine.
|
||||
//
|
||||
// Note: It's important to allow commands through for the mock engine
|
||||
// because it needs the commands to build the artifact graph in sketch
|
||||
// mode.
|
||||
if self.execution_kind().await.is_isolated() {
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -48,6 +48,15 @@ impl ExecErrorWithState {
|
||||
}
|
||||
}
|
||||
|
||||
impl ExecError {
|
||||
pub fn as_kcl_error(&self) -> Option<&crate::KclError> {
|
||||
let ExecError::Kcl(k) = &self else {
|
||||
return None;
|
||||
};
|
||||
Some(&k.error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ExecError> for ExecErrorWithState {
|
||||
fn from(error: ExecError) -> Self {
|
||||
Self {
|
||||
@ -169,13 +178,8 @@ impl KclErrorWithOutputs {
|
||||
path: self
|
||||
.filenames
|
||||
.get(&first_source_range.module_id())
|
||||
.ok_or_else(|| {
|
||||
anyhow::anyhow!(
|
||||
"Could not find filename for module id: {:?}",
|
||||
first_source_range.module_id()
|
||||
)
|
||||
})?
|
||||
.clone(),
|
||||
.cloned()
|
||||
.unwrap_or(ModulePath::Main),
|
||||
});
|
||||
let filename = source.path.to_string();
|
||||
let kcl_source = source.source.to_string();
|
||||
@ -183,11 +187,10 @@ impl KclErrorWithOutputs {
|
||||
let mut related = Vec::new();
|
||||
for source_range in source_ranges {
|
||||
let module_id = source_range.module_id();
|
||||
let source = self
|
||||
.source_files
|
||||
.get(&module_id)
|
||||
.cloned()
|
||||
.ok_or_else(|| anyhow::anyhow!("Could not find source file for module id: {:?}", module_id))?;
|
||||
let source = self.source_files.get(&module_id).cloned().unwrap_or(ModuleSource {
|
||||
source: code.to_string(),
|
||||
path: self.filenames.get(&module_id).cloned().unwrap_or(ModulePath::Main),
|
||||
});
|
||||
let error = self.error.override_source_ranges(vec![source_range]);
|
||||
let report = Report {
|
||||
error,
|
||||
|
@ -488,6 +488,11 @@ impl ArtifactGraph {
|
||||
pub fn len(&self) -> usize {
|
||||
self.map.len()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn iter(&self) -> impl Iterator<Item = (&ArtifactId, &Artifact)> {
|
||||
self.map.iter()
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn build_artifact_graph(
|
||||
@ -622,10 +627,7 @@ fn artifacts_to_update(
|
||||
let uuid = artifact_command.cmd_id;
|
||||
let id = ArtifactId::new(uuid);
|
||||
|
||||
let Some(response) = responses.get(&uuid) else {
|
||||
// Response not found or not successful.
|
||||
return Ok(Vec::new());
|
||||
};
|
||||
let response = responses.get(&uuid);
|
||||
|
||||
let cmd = &artifact_command.command;
|
||||
|
||||
@ -757,7 +759,7 @@ fn artifacts_to_update(
|
||||
new_path.seg_ids = vec![id];
|
||||
return_arr.push(Artifact::Path(new_path));
|
||||
}
|
||||
if let OkModelingCmdResponse::ClosePath(close_path) = response {
|
||||
if let Some(OkModelingCmdResponse::ClosePath(close_path)) = response {
|
||||
return_arr.push(Artifact::Solid2d(Solid2d {
|
||||
id: close_path.face_id.into(),
|
||||
path_id,
|
||||
@ -800,7 +802,7 @@ fn artifacts_to_update(
|
||||
return Ok(return_arr);
|
||||
}
|
||||
ModelingCmd::Loft(loft_cmd) => {
|
||||
let OkModelingCmdResponse::Loft(_) = response else {
|
||||
let Some(OkModelingCmdResponse::Loft(_)) = response else {
|
||||
return Ok(Vec::new());
|
||||
};
|
||||
let mut return_arr = Vec::new();
|
||||
@ -830,7 +832,7 @@ fn artifacts_to_update(
|
||||
return Ok(return_arr);
|
||||
}
|
||||
ModelingCmd::Solid3dGetExtrusionFaceInfo(_) => {
|
||||
let OkModelingCmdResponse::Solid3dGetExtrusionFaceInfo(face_info) = response else {
|
||||
let Some(OkModelingCmdResponse::Solid3dGetExtrusionFaceInfo(face_info)) = response else {
|
||||
return Ok(Vec::new());
|
||||
};
|
||||
let mut return_arr = Vec::new();
|
||||
@ -954,6 +956,11 @@ fn artifacts_to_update(
|
||||
ModelingCmd::Solid3dGetOppositeEdge(_) => SweepEdgeSubType::Opposite,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
// We need a response to continue. If we're in sketch mode doing
|
||||
// mock execution, we won't have one.
|
||||
if response.is_none() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let face_id = ArtifactId::new(*face_id);
|
||||
let edge_id = ArtifactId::new(*edge_id);
|
||||
let Some(Artifact::Wall(wall)) = artifacts.get(&face_id) else {
|
||||
@ -969,7 +976,7 @@ fn artifacts_to_update(
|
||||
return Ok(Vec::new());
|
||||
};
|
||||
let response_edge_id = match response {
|
||||
OkModelingCmdResponse::Solid3dGetNextAdjacentEdge(r) => {
|
||||
Some(OkModelingCmdResponse::Solid3dGetNextAdjacentEdge(r)) => {
|
||||
let Some(edge_id) = r.edge else {
|
||||
return Err(KclError::Internal(KclErrorDetails {
|
||||
message:format!(
|
||||
@ -980,7 +987,7 @@ fn artifacts_to_update(
|
||||
};
|
||||
edge_id.into()
|
||||
}
|
||||
OkModelingCmdResponse::Solid3dGetOppositeEdge(r) => r.edge.into(),
|
||||
Some(OkModelingCmdResponse::Solid3dGetOppositeEdge(r)) => r.edge.into(),
|
||||
_ => {
|
||||
return Err(KclError::Internal(KclErrorDetails {
|
||||
message:format!(
|
||||
|
@ -5,6 +5,7 @@ use std::sync::Arc;
|
||||
use itertools::{EitherOrBoth, Itertools};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use super::IdGenerator;
|
||||
use crate::{
|
||||
execution::{annotations, memory::Stack, EnvironmentRef, ExecState, ExecutorSettings},
|
||||
parsing::ast::types::{Annotation, Node, Program},
|
||||
@ -14,8 +15,10 @@ use crate::{
|
||||
lazy_static::lazy_static! {
|
||||
/// A static mutable lock for updating the last successful execution state for the cache.
|
||||
static ref OLD_AST: Arc<RwLock<Option<OldAstState>>> = Default::default();
|
||||
// The last successful run's memory. Not cleared after an unssuccessful run.
|
||||
// The last successful run's memory. Not cleared after an unsuccessful run.
|
||||
static ref PREV_MEMORY: Arc<RwLock<Option<Stack>>> = Default::default();
|
||||
/// The ID generator for mock execution.
|
||||
static ref MOCK_ID_GENERATOR: Arc<RwLock<Option<IdGenerator>>> = Default::default();
|
||||
}
|
||||
|
||||
/// Read the old ast memory from the lock.
|
||||
@ -49,6 +52,21 @@ pub async fn clear_mem_cache() {
|
||||
*old_mem = None;
|
||||
}
|
||||
|
||||
pub(crate) async fn read_mock_ids() -> Option<IdGenerator> {
|
||||
let cache = MOCK_ID_GENERATOR.read().await;
|
||||
cache.clone()
|
||||
}
|
||||
|
||||
pub(super) async fn write_mock_ids(id_gen: IdGenerator) {
|
||||
let mut cache = MOCK_ID_GENERATOR.write().await;
|
||||
*cache = Some(id_gen);
|
||||
}
|
||||
|
||||
pub async fn clear_mock_ids() {
|
||||
let mut cache = MOCK_ID_GENERATOR.write().await;
|
||||
*cache = None;
|
||||
}
|
||||
|
||||
/// Information for the caching an AST and smartly re-executing it if we can.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CacheInformation<'a> {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user