Compare commits
41 Commits
lf94/mac-m
...
kcl-51
Author | SHA1 | Date | |
---|---|---|---|
e7d00f148b | |||
d19a7df7e8 | |||
45fae52afc | |||
270f173aad | |||
ddcff1ba63 | |||
cb1b08d6b6 | |||
533fa749b2 | |||
af492d2cb6 | |||
26fba71abf | |||
859bfc7b28 | |||
3b1d1307c4 | |||
f5a2c84ce2 | |||
cccb71fd30 | |||
44be072d04 | |||
86beb6ebf1 | |||
6d72104faa | |||
f2c5661710 | |||
ecb2359bc5 | |||
6e5058bbdc | |||
988a068d6d | |||
0688ce7fe9 | |||
f9e09893e7 | |||
dd1534a61d | |||
e17c6e272c | |||
cb0470a31d | |||
ff6186f4f0 | |||
4dd669bd46 | |||
09131722e3 | |||
87ab8fe78d | |||
bc928a34ef | |||
dca78acdf2 | |||
40f4450995 | |||
178d943423 | |||
e78788482e | |||
e50e9a00d4 | |||
dc82b4c8ea | |||
a8b0e1a771 | |||
75a975b1e1 | |||
3f02bb2065 | |||
9c986d3aa8 | |||
4741d9592b |
@ -22,6 +22,13 @@
|
|||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/no-floating-promises": "error",
|
"@typescript-eslint/no-floating-promises": "error",
|
||||||
"@typescript-eslint/no-misused-promises": "error",
|
"@typescript-eslint/no-misused-promises": "error",
|
||||||
|
"@typescript-eslint/no-unused-vars": ["error", {
|
||||||
|
"varsIgnorePattern": "^_",
|
||||||
|
"argsIgnorePattern": "^_",
|
||||||
|
"ignoreRestSiblings": true,
|
||||||
|
"vars": "all",
|
||||||
|
"args": "none"
|
||||||
|
}],
|
||||||
"jsx-a11y/click-events-have-key-events": "off",
|
"jsx-a11y/click-events-have-key-events": "off",
|
||||||
"jsx-a11y/no-autofocus": "off",
|
"jsx-a11y/no-autofocus": "off",
|
||||||
"jsx-a11y/no-noninteractive-element-interactions": "off",
|
"jsx-a11y/no-noninteractive-element-interactions": "off",
|
||||||
|
66
.github/workflows/e2e-tests.yml
vendored
@ -75,7 +75,7 @@ jobs:
|
|||||||
|
|
||||||
prepare-wasm:
|
prepare-wasm:
|
||||||
# seperate job on Ubuntu to build or fetch the wasm blob once on the fastest runner
|
# seperate job on Ubuntu to build or fetch the wasm blob once on the fastest runner
|
||||||
runs-on: namespace-profile-ubuntu-8-cores
|
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||||
needs: conditions
|
needs: conditions
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -163,7 +163,7 @@ jobs:
|
|||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
name: playwright:snapshots:ubuntu
|
name: playwright:snapshots:ubuntu
|
||||||
runs-on: namespace-profile-ubuntu-8-cores
|
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||||
needs: [conditions, prepare-wasm]
|
needs: [conditions, prepare-wasm]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/create-github-app-token@v1
|
- uses: actions/create-github-app-token@v1
|
||||||
@ -220,8 +220,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Run ubuntu/chrome snapshots
|
- name: Run ubuntu/chrome snapshots
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
if: needs.conditions.outputs.should-run == 'true'
|
||||||
run: |
|
uses: nick-fields/retry@v3.0.2
|
||||||
yarn test:snapshots
|
with:
|
||||||
|
shell: bash
|
||||||
|
command: yarn test:snapshots
|
||||||
|
timeout_minutes: 30
|
||||||
|
max_attempts: 3
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
NODE_ENV: development
|
NODE_ENV: development
|
||||||
@ -233,19 +237,14 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
||||||
with:
|
with:
|
||||||
name: playwright-report-snapshots-${{ matrix.os }}-snapshot-${{ matrix.shardIndex }}-${{ github.sha }}
|
name: playwright-report-ubuntu-snapshot-${{ github.sha }}
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
include-hidden-files: true
|
include-hidden-files: true
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
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
|
- 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' }}
|
if: ${{ needs.conditions.outputs.should-run == 'true' && github.ref != 'refs/heads/main' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
id: git-check
|
id: git-check
|
||||||
run: |
|
run: |
|
||||||
@ -266,31 +265,36 @@ jobs:
|
|||||||
git fetch origin
|
git fetch origin
|
||||||
echo ${{ github.head_ref }}
|
echo ${{ github.head_ref }}
|
||||||
git checkout ${{ github.head_ref }}
|
git checkout ${{ github.head_ref }}
|
||||||
git commit -m "A snapshot a day keeps the bugs away! 📷🐛 (OS: ${{matrix.os}})" || true
|
git commit -m "A snapshot a day keeps the bugs away! 📷🐛" || true
|
||||||
git push
|
git push
|
||||||
git push origin ${{ github.head_ref }}
|
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:
|
electron:
|
||||||
needs: [conditions, prepare-wasm]
|
needs: [conditions, prepare-wasm]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
name: playwright:electron:${{ matrix.os }} ${{ matrix.shardIndex }} ${{ matrix.shardTotal }}
|
env:
|
||||||
|
OS_NAME: ${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}
|
||||||
|
name: playwright:electron:${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}:${{ matrix.shardIndex }}:${{ matrix.shardTotal }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
# TODO: enable self-hosted-windows-8-cores once available
|
# TODO: enable namespace-profile-windows-latest once available
|
||||||
os: [namespace-profile-ubuntu-8-cores, namespace-profile-macos-8-cores, windows-16-cores]
|
os:
|
||||||
|
- "runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64"
|
||||||
|
- namespace-profile-macos-8-cores
|
||||||
|
- windows-latest
|
||||||
shardIndex: [1, 2, 3, 4]
|
shardIndex: [1, 2, 3, 4]
|
||||||
shardTotal: [4]
|
shardTotal: [4]
|
||||||
|
# Disable macos and windows tests on hourly e2e tests since we only care
|
||||||
|
# about server side changes.
|
||||||
|
# Technique from https://github.com/joaomcteixeira/python-project-skeleton/pull/31/files
|
||||||
|
isScheduled:
|
||||||
|
- ${{ github.event_name == 'schedule' }}
|
||||||
|
exclude:
|
||||||
|
- os: namespace-profile-macos-8-cores
|
||||||
|
isScheduled: true
|
||||||
|
- os: windows-latest
|
||||||
|
isScheduled: true
|
||||||
# TODO: add ref here for main and latest release tag
|
# TODO: add ref here for main and latest release tag
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
@ -347,7 +351,7 @@ jobs:
|
|||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
name: test-results-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
name: test-results-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||||
path: test-results/
|
path: test-results/
|
||||||
|
|
||||||
- name: Run playwright/electron flow (with retries)
|
- name: Run playwright/electron flow (with retries)
|
||||||
@ -356,9 +360,9 @@ jobs:
|
|||||||
uses: nick-fields/retry@v3.0.2
|
uses: nick-fields/retry@v3.0.2
|
||||||
with:
|
with:
|
||||||
shell: bash
|
shell: bash
|
||||||
command: .github/ci-cd-scripts/playwright-electron.sh ${{matrix.shardIndex}} ${{matrix.shardTotal}} ${{matrix.os}}
|
command: .github/ci-cd-scripts/playwright-electron.sh ${{matrix.shardIndex}} ${{matrix.shardTotal}} ${{ env.OS_NAME }}
|
||||||
timeout_minutes: 30
|
timeout_minutes: 45
|
||||||
max_attempts: 25
|
max_attempts: 15
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
FAIL_ON_CONSOLE_ERRORS: true
|
FAIL_ON_CONSOLE_ERRORS: true
|
||||||
@ -370,7 +374,7 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && always() }}
|
if: ${{ needs.conditions.outputs.should-run == 'true' && always() }}
|
||||||
with:
|
with:
|
||||||
name: test-results-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
name: test-results-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||||
path: test-results/
|
path: test-results/
|
||||||
include-hidden-files: true
|
include-hidden-files: true
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
@ -379,7 +383,7 @@ jobs:
|
|||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && always() }}
|
if: ${{ needs.conditions.outputs.should-run == 'true' && always() }}
|
||||||
with:
|
with:
|
||||||
name: playwright-report-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
name: playwright-report-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
include-hidden-files: true
|
include-hidden-files: true
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
2
Makefile
@ -4,7 +4,7 @@ KCL_WASM_LIB_FILES := $(wildcard rust/**/*.rs)
|
|||||||
TS_SRC := $(wildcard src/**/*.tsx) $(wildcard src/**/*.ts)
|
TS_SRC := $(wildcard src/**/*.tsx) $(wildcard src/**/*.ts)
|
||||||
XSTATE_TYPEGENS := $(wildcard src/machines/*.typegen.ts)
|
XSTATE_TYPEGENS := $(wildcard src/machines/*.typegen.ts)
|
||||||
|
|
||||||
dev: node_modules public/wasm_lib_bg.wasm $(XSTATE_TYPEGENS)
|
dev: node_modules public/kcl_wasm_lib_bg.wasm $(XSTATE_TYPEGENS)
|
||||||
yarn start
|
yarn start
|
||||||
|
|
||||||
# I'm sorry this is so specific to my setup you may as well ignore this.
|
# I'm sorry this is so specific to my setup you may as well ignore this.
|
||||||
|
10
README.md
@ -105,7 +105,7 @@ Finally, to run the web app only, run:
|
|||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're not a Zoo employee you won't be able to access the dev environment, you should copy everything from `.env.production` to `.env.development` to make it point to production instead, then when you navigate to `localhost:3000` the easiest way to sign in is to paste `localStorage.setItem('TOKEN_PERSIST_KEY', "your-token-from-https://zoo.dev/account/api-tokens")` replacing the with a real token from https://zoo.dev/account/api-tokens of course, then navigate to localhost:3000 again. Note that navigating to `localhost:3000/signin` removes your token so you will need to set the token again.
|
If you're not a Zoo employee you won't be able to access the dev environment, you should copy everything from `.env.production` to `.env.development.local` to make it point to production instead, then when you navigate to `localhost:3000` the easiest way to sign in is to paste `localStorage.setItem('TOKEN_PERSIST_KEY', "your-token-from-https://zoo.dev/account/api-tokens")` replacing the with a real token from https://zoo.dev/account/api-tokens of course, then navigate to `localhost:3000` again. Note that navigating to `localhost:3000/signin` removes your token so you will need to set the token again.
|
||||||
|
|
||||||
### Development environment variables
|
### Development environment variables
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ Third-Party Cookies".
|
|||||||
|
|
||||||
## Desktop
|
## Desktop
|
||||||
|
|
||||||
To spin up the desktop app, `yarn install` and `yarn build:wasm` need to have been done before hand then
|
To spin up the desktop app, `yarn install` and `yarn build:wasm` need to have been done before hand then:
|
||||||
|
|
||||||
```
|
```
|
||||||
yarn tron:start
|
yarn tron:start
|
||||||
@ -130,13 +130,13 @@ yarn tron:start
|
|||||||
|
|
||||||
This will start the application and hot-reload on changes.
|
This will start the application and hot-reload on changes.
|
||||||
|
|
||||||
Devtools can be opened with the usual Cmd-Opt-I (Mac) or Ctrl-Shift-I (Linux and Windows).
|
Devtools can be opened with the usual Command-Option-I (macOS) or Ctrl-Shift-I (Linux and Windows).
|
||||||
|
|
||||||
To package the app for your platform with electron-builder, run `yarn tronb:package:dev` (or `yarn tronb:package:prod` to point to the .env.production variables)
|
To package the app for your platform with electron-builder, run `yarn tronb:package:dev` (or `yarn tronb:package:prod` to point to the .env.production variables).
|
||||||
|
|
||||||
## Checking out commits / Bisecting
|
## Checking out commits / Bisecting
|
||||||
|
|
||||||
Which commands from setup are one off vs need to be run every time?
|
Which commands from setup are one off vs. need to be run every time?
|
||||||
|
|
||||||
The following will need to be run when checking out a new commit and guarantees the build is not stale:
|
The following will need to be run when checking out a new commit and guarantees the build is not stale:
|
||||||
|
|
||||||
|
@ -10,11 +10,11 @@ This will work on any solid, including extruded solids, revolved solids, and she
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
appearance(
|
appearance(
|
||||||
solidSet: SolidSet,
|
solids: [Solid],
|
||||||
color: String,
|
color: String,
|
||||||
metalness?: number,
|
metalness?: number,
|
||||||
roughness?: number,
|
roughness?: number,
|
||||||
): SolidSet
|
): [Solid]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -22,14 +22,14 @@ appearance(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solidSet` | [`SolidSet`](/docs/kcl/types/SolidSet) | The solid(s) whose appearance is being set | Yes |
|
| `solids` | [`[Solid]`](/docs/kcl/types/Solid) | The solid(s) whose appearance is being set | Yes |
|
||||||
| `color` | `String` | Color of the new material, a hex string like '#ff0000' | Yes |
|
| `color` | `String` | Color of the new material, a hex string like '#ff0000' | Yes |
|
||||||
| `metalness` | [`number`](/docs/kcl/types/number) | Metalness of the new material, a percentage like 95.7. | No |
|
| `metalness` | [`number`](/docs/kcl/types/number) | Metalness of the new material, a percentage like 95.7. | No |
|
||||||
| `roughness` | [`number`](/docs/kcl/types/number) | Roughness of the new material, a percentage like 95.7. | No |
|
| `roughness` | [`number`](/docs/kcl/types/number) | Roughness of the new material, a percentage like 95.7. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`SolidSet`](/docs/kcl/types/SolidSet) - A solid or a group of solids.
|
[`[Solid]`](/docs/kcl/types/Solid)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
@ -54,7 +54,7 @@ example = extrude(exampleSketch, length = 5)
|
|||||||
// Add color to a revolved solid.
|
// Add color to a revolved solid.
|
||||||
sketch001 = startSketchOn('XY')
|
sketch001 = startSketchOn('XY')
|
||||||
|> circle(center = [15, 0], radius = 5)
|
|> circle(center = [15, 0], radius = 5)
|
||||||
|> revolve({ angle = 360, axis = 'y' }, %)
|
|> revolve(angle = 360, axis = 'y')
|
||||||
|> appearance(color = '#ff0000', metalness = 90, roughness = 90)
|
|> appearance(color = '#ff0000', metalness = 90, roughness = 90)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -10,9 +10,11 @@ You can provide more than one sketch to extrude, and they will all be extruded i
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
extrude(
|
extrude(
|
||||||
sketchSet: SketchSet,
|
sketches: [Sketch],
|
||||||
length: number,
|
length: number,
|
||||||
): SolidSet
|
tagStart?: TagDeclarator,
|
||||||
|
tagEnd?: TagDeclarator,
|
||||||
|
): [Solid]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -20,12 +22,14 @@ extrude(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | Which sketch or set of sketches should be extruded | Yes |
|
| `sketches` | [`[Sketch]`](/docs/kcl/types/Sketch) | Which sketch or sketches should be extruded | Yes |
|
||||||
| `length` | [`number`](/docs/kcl/types/number) | How far to extrude the given sketches | Yes |
|
| `length` | [`number`](/docs/kcl/types/number) | How far to extrude the given sketches | Yes |
|
||||||
|
| `tagStart` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | A named tag for the face at the start of the extrusion, i.e. the original sketch | No |
|
||||||
|
| `tagEnd` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | A named tag for the face at the end of the extrusion, i.e. the new face created by extruding the original sketch | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`SolidSet`](/docs/kcl/types/SolidSet) - A solid or a group of solids.
|
[`[Solid]`](/docs/kcl/types/Solid)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -10,7 +10,7 @@ Use a 2-dimensional sketch to cut a hole in another 2-dimensional sketch.
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
hole(
|
hole(
|
||||||
holeSketch: SketchSet,
|
holeSketch: [Sketch],
|
||||||
sketch: Sketch,
|
sketch: Sketch,
|
||||||
): Sketch
|
): Sketch
|
||||||
```
|
```
|
||||||
@ -20,7 +20,7 @@ hole(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `holeSketch` | [`SketchSet`](/docs/kcl/types/SketchSet) | A sketch or a group of sketches. | Yes |
|
| `holeSketch` | [`[Sketch]`](/docs/kcl/types/Sketch) | | Yes |
|
||||||
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | | Yes |
|
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
@ -15,6 +15,8 @@ loft(
|
|||||||
bezApproximateRational: bool,
|
bezApproximateRational: bool,
|
||||||
baseCurveIndex?: integer,
|
baseCurveIndex?: integer,
|
||||||
tolerance?: number,
|
tolerance?: number,
|
||||||
|
tagStart?: TagDeclarator,
|
||||||
|
tagEnd?: TagDeclarator,
|
||||||
): Solid
|
): Solid
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -28,6 +30,8 @@ loft(
|
|||||||
| `bezApproximateRational` | [`bool`](/docs/kcl/types/bool) | Attempt to approximate rational curves (such as arcs) using a bezier. This will remove banding around interpolations between arcs and non-arcs. It may produce errors in other scenarios Over time, this field won't be necessary. | Yes |
|
| `bezApproximateRational` | [`bool`](/docs/kcl/types/bool) | Attempt to approximate rational curves (such as arcs) using a bezier. This will remove banding around interpolations between arcs and non-arcs. It may produce errors in other scenarios Over time, this field won't be necessary. | Yes |
|
||||||
| `baseCurveIndex` | `integer` | This can be set to override the automatically determined topological base curve, which is usually the first section encountered. | No |
|
| `baseCurveIndex` | `integer` | This can be set to override the automatically determined topological base curve, which is usually the first section encountered. | No |
|
||||||
| `tolerance` | [`number`](/docs/kcl/types/number) | Tolerance for the loft operation. | No |
|
| `tolerance` | [`number`](/docs/kcl/types/number) | Tolerance for the loft operation. | No |
|
||||||
|
| `tagStart` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | A named tag for the face at the start of the loft, i.e. the original sketch | No |
|
||||||
|
| `tagEnd` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | A named tag for the face at the end of the loft, i.e. the last sketch | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ Mirror occurs around a local sketch axis rather than a global axis.
|
|||||||
```js
|
```js
|
||||||
mirror2d(
|
mirror2d(
|
||||||
data: Mirror2dData,
|
data: Mirror2dData,
|
||||||
sketchSet: SketchSet,
|
sketches: [Sketch],
|
||||||
): [Sketch]
|
): [Sketch]
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ mirror2d(
|
|||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `data` | [`Mirror2dData`](/docs/kcl/types/Mirror2dData) | Data for a mirror. | Yes |
|
| `data` | [`Mirror2dData`](/docs/kcl/types/Mirror2dData) | Data for a mirror. | Yes |
|
||||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | A sketch or a group of sketches. | Yes |
|
| `sketches` | [`[Sketch]`](/docs/kcl/types/Sketch) | | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ Repeat a 2-dimensional sketch some number of times along a partial or complete c
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternCircular2d(
|
patternCircular2d(
|
||||||
sketchSet: SketchSet,
|
sketchSet: [Sketch],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
center: [number],
|
center: [number],
|
||||||
arcDegrees: number,
|
arcDegrees: number,
|
||||||
@ -24,7 +24,7 @@ patternCircular2d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | Which sketch(es) to pattern | Yes |
|
| `sketchSet` | [`[Sketch]`](/docs/kcl/types/Sketch) | Which sketch(es) to pattern | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `center` | [`[number]`](/docs/kcl/types/number) | The center about which to make the pattern. This is a 2D vector. | Yes |
|
| `center` | [`[number]`](/docs/kcl/types/number) | The center about which to make the pattern. This is a 2D vector. | Yes |
|
||||||
| `arcDegrees` | [`number`](/docs/kcl/types/number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. | Yes |
|
| `arcDegrees` | [`number`](/docs/kcl/types/number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. | Yes |
|
||||||
|
@ -10,7 +10,7 @@ Repeat a 3-dimensional solid some number of times along a partial or complete ci
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternCircular3d(
|
patternCircular3d(
|
||||||
solidSet: SolidSet,
|
solids: [Solid],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
axis: [number],
|
axis: [number],
|
||||||
center: [number],
|
center: [number],
|
||||||
@ -25,7 +25,7 @@ patternCircular3d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solidSet` | [`SolidSet`](/docs/kcl/types/SolidSet) | Which solid(s) to pattern | Yes |
|
| `solids` | [`[Solid]`](/docs/kcl/types/Solid) | Which solid(s) to pattern | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis around which to make the pattern. This is a 3D vector | Yes |
|
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis around which to make the pattern. This is a 3D vector | Yes |
|
||||||
| `center` | [`[number]`](/docs/kcl/types/number) | The center about which to make the pattern. This is a 3D vector. | Yes |
|
| `center` | [`[number]`](/docs/kcl/types/number) | The center about which to make the pattern. This is a 3D vector. | Yes |
|
||||||
|
@ -10,7 +10,7 @@ Repeat a 2-dimensional sketch along some dimension, with a dynamic amount of dis
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternLinear2d(
|
patternLinear2d(
|
||||||
sketchSet: SketchSet,
|
sketches: [Sketch],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
distance: number,
|
distance: number,
|
||||||
axis: [number],
|
axis: [number],
|
||||||
@ -23,7 +23,7 @@ patternLinear2d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | The sketch(es) to duplicate | Yes |
|
| `sketches` | [`[Sketch]`](/docs/kcl/types/Sketch) | The sketch(es) to duplicate | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `distance` | [`number`](/docs/kcl/types/number) | Distance between each repetition. Also known as 'spacing'. | Yes |
|
| `distance` | [`number`](/docs/kcl/types/number) | Distance between each repetition. Also known as 'spacing'. | Yes |
|
||||||
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis of the pattern. A 2D vector. | Yes |
|
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis of the pattern. A 2D vector. | Yes |
|
||||||
|
@ -10,7 +10,7 @@ Repeat a 3-dimensional solid along a linear path, with a dynamic amount of dista
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternLinear3d(
|
patternLinear3d(
|
||||||
solidSet: SolidSet,
|
solids: [Solid],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
distance: number,
|
distance: number,
|
||||||
axis: [number],
|
axis: [number],
|
||||||
@ -23,7 +23,7 @@ patternLinear3d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solidSet` | [`SolidSet`](/docs/kcl/types/SolidSet) | The solid(s) to duplicate | Yes |
|
| `solids` | [`[Solid]`](/docs/kcl/types/Solid) | The solid(s) to duplicate | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `distance` | [`number`](/docs/kcl/types/number) | Distance between each repetition. Also known as 'spacing'. | Yes |
|
| `distance` | [`number`](/docs/kcl/types/number) | Distance between each repetition. Also known as 'spacing'. | Yes |
|
||||||
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis of the pattern. A 2D vector. | Yes |
|
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis of the pattern. A 2D vector. | Yes |
|
||||||
|
@ -36,7 +36,7 @@ The transform function returns a transform object. All properties of the object
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternTransform(
|
patternTransform(
|
||||||
solidSet: SolidSet,
|
solids: [Solid],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
transform: FunctionSource,
|
transform: FunctionSource,
|
||||||
useOriginal?: bool,
|
useOriginal?: bool,
|
||||||
@ -48,7 +48,7 @@ patternTransform(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solidSet` | [`SolidSet`](/docs/kcl/types/SolidSet) | The solid(s) to duplicate | Yes |
|
| `solids` | [`[Solid]`](/docs/kcl/types/Solid) | The solid(s) to duplicate | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `transform` | `FunctionSource` | How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples. | Yes |
|
| `transform` | `FunctionSource` | How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples. | Yes |
|
||||||
| `useOriginal` | [`bool`](/docs/kcl/types/bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. | No |
|
| `useOriginal` | [`bool`](/docs/kcl/types/bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. | No |
|
||||||
|
@ -10,7 +10,7 @@ Just like patternTransform, but works on 2D sketches not 3D solids.
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternTransform2d(
|
patternTransform2d(
|
||||||
sketchSet: SketchSet,
|
sketches: [Sketch],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
transform: FunctionSource,
|
transform: FunctionSource,
|
||||||
useOriginal?: bool,
|
useOriginal?: bool,
|
||||||
@ -22,7 +22,7 @@ patternTransform2d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | The sketch(es) to duplicate | Yes |
|
| `sketches` | [`[Sketch]`](/docs/kcl/types/Sketch) | The sketch(es) to duplicate | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `transform` | `FunctionSource` | How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples. | Yes |
|
| `transform` | `FunctionSource` | How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples. | Yes |
|
||||||
| `useOriginal` | [`bool`](/docs/kcl/types/bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. | No |
|
| `useOriginal` | [`bool`](/docs/kcl/types/bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. | No |
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
title: "scale"
|
title: "scale"
|
||||||
excerpt: "Scale a solid."
|
excerpt: "Scale a solid or a sketch."
|
||||||
layout: manual
|
layout: manual
|
||||||
---
|
---
|
||||||
|
|
||||||
Scale a solid.
|
Scale a solid or a sketch.
|
||||||
|
|
||||||
By default the transform is applied in local sketch axis, therefore the origin will not move.
|
By default the transform is applied in local sketch axis, therefore the origin will not move.
|
||||||
|
|
||||||
@ -12,10 +12,10 @@ If you want to apply the transform in global space, set `global` to `true`. The
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
scale(
|
scale(
|
||||||
solidSet: SolidOrImportedGeometry,
|
objects: SolidOrSketchOrImportedGeometry,
|
||||||
scale: [number],
|
scale: [number],
|
||||||
global?: bool,
|
global?: bool,
|
||||||
): SolidOrImportedGeometry
|
): SolidOrSketchOrImportedGeometry
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -23,13 +23,13 @@ scale(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solidSet` | [`SolidOrImportedGeometry`](/docs/kcl/types/SolidOrImportedGeometry) | The solid or set of solids to scale. | Yes |
|
| `objects` | [`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) | The solid, sketch, or set of solids or sketches to scale. | Yes |
|
||||||
| `scale` | [`[number]`](/docs/kcl/types/number) | The scale factor for the x, y, and z axes. | Yes |
|
| `scale` | [`[number]`](/docs/kcl/types/number) | The scale factor for the x, y, and z axes. | Yes |
|
||||||
| `global` | [`bool`](/docs/kcl/types/bool) | If true, the transform is applied in global space. The origin of the model will move. By default, the transform is applied in local sketch axis, therefore the origin will not move. | No |
|
| `global` | [`bool`](/docs/kcl/types/bool) | If true, the transform is applied in global space. The origin of the model will move. By default, the transform is applied in local sketch axis, therefore the origin will not move. | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`SolidOrImportedGeometry`](/docs/kcl/types/SolidOrImportedGeometry) - Data for a solid or an imported geometry.
|
[`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) - Data for a solid or an imported geometry.
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -10,10 +10,10 @@ Remove volume from a 3-dimensional shape such that a wall of the provided thickn
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
shell(
|
shell(
|
||||||
solidSet: SolidSet,
|
solids: [Solid],
|
||||||
thickness: number,
|
thickness: number,
|
||||||
faces: [FaceTag],
|
faces: [FaceTag],
|
||||||
): SolidSet
|
): [Solid]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -21,13 +21,13 @@ shell(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solidSet` | [`SolidSet`](/docs/kcl/types/SolidSet) | Which solid (or solids) to shell out | Yes |
|
| `solids` | [`[Solid]`](/docs/kcl/types/Solid) | Which solid (or solids) to shell out | Yes |
|
||||||
| `thickness` | [`number`](/docs/kcl/types/number) | The thickness of the shell | Yes |
|
| `thickness` | [`number`](/docs/kcl/types/number) | The thickness of the shell | Yes |
|
||||||
| `faces` | [`[FaceTag]`](/docs/kcl/types/FaceTag) | The faces you want removed | Yes |
|
| `faces` | [`[FaceTag]`](/docs/kcl/types/FaceTag) | The faces you want removed | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`SolidSet`](/docs/kcl/types/SolidSet) - A solid or a group of solids.
|
[`[Solid]`](/docs/kcl/types/Solid)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
99882
docs/kcl/std.json
@ -12,11 +12,13 @@ You can provide more than one sketch to sweep, and they will all be swept along
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
sweep(
|
sweep(
|
||||||
sketchSet: SketchSet,
|
sketches: [Sketch],
|
||||||
path: SweepPath,
|
path: SweepPath,
|
||||||
sectional?: bool,
|
sectional?: bool,
|
||||||
tolerance?: number,
|
tolerance?: number,
|
||||||
): SolidSet
|
tagStart?: TagDeclarator,
|
||||||
|
tagEnd?: TagDeclarator,
|
||||||
|
): [Solid]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -24,14 +26,16 @@ sweep(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | The sketch or set of sketches that should be swept in space | Yes |
|
| `sketches` | [`[Sketch]`](/docs/kcl/types/Sketch) | The sketch or set of sketches that should be swept in space | Yes |
|
||||||
| `path` | [`SweepPath`](/docs/kcl/types/SweepPath) | The path to sweep the sketch along | Yes |
|
| `path` | [`SweepPath`](/docs/kcl/types/SweepPath) | The path to sweep the sketch along | Yes |
|
||||||
| `sectional` | [`bool`](/docs/kcl/types/bool) | If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components. | No |
|
| `sectional` | [`bool`](/docs/kcl/types/bool) | If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components. | No |
|
||||||
| `tolerance` | [`number`](/docs/kcl/types/number) | Tolerance for this operation | No |
|
| `tolerance` | [`number`](/docs/kcl/types/number) | Tolerance for this operation | No |
|
||||||
|
| `tagStart` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | A named tag for the face at the start of the sweep, i.e. the original sketch | No |
|
||||||
|
| `tagEnd` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | A named tag for the face at the end of the sweep | No |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`SolidSet`](/docs/kcl/types/SolidSet) - A solid or a group of solids.
|
[`[Solid]`](/docs/kcl/types/Solid)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -100,6 +100,22 @@ Any KCL value.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Property | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `type` |enum: `HomArray`| | No |
|
||||||
|
| `value` |`[` [`KclValue`](/docs/kcl/types/KclValue) `]`| | No |
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
**Type:** `object`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
@ -122,7 +138,6 @@ Any KCL value.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: [`TagIdentifier`](/docs/kcl/types#tag-identifier)| | No |
|
| `type` |enum: [`TagIdentifier`](/docs/kcl/types#tag-identifier)| | No |
|
||||||
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
||||||
| `info` |[`TagEngineInfo`](/docs/kcl/types/TagEngineInfo)| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -200,22 +215,6 @@ Any KCL value.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `Sketches`| | No |
|
|
||||||
| `value` |`[` [`Sketch`](/docs/kcl/types/Sketch) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
@ -232,22 +231,6 @@ Any KCL value.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `Solids`| | No |
|
|
||||||
| `value` |`[` [`Solid`](/docs/kcl/types/Solid) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
@ -338,22 +321,6 @@ Data for an imported geometry.
|
|||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `Tombstone`| | No |
|
|
||||||
| `value` |`null`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,6 +126,30 @@ A base path.
|
|||||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
A base path.
|
||||||
|
|
||||||
|
**Type:** `object`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Property | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `type` |enum: `ArcThreePoint`| | No |
|
||||||
|
| `p1` |`[number, number]`| Point 1 of the arc (base on the end of previous segment) | No |
|
||||||
|
| `p2` |`[number, number]`| Point 2 of the arc (interior kwarg) | No |
|
||||||
|
| `p3` |`[number, number]`| Point 3 of the arc (end kwarg) | No |
|
||||||
|
| `from` |`[number, number]`| The from point. | No |
|
||||||
|
| `to` |`[number, number]`| The to point. | No |
|
||||||
|
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||||
|
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||||
|
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
A path that is horizontal.
|
A path that is horizontal.
|
||||||
|
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
---
|
|
||||||
title: "SketchSet"
|
|
||||||
excerpt: "A sketch or a group of sketches."
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
A sketch or a group of sketches.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**This schema accepts exactly one of the following:**
|
|
||||||
|
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `sketch`| | No |
|
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the sketch (this will change when the engine's reference to it changes). | No |
|
|
||||||
| `paths` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No |
|
|
||||||
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
|
|
||||||
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No |
|
|
||||||
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |
|
|
||||||
| `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 |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
**Type:** `[object, array]`
|
|
||||||
|
|
||||||
`[` [`Sketch`](/docs/kcl/types/Sketch) `]`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `sketches`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -12,30 +12,6 @@ Data for a solid or an imported geometry.
|
|||||||
|
|
||||||
**This schema accepts exactly one of the following:**
|
**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.
|
Data for an imported geometry.
|
||||||
|
|
||||||
**Type:** `object`
|
**Type:** `object`
|
||||||
|
66
docs/kcl/types/SolidOrSketchOrImportedGeometry.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
---
|
||||||
|
title: "SolidOrSketchOrImportedGeometry"
|
||||||
|
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:**
|
||||||
|
|
||||||
|
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 |
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
**Type:** `[object, array]`
|
||||||
|
|
||||||
|
`[` [`Solid`](/docs/kcl/types/Solid) `]`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Property | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `type` |enum: `solidSet`| | No |
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
**Type:** `[object, array]`
|
||||||
|
|
||||||
|
`[` [`Sketch`](/docs/kcl/types/Sketch) `]`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Property | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `type` |enum: `sketchSet`| | No |
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
|||||||
---
|
|
||||||
title: "SolidSet"
|
|
||||||
excerpt: "A solid or a group of solids."
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
A solid or a group of solids.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**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 |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
**Type:** `[object, array]`
|
|
||||||
|
|
||||||
`[` [`Solid`](/docs/kcl/types/Solid) `]`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `solids`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { test, expect } from './zoo-test'
|
|||||||
import * as fsp from 'fs/promises'
|
import * as fsp from 'fs/promises'
|
||||||
import { executorInputPath, getUtils } from './test-utils'
|
import { executorInputPath, getUtils } from './test-utils'
|
||||||
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
|
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
|
||||||
import path from 'path'
|
import path, { join } from 'path'
|
||||||
|
|
||||||
test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
|
test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
|
||||||
test('Extrude from command bar selects extrude line after', async ({
|
test('Extrude from command bar selects extrude line after', async ({
|
||||||
@ -487,4 +487,53 @@ test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await toolbar.expectFileTreeState(['main.kcl', 'test.kcl'])
|
await toolbar.expectFileTreeState(['main.kcl', 'test.kcl'])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test(`Can add a named parameter or constant`, async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
context,
|
||||||
|
cmdBar,
|
||||||
|
scene,
|
||||||
|
editor,
|
||||||
|
}) => {
|
||||||
|
const projectName = 'test'
|
||||||
|
const beforeKclCode = `a = 5
|
||||||
|
b = a * a
|
||||||
|
c = 3 + a`
|
||||||
|
await context.folderSetupFn(async (dir) => {
|
||||||
|
const testProject = join(dir, projectName)
|
||||||
|
await fsp.mkdir(testProject, { recursive: true })
|
||||||
|
await fsp.writeFile(join(testProject, 'main.kcl'), beforeKclCode, 'utf-8')
|
||||||
|
})
|
||||||
|
await homePage.openProject(projectName)
|
||||||
|
// TODO: you probably shouldn't need an engine connection to add a parameter,
|
||||||
|
// but you do because all modeling commands have that requirement
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await test.step(`Go through the command palette flow`, async () => {
|
||||||
|
await cmdBar.cmdBarOpenBtn.click()
|
||||||
|
await cmdBar.chooseCommand('create parameter')
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
commandName: 'Create parameter',
|
||||||
|
currentArgKey: 'value',
|
||||||
|
currentArgValue: '5',
|
||||||
|
headerArguments: {
|
||||||
|
Value: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'value',
|
||||||
|
})
|
||||||
|
await cmdBar.argumentInput.locator('[contenteditable]').fill(`b - 5`)
|
||||||
|
// TODO: we have no loading indicator for the KCL argument input calculation
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'commandBarClosed',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
`a = 5b = a * amyParameter001 = b - 5c = 3 + a`
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -100,7 +100,8 @@ test(
|
|||||||
try {
|
try {
|
||||||
const outputGltf = await fsp.readFile(firstFileFullPath)
|
const outputGltf = await fsp.readFile(firstFileFullPath)
|
||||||
return outputGltf.byteLength
|
return outputGltf.byteLength
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
|
void error
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -179,7 +180,8 @@ test(
|
|||||||
try {
|
try {
|
||||||
const outputGltf = await fsp.readFile(secondFileFullPath)
|
const outputGltf = await fsp.readFile(secondFileFullPath)
|
||||||
return outputGltf.byteLength
|
return outputGltf.byteLength
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
|
void error
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -726,10 +726,10 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
|> line(end = [2, 0])
|
|> line(end = [2, 0])
|
||||||
|> line(end = [0, -10])
|
|> line(end = [0, -10])
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({
|
|> revolve(
|
||||||
axis: revolveAxis,
|
axis = revolveAxis,
|
||||||
angle: 90
|
angle = 90
|
||||||
}, %)
|
)
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -21,7 +21,7 @@ sketch001 = startSketchOn('XZ')
|
|||||||
|> angledLine([-45, length001], %)
|
|> angledLine([-45, length001], %)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
revolve001 = revolve({ axis = "X" }, sketch001)
|
revolve001 = revolve(sketch001, axis = "X")
|
||||||
triangle()
|
triangle()
|
||||||
|> extrude(length = 30)
|
|> extrude(length = 30)
|
||||||
plane001 = offsetPlane('XY', offset = 10)
|
plane001 = offsetPlane('XY', offset = 10)
|
||||||
@ -126,7 +126,7 @@ test.describe('Feature Tree pane', () => {
|
|||||||
await testViewSource({
|
await testViewSource({
|
||||||
operationName: 'Revolve',
|
operationName: 'Revolve',
|
||||||
operationIndex: 0,
|
operationIndex: 0,
|
||||||
expectedActiveLine: 'revolve001 = revolve({ axis = "X" }, sketch001)',
|
expectedActiveLine: 'revolve001 = revolve(sketch001, axis = "X")',
|
||||||
})
|
})
|
||||||
await testViewSource({
|
await testViewSource({
|
||||||
operationName: 'Triangle',
|
operationName: 'Triangle',
|
||||||
@ -231,10 +231,10 @@ test.describe('Feature Tree pane', () => {
|
|||||||
|> circle(center = [0, 0], radius = 5)
|
|> circle(center = [0, 0], radius = 5)
|
||||||
renamedExtrude = extrude(sketch001, length = ${initialInput})`
|
renamedExtrude = extrude(sketch001, length = ${initialInput})`
|
||||||
const newConstantName = 'distance001'
|
const newConstantName = 'distance001'
|
||||||
const expectedCode = `sketch001 = startSketchOn('XZ')
|
const expectedCode = `${newConstantName} = 23
|
||||||
|
sketch001 = startSketchOn('XZ')
|
||||||
|> circle(center = [0, 0], radius = 5)
|
|> circle(center = [0, 0], radius = 5)
|
||||||
${newConstantName} = 23
|
renamedExtrude = extrude(sketch001, length = ${newConstantName})`
|
||||||
renamedExtrude = extrude(sketch001, length = ${newConstantName})`
|
|
||||||
|
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const testDir = join(dir, 'test-sample')
|
const testDir = join(dir, 'test-sample')
|
||||||
|
@ -1197,7 +1197,7 @@ test.describe('Undo and redo do not keep history when navigating between files',
|
|||||||
`cloned file has an incremented name and same contents`,
|
`cloned file has an incremented name and same contents`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ page, context, homePage }, testInfo) => {
|
async ({ page, context, homePage }, testInfo) => {
|
||||||
const { panesOpen, createNewFile, cloneFile } = await getUtils(page, test)
|
const { panesOpen, cloneFile } = await getUtils(page, test)
|
||||||
|
|
||||||
const { dir } = await context.folderSetupFn(async (dir) => {
|
const { dir } = await context.folderSetupFn(async (dir) => {
|
||||||
const finalDir = join(dir, 'testDefault')
|
const finalDir = join(dir, 'testDefault')
|
||||||
|
@ -3,25 +3,15 @@
|
|||||||
import type {
|
import type {
|
||||||
BrowserContext,
|
BrowserContext,
|
||||||
ElectronApplication,
|
ElectronApplication,
|
||||||
Fixtures as PlaywrightFixtures,
|
|
||||||
TestInfo,
|
TestInfo,
|
||||||
Page,
|
Page,
|
||||||
} from '@playwright/test'
|
} from '@playwright/test'
|
||||||
|
|
||||||
import {
|
import { _electron as electron } from '@playwright/test'
|
||||||
_electron as electron,
|
|
||||||
PlaywrightTestArgs,
|
|
||||||
PlaywrightWorkerArgs,
|
|
||||||
} from '@playwright/test'
|
|
||||||
|
|
||||||
import * as TOML from '@iarna/toml'
|
import * as TOML from '@iarna/toml'
|
||||||
import {
|
import { TEST_SETTINGS } from '../storageStates'
|
||||||
TEST_SETTINGS_KEY,
|
import { SETTINGS_FILE_NAME } from 'lib/constants'
|
||||||
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 { getUtils, setup } from '../test-utils'
|
||||||
import fsp from 'fs/promises'
|
import fsp from 'fs/promises'
|
||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
@ -31,7 +21,6 @@ import { EditorFixture } from './editorFixture'
|
|||||||
import { ToolbarFixture } from './toolbarFixture'
|
import { ToolbarFixture } from './toolbarFixture'
|
||||||
import { SceneFixture } from './sceneFixture'
|
import { SceneFixture } from './sceneFixture'
|
||||||
import { HomePageFixture } from './homePageFixture'
|
import { HomePageFixture } from './homePageFixture'
|
||||||
import { unsafeTypedKeys } from 'lib/utils'
|
|
||||||
import { DeepPartial } from 'lib/types'
|
import { DeepPartial } from 'lib/types'
|
||||||
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
||||||
|
|
||||||
@ -278,13 +267,14 @@ export class ElectronZoo {
|
|||||||
if (fs.existsSync(this.projectDirName)) {
|
if (fs.existsSync(this.projectDirName)) {
|
||||||
await fsp.rm(this.projectDirName, { recursive: true })
|
await fsp.rm(this.projectDirName, { recursive: true })
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (_e) {
|
||||||
console.error(e)
|
console.error(_e)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fsp.mkdir(this.projectDirName)
|
await fsp.mkdir(this.projectDirName)
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
|
void error
|
||||||
// Not a problem if it already exists.
|
// Not a problem if it already exists.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
} from '../test-utils'
|
} from '../test-utils'
|
||||||
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
||||||
import { SIDEBAR_BUTTON_SUFFIX } from 'lib/constants'
|
import { SIDEBAR_BUTTON_SUFFIX } from 'lib/constants'
|
||||||
|
import { ToolbarModeName } from 'lib/toolbar'
|
||||||
|
|
||||||
export class ToolbarFixture {
|
export class ToolbarFixture {
|
||||||
public page: Page
|
public page: Page
|
||||||
@ -120,6 +121,15 @@ export class ToolbarFixture {
|
|||||||
// this is for the engine animation, as it takes 500ms to complete
|
// this is for the engine animation, as it takes 500ms to complete
|
||||||
await this.page.waitForTimeout(600)
|
await this.page.waitForTimeout(600)
|
||||||
}
|
}
|
||||||
|
private _getMode = () =>
|
||||||
|
this.page.locator('[data-current-mode]').getAttribute('data-current-mode')
|
||||||
|
expectToolbarMode = {
|
||||||
|
toBe: (mode: ToolbarModeName) => expect.poll(this._getMode).toEqual(mode),
|
||||||
|
not: {
|
||||||
|
toBe: (mode: ToolbarModeName) =>
|
||||||
|
expect.poll(this._getMode).not.toEqual(mode),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
private _serialiseFileTree = async () => {
|
private _serialiseFileTree = async () => {
|
||||||
return this.page
|
return this.page
|
||||||
@ -176,6 +186,22 @@ export class ToolbarFixture {
|
|||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
await this.page.getByTestId('dropdown-circle-three-points').click()
|
await this.page.getByTestId('dropdown-circle-three-points').click()
|
||||||
}
|
}
|
||||||
|
selectArc = async () => {
|
||||||
|
await this.page
|
||||||
|
.getByRole('button', { name: 'caret down Tangential Arc:' })
|
||||||
|
.click()
|
||||||
|
await expect(this.page.getByTestId('dropdown-arc')).toBeVisible()
|
||||||
|
await this.page.getByTestId('dropdown-arc').click()
|
||||||
|
}
|
||||||
|
selectThreePointArc = async () => {
|
||||||
|
await this.page
|
||||||
|
.getByRole('button', { name: 'caret down Tangential Arc:' })
|
||||||
|
.click()
|
||||||
|
await expect(
|
||||||
|
this.page.getByTestId('dropdown-three-point-arc')
|
||||||
|
).toBeVisible()
|
||||||
|
await this.page.getByTestId('dropdown-three-point-arc').click()
|
||||||
|
}
|
||||||
|
|
||||||
async closePane(paneId: SidebarType) {
|
async closePane(paneId: SidebarType) {
|
||||||
return closePane(this.page, paneId + SIDEBAR_BUTTON_SUFFIX)
|
return closePane(this.page, paneId + SIDEBAR_BUTTON_SUFFIX)
|
||||||
|
@ -850,159 +850,157 @@ openSketch = startSketchOn('XY')
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`Shift-click to select and deselect sketch segments`, async ({
|
test.fixme(
|
||||||
page,
|
`Shift-click to select and deselect sketch segments`,
|
||||||
homePage,
|
async ({ page, homePage, scene, editor }) => {
|
||||||
scene,
|
// Locators
|
||||||
editor,
|
const firstPointLocation = { x: 200, y: 100 }
|
||||||
}) => {
|
const secondPointLocation = { x: 800, y: 100 }
|
||||||
// Locators
|
const thirdPointLocation = { x: 800, y: 400 }
|
||||||
const firstPointLocation = { x: 200, y: 100 }
|
const fristSegmentLocation = { x: 750, y: 100 }
|
||||||
const secondPointLocation = { x: 800, y: 100 }
|
const secondSegmentLocation = { x: 800, y: 150 }
|
||||||
const thirdPointLocation = { x: 800, y: 400 }
|
const planeLocation = { x: 700, y: 200 }
|
||||||
const fristSegmentLocation = { x: 750, y: 100 }
|
|
||||||
const secondSegmentLocation = { x: 800, y: 150 }
|
|
||||||
const planeLocation = { x: 700, y: 200 }
|
|
||||||
|
|
||||||
// Click helpers
|
// Click helpers
|
||||||
const [clickFirstPoint] = scene.makeMouseHelpers(
|
const [clickFirstPoint] = scene.makeMouseHelpers(
|
||||||
firstPointLocation.x,
|
firstPointLocation.x,
|
||||||
firstPointLocation.y
|
firstPointLocation.y
|
||||||
)
|
)
|
||||||
const [clickSecondPoint] = scene.makeMouseHelpers(
|
const [clickSecondPoint] = scene.makeMouseHelpers(
|
||||||
secondPointLocation.x,
|
secondPointLocation.x,
|
||||||
secondPointLocation.y
|
secondPointLocation.y
|
||||||
)
|
)
|
||||||
const [clickThirdPoint] = scene.makeMouseHelpers(
|
const [clickThirdPoint] = scene.makeMouseHelpers(
|
||||||
thirdPointLocation.x,
|
thirdPointLocation.x,
|
||||||
thirdPointLocation.y
|
thirdPointLocation.y
|
||||||
)
|
)
|
||||||
const [clickFirstSegment] = scene.makeMouseHelpers(
|
const [clickFirstSegment] = scene.makeMouseHelpers(
|
||||||
fristSegmentLocation.x,
|
fristSegmentLocation.x,
|
||||||
fristSegmentLocation.y
|
fristSegmentLocation.y
|
||||||
)
|
)
|
||||||
const [clickSecondSegment] = scene.makeMouseHelpers(
|
const [clickSecondSegment] = scene.makeMouseHelpers(
|
||||||
secondSegmentLocation.x,
|
secondSegmentLocation.x,
|
||||||
secondSegmentLocation.y
|
secondSegmentLocation.y
|
||||||
)
|
)
|
||||||
const [clickPlane] = scene.makeMouseHelpers(
|
const [clickPlane] = scene.makeMouseHelpers(
|
||||||
planeLocation.x,
|
planeLocation.x,
|
||||||
planeLocation.y
|
planeLocation.y
|
||||||
)
|
|
||||||
|
|
||||||
// Colors
|
|
||||||
const edgeColorWhite: [number, number, number] = [220, 220, 220]
|
|
||||||
const edgeColorBlue: [number, number, number] = [20, 20, 200]
|
|
||||||
const backgroundColor: [number, number, number] = [30, 30, 30]
|
|
||||||
const tolerance = 40
|
|
||||||
const timeout = 150
|
|
||||||
|
|
||||||
// Setup
|
|
||||||
await test.step(`Initial test setup`, async () => {
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
||||||
await homePage.goToModelingScene()
|
|
||||||
|
|
||||||
// Wait for the scene and stream to load
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
backgroundColor,
|
|
||||||
secondPointLocation,
|
|
||||||
tolerance
|
|
||||||
)
|
)
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('Select and deselect a single sketch segment', async () => {
|
// Colors
|
||||||
await test.step('Get into sketch mode', async () => {
|
const edgeColorWhite: [number, number, number] = [220, 220, 220]
|
||||||
await editor.closePane()
|
const edgeColorBlue: [number, number, number] = [20, 20, 200]
|
||||||
await page.waitForTimeout(timeout)
|
const backgroundColor: [number, number, number] = [30, 30, 30]
|
||||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
const tolerance = 40
|
||||||
await page.waitForTimeout(timeout)
|
const timeout = 150
|
||||||
await clickPlane()
|
|
||||||
await page.waitForTimeout(1000)
|
// Setup
|
||||||
})
|
await test.step(`Initial test setup`, async () => {
|
||||||
await test.step('Draw sketch', async () => {
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await clickFirstPoint()
|
await homePage.goToModelingScene()
|
||||||
await page.waitForTimeout(timeout)
|
|
||||||
await clickSecondPoint()
|
// Wait for the scene and stream to load
|
||||||
await page.waitForTimeout(timeout)
|
|
||||||
await clickThirdPoint()
|
|
||||||
await page.waitForTimeout(timeout)
|
|
||||||
})
|
|
||||||
await test.step('Deselect line tool', async () => {
|
|
||||||
const btnLine = page.getByTestId('line')
|
|
||||||
const btnLineAriaPressed = await btnLine.getAttribute('aria-pressed')
|
|
||||||
if (btnLineAriaPressed === 'true') {
|
|
||||||
await btnLine.click()
|
|
||||||
}
|
|
||||||
await page.waitForTimeout(timeout)
|
|
||||||
})
|
|
||||||
await test.step('Select the first segment', async () => {
|
|
||||||
await page.waitForTimeout(timeout)
|
|
||||||
await clickFirstSegment()
|
|
||||||
await page.waitForTimeout(timeout)
|
|
||||||
await scene.expectPixelColor(
|
await scene.expectPixelColor(
|
||||||
edgeColorBlue,
|
backgroundColor,
|
||||||
fristSegmentLocation,
|
secondPointLocation,
|
||||||
tolerance
|
|
||||||
)
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
edgeColorWhite,
|
|
||||||
secondSegmentLocation,
|
|
||||||
tolerance
|
tolerance
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
await test.step('Select the second segment (Shift-click)', async () => {
|
|
||||||
await page.keyboard.down('Shift')
|
await test.step('Select and deselect a single sketch segment', async () => {
|
||||||
await page.waitForTimeout(timeout)
|
await test.step('Get into sketch mode', async () => {
|
||||||
await clickSecondSegment()
|
await editor.closePane()
|
||||||
await page.waitForTimeout(timeout)
|
await page.waitForTimeout(timeout)
|
||||||
await page.keyboard.up('Shift')
|
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||||
await scene.expectPixelColor(
|
await page.waitForTimeout(timeout)
|
||||||
edgeColorBlue,
|
await clickPlane()
|
||||||
fristSegmentLocation,
|
await page.waitForTimeout(1000)
|
||||||
tolerance
|
})
|
||||||
)
|
await test.step('Draw sketch', async () => {
|
||||||
await scene.expectPixelColor(
|
await clickFirstPoint()
|
||||||
edgeColorBlue,
|
await page.waitForTimeout(timeout)
|
||||||
secondSegmentLocation,
|
await clickSecondPoint()
|
||||||
tolerance
|
await page.waitForTimeout(timeout)
|
||||||
)
|
await clickThirdPoint()
|
||||||
|
await page.waitForTimeout(timeout)
|
||||||
|
})
|
||||||
|
await test.step('Deselect line tool', async () => {
|
||||||
|
const btnLine = page.getByTestId('line')
|
||||||
|
const btnLineAriaPressed = await btnLine.getAttribute('aria-pressed')
|
||||||
|
if (btnLineAriaPressed === 'true') {
|
||||||
|
await btnLine.click()
|
||||||
|
}
|
||||||
|
await page.waitForTimeout(timeout)
|
||||||
|
})
|
||||||
|
await test.step('Select the first segment', async () => {
|
||||||
|
await page.waitForTimeout(timeout)
|
||||||
|
await clickFirstSegment()
|
||||||
|
await page.waitForTimeout(timeout)
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorBlue,
|
||||||
|
fristSegmentLocation,
|
||||||
|
tolerance
|
||||||
|
)
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorWhite,
|
||||||
|
secondSegmentLocation,
|
||||||
|
tolerance
|
||||||
|
)
|
||||||
|
})
|
||||||
|
await test.step('Select the second segment (Shift-click)', async () => {
|
||||||
|
await page.keyboard.down('Shift')
|
||||||
|
await page.waitForTimeout(timeout)
|
||||||
|
await clickSecondSegment()
|
||||||
|
await page.waitForTimeout(timeout)
|
||||||
|
await page.keyboard.up('Shift')
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorBlue,
|
||||||
|
fristSegmentLocation,
|
||||||
|
tolerance
|
||||||
|
)
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorBlue,
|
||||||
|
secondSegmentLocation,
|
||||||
|
tolerance
|
||||||
|
)
|
||||||
|
})
|
||||||
|
await test.step('Deselect the first segment', async () => {
|
||||||
|
await page.keyboard.down('Shift')
|
||||||
|
await page.waitForTimeout(timeout)
|
||||||
|
await clickFirstSegment()
|
||||||
|
await page.waitForTimeout(timeout)
|
||||||
|
await page.keyboard.up('Shift')
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorWhite,
|
||||||
|
fristSegmentLocation,
|
||||||
|
tolerance
|
||||||
|
)
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorBlue,
|
||||||
|
secondSegmentLocation,
|
||||||
|
tolerance
|
||||||
|
)
|
||||||
|
})
|
||||||
|
await test.step('Deselect the second segment', async () => {
|
||||||
|
await page.keyboard.down('Shift')
|
||||||
|
await page.waitForTimeout(timeout)
|
||||||
|
await clickSecondSegment()
|
||||||
|
await page.waitForTimeout(timeout)
|
||||||
|
await page.keyboard.up('Shift')
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorWhite,
|
||||||
|
fristSegmentLocation,
|
||||||
|
tolerance
|
||||||
|
)
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorWhite,
|
||||||
|
secondSegmentLocation,
|
||||||
|
tolerance
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
await test.step('Deselect the first segment', async () => {
|
}
|
||||||
await page.keyboard.down('Shift')
|
)
|
||||||
await page.waitForTimeout(timeout)
|
|
||||||
await clickFirstSegment()
|
|
||||||
await page.waitForTimeout(timeout)
|
|
||||||
await page.keyboard.up('Shift')
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
edgeColorWhite,
|
|
||||||
fristSegmentLocation,
|
|
||||||
tolerance
|
|
||||||
)
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
edgeColorBlue,
|
|
||||||
secondSegmentLocation,
|
|
||||||
tolerance
|
|
||||||
)
|
|
||||||
})
|
|
||||||
await test.step('Deselect the second segment', async () => {
|
|
||||||
await page.keyboard.down('Shift')
|
|
||||||
await page.waitForTimeout(timeout)
|
|
||||||
await clickSecondSegment()
|
|
||||||
await page.waitForTimeout(timeout)
|
|
||||||
await page.keyboard.up('Shift')
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
edgeColorWhite,
|
|
||||||
fristSegmentLocation,
|
|
||||||
tolerance
|
|
||||||
)
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
edgeColorWhite,
|
|
||||||
secondSegmentLocation,
|
|
||||||
tolerance
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test(`Offset plane point-and-click`, async ({
|
test(`Offset plane point-and-click`, async ({
|
||||||
context,
|
context,
|
||||||
@ -1024,7 +1022,7 @@ openSketch = startSketchOn('XY')
|
|||||||
await page.waitForTimeout(15000)
|
await page.waitForTimeout(15000)
|
||||||
|
|
||||||
await test.step(`Look for the blue of the XZ plane`, async () => {
|
await test.step(`Look for the blue of the XZ plane`, async () => {
|
||||||
await scene.expectPixelColor([50, 51, 96], testPoint, 15)
|
//await scene.expectPixelColor([50, 51, 96], testPoint, 15) // FIXME
|
||||||
})
|
})
|
||||||
await test.step(`Go through the command bar flow`, async () => {
|
await test.step(`Go through the command bar flow`, async () => {
|
||||||
await toolbar.offsetPlaneButton.click()
|
await toolbar.offsetPlaneButton.click()
|
||||||
@ -1066,7 +1064,7 @@ openSketch = startSketchOn('XY')
|
|||||||
)
|
)
|
||||||
await operationButton.click({ button: 'left' })
|
await operationButton.click({ button: 'left' })
|
||||||
await page.keyboard.press('Delete')
|
await page.keyboard.press('Delete')
|
||||||
await scene.expectPixelColor([50, 51, 96], testPoint, 15)
|
//await scene.expectPixelColor([50, 51, 96], testPoint, 15) // FIXME
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1880,6 +1878,119 @@ fillet04 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test(`Fillet with large radius should update code even if engine fails`, async ({
|
||||||
|
context,
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
editor,
|
||||||
|
toolbar,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
// Create a cube with small edges that will cause some fillets to fail
|
||||||
|
const initialCode = `sketch001 = startSketchOn('XY')
|
||||||
|
profile001 = startProfileAt([0, 0], sketch001)
|
||||||
|
|> yLine(length = -1)
|
||||||
|
|> xLine(length = -10)
|
||||||
|
|> yLine(length = 10)
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()
|
||||||
|
extrude001 = extrude(profile001, length = 5)
|
||||||
|
`
|
||||||
|
const taggedSegment = `yLine(length = -1, tag = $seg01)`
|
||||||
|
const filletExpression = `fillet(radius = 1000, tags = [getNextAdjacentEdge(seg01)])`
|
||||||
|
|
||||||
|
// Locators
|
||||||
|
const edgeLocation = { x: 659, y: 313 }
|
||||||
|
const bodyLocation = { x: 594, y: 313 }
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
const edgeColorWhite: [number, number, number] = [248, 248, 248]
|
||||||
|
const edgeColorYellow: [number, number, number] = [251, 251, 120] // Mac:B=251,251,90 Ubuntu:240,241,180, Windows:240,241,180
|
||||||
|
const backgroundColor: [number, number, number] = [30, 30, 30]
|
||||||
|
const bodyColor: [number, number, number] = [155, 155, 155]
|
||||||
|
const lowTolerance = 20
|
||||||
|
const highTolerance = 70
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
await test.step(`Initial test setup`, async () => {
|
||||||
|
await context.addInitScript((initialCode) => {
|
||||||
|
localStorage.setItem('persistCode', initialCode)
|
||||||
|
}, initialCode)
|
||||||
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
// verify modeling scene is loaded
|
||||||
|
await scene.expectPixelColor(backgroundColor, edgeLocation, lowTolerance)
|
||||||
|
|
||||||
|
// wait for stream to load
|
||||||
|
await scene.expectPixelColor(bodyColor, bodyLocation, highTolerance)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test
|
||||||
|
await test.step('Select edges and apply oversized fillet', async () => {
|
||||||
|
await test.step(`Select the edge`, async () => {
|
||||||
|
await scene.expectPixelColor(edgeColorWhite, edgeLocation, lowTolerance)
|
||||||
|
const [clickOnTheEdge] = scene.makeMouseHelpers(
|
||||||
|
edgeLocation.x,
|
||||||
|
edgeLocation.y
|
||||||
|
)
|
||||||
|
await clickOnTheEdge()
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorYellow,
|
||||||
|
edgeLocation,
|
||||||
|
highTolerance // Ubuntu color mismatch can require high tolerance
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Apply fillet`, async () => {
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await toolbar.filletButton.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Fillet',
|
||||||
|
highlightedHeaderArg: 'selection',
|
||||||
|
currentArgKey: 'selection',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Selection: '',
|
||||||
|
Radius: '',
|
||||||
|
},
|
||||||
|
stage: 'arguments',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Fillet',
|
||||||
|
highlightedHeaderArg: 'radius',
|
||||||
|
currentArgKey: 'radius',
|
||||||
|
currentArgValue: '5',
|
||||||
|
headerArguments: {
|
||||||
|
Selection: '1 sweepEdge',
|
||||||
|
Radius: '',
|
||||||
|
},
|
||||||
|
stage: 'arguments',
|
||||||
|
})
|
||||||
|
// Set a large radius (1000)
|
||||||
|
await cmdBar.currentArgumentInput.locator('.cm-content').fill('1000')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Fillet',
|
||||||
|
headerArguments: {
|
||||||
|
Selection: '1 sweepEdge',
|
||||||
|
Radius: '1000',
|
||||||
|
},
|
||||||
|
stage: 'review',
|
||||||
|
})
|
||||||
|
// Apply fillet with large radius
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Verify code is updated regardless of execution errors', async () => {
|
||||||
|
await editor.expectEditor.toContain(taggedSegment)
|
||||||
|
await editor.expectEditor.toContain(filletExpression)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test(`Chamfer point-and-click`, async ({
|
test(`Chamfer point-and-click`, async ({
|
||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
@ -1906,7 +2017,6 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
// Locators
|
// Locators
|
||||||
const firstEdgeLocation = { x: 600, y: 193 }
|
const firstEdgeLocation = { x: 600, y: 193 }
|
||||||
const secondEdgeLocation = { x: 600, y: 383 }
|
const secondEdgeLocation = { x: 600, y: 383 }
|
||||||
const bodyLocation = { x: 630, y: 290 }
|
|
||||||
const [clickOnFirstEdge] = scene.makeMouseHelpers(
|
const [clickOnFirstEdge] = scene.makeMouseHelpers(
|
||||||
firstEdgeLocation.x,
|
firstEdgeLocation.x,
|
||||||
firstEdgeLocation.y
|
firstEdgeLocation.y
|
||||||
@ -1919,7 +2029,6 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
// Colors
|
// Colors
|
||||||
const edgeColorWhite: [number, number, number] = [248, 248, 248]
|
const edgeColorWhite: [number, number, number] = [248, 248, 248]
|
||||||
const edgeColorYellow: [number, number, number] = [251, 251, 40] // Mac:B=67 Ubuntu:B=12
|
const edgeColorYellow: [number, number, number] = [251, 251, 40] // Mac:B=67 Ubuntu:B=12
|
||||||
const bodyColor: [number, number, number] = [155, 155, 155]
|
|
||||||
const chamferColor: [number, number, number] = [168, 168, 168]
|
const chamferColor: [number, number, number] = [168, 168, 168]
|
||||||
const backgroundColor: [number, number, number] = [30, 30, 30]
|
const backgroundColor: [number, number, number] = [30, 30, 30]
|
||||||
const lowTolerance = 20
|
const lowTolerance = 20
|
||||||
@ -2271,8 +2380,8 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `sketch001 = startSketchOn('XZ')
|
const initialCode = `sketch001 = startSketchOn('XZ')
|
||||||
|> circle(center = [0, 0], radius = 30)
|
|> circle(center = [0, 0], radius = 30)
|
||||||
extrude001 = extrude(sketch001, length = 30)
|
extrude001 = extrude(sketch001, length = 30)
|
||||||
`
|
`
|
||||||
await context.addInitScript((initialCode) => {
|
await context.addInitScript((initialCode) => {
|
||||||
localStorage.setItem('persistCode', initialCode)
|
localStorage.setItem('persistCode', initialCode)
|
||||||
@ -2286,6 +2395,8 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
||||||
const shellDeclaration =
|
const shellDeclaration =
|
||||||
"shell001 = shell(extrude001, faces = ['end'], thickness = 5)"
|
"shell001 = shell(extrude001, faces = ['end'], thickness = 5)"
|
||||||
|
const editedShellDeclaration =
|
||||||
|
"shell001 = shell(extrude001, faces = ['end'], thickness = 2)"
|
||||||
|
|
||||||
await test.step(`Look for the grey of the shape`, async () => {
|
await test.step(`Look for the grey of the shape`, async () => {
|
||||||
await scene.expectPixelColor([127, 127, 127], testPoint, 15)
|
await scene.expectPixelColor([127, 127, 127], testPoint, 15)
|
||||||
@ -2352,6 +2463,45 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
})
|
})
|
||||||
await scene.expectPixelColor([146, 146, 146], testPoint, 15)
|
await scene.expectPixelColor([146, 146, 146], testPoint, 15)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await test.step('Edit shell via feature tree selection works', async () => {
|
||||||
|
await toolbar.closePane('code')
|
||||||
|
await toolbar.openPane('feature-tree')
|
||||||
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
|
'Shell',
|
||||||
|
0
|
||||||
|
)
|
||||||
|
await operationButton.dblclick()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'thickness',
|
||||||
|
currentArgValue: '5',
|
||||||
|
headerArguments: {
|
||||||
|
Thickness: '5',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'thickness',
|
||||||
|
commandName: 'Shell',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText('2')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Thickness: '2',
|
||||||
|
},
|
||||||
|
commandName: 'Shell',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await toolbar.closePane('feature-tree')
|
||||||
|
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
|
||||||
|
await toolbar.openPane('code')
|
||||||
|
await editor.expectEditor.toContain(editedShellDeclaration)
|
||||||
|
await editor.expectState({
|
||||||
|
diagnostics: [],
|
||||||
|
activeLines: [editedShellDeclaration],
|
||||||
|
highlightedCode: '',
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2387,6 +2537,8 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
const mutatedCode = 'xLine(length = -40, tag = $seg01)'
|
const mutatedCode = 'xLine(length = -40, tag = $seg01)'
|
||||||
const shellDeclaration =
|
const shellDeclaration =
|
||||||
"shell001 = shell(extrude001, faces = ['end', seg01], thickness = 5)"
|
"shell001 = shell(extrude001, faces = ['end', seg01], thickness = 5)"
|
||||||
|
const editedShellDeclaration =
|
||||||
|
"shell001 = shell(extrude001, faces = ['end', seg01], thickness = 1)"
|
||||||
|
|
||||||
await test.step(`Look for the grey of the shape`, async () => {
|
await test.step(`Look for the grey of the shape`, async () => {
|
||||||
await scene.expectPixelColor([99, 99, 99], testPoint, 15)
|
await scene.expectPixelColor([99, 99, 99], testPoint, 15)
|
||||||
@ -2435,6 +2587,41 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
await scene.expectPixelColor([49, 49, 49], testPoint, 15)
|
await scene.expectPixelColor([49, 49, 49], testPoint, 15)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await test.step('Edit shell via feature tree selection works', async () => {
|
||||||
|
await editor.closePane()
|
||||||
|
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
|
||||||
|
await operationButton.dblclick({ button: 'left' })
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'thickness',
|
||||||
|
currentArgValue: '5',
|
||||||
|
headerArguments: {
|
||||||
|
Thickness: '5',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'thickness',
|
||||||
|
commandName: 'Shell',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText('1')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Thickness: '1',
|
||||||
|
},
|
||||||
|
commandName: 'Shell',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await toolbar.closePane('feature-tree')
|
||||||
|
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
|
||||||
|
await toolbar.openPane('code')
|
||||||
|
await editor.expectEditor.toContain(editedShellDeclaration)
|
||||||
|
await editor.expectState({
|
||||||
|
diagnostics: [],
|
||||||
|
activeLines: [editedShellDeclaration],
|
||||||
|
highlightedCode: '',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
await test.step('Delete shell via feature tree selection', async () => {
|
await test.step('Delete shell via feature tree selection', async () => {
|
||||||
await editor.closePane()
|
await editor.closePane()
|
||||||
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
|
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
|
||||||
@ -2529,7 +2716,7 @@ extrude002 = extrude(sketch002, length = 50)
|
|||||||
highlightedCode: '',
|
highlightedCode: '',
|
||||||
})
|
})
|
||||||
await toolbar.closePane('code')
|
await toolbar.closePane('code')
|
||||||
await scene.expectPixelColor([73, 73, 73], testPoint, 15)
|
await scene.expectPixelColor([80, 80, 80], testPoint, 15)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2734,7 +2921,7 @@ segAng(rectangleSegmentA002),
|
|||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
|
||||||
const newCodeToFind = `revolve001 = revolve({ angle = 360, axis = 'X' }, sketch002)`
|
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = 'X')`
|
||||||
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
||||||
})
|
})
|
||||||
test('revolve surface around edge from an extruded solid2d', async ({
|
test('revolve surface around edge from an extruded solid2d', async ({
|
||||||
@ -2784,7 +2971,7 @@ radius = 8.69
|
|||||||
await page.getByText(lineCodeToSelection).click()
|
await page.getByText(lineCodeToSelection).click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
|
||||||
const newCodeToFind = `revolve001 = revolve({angle = 360, axis = getOppositeEdge(rectangleSegmentA001)}, sketch002) `
|
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = getOppositeEdge(rectangleSegmentA001)) `
|
||||||
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
||||||
})
|
})
|
||||||
test('revolve sketch circle around line segment from startProfileAt sketch', async ({
|
test('revolve sketch circle around line segment from startProfileAt sketch', async ({
|
||||||
@ -2835,7 +3022,7 @@ radius = 8.69
|
|||||||
await page.getByText(lineCodeToSelection).click()
|
await page.getByText(lineCodeToSelection).click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
|
||||||
const newCodeToFind = `revolve001 = revolve({ angle = 360, axis = seg01 }, sketch003)`
|
const newCodeToFind = `revolve001 = revolve(sketch003, angle = 360, axis = seg01)`
|
||||||
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -539,7 +539,8 @@ test.describe('Can export from electron app', () => {
|
|||||||
try {
|
try {
|
||||||
const outputGltf = await fsp.readFile(filepath)
|
const outputGltf = await fsp.readFile(filepath)
|
||||||
return outputGltf.byteLength
|
return outputGltf.byteLength
|
||||||
} catch (e) {
|
} catch (error: unknown) {
|
||||||
|
void error
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -53,46 +53,47 @@ sketch003 = startSketchOn('XY')
|
|||||||
|> close()
|
|> close()
|
||||||
extrude003 = extrude(sketch003, length = 20)
|
extrude003 = extrude(sketch003, length = 20)
|
||||||
`
|
`
|
||||||
|
test.describe('edit with AI example snapshots', () => {
|
||||||
|
test(
|
||||||
|
`change colour`,
|
||||||
|
{ tag: '@snapshot' },
|
||||||
|
async ({ context, homePage, cmdBar, editor, page, scene }) => {
|
||||||
|
await context.addInitScript((file) => {
|
||||||
|
localStorage.setItem('persistCode', file)
|
||||||
|
}, file)
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.waitForExecutionDone()
|
||||||
|
|
||||||
test(
|
const body1CapCoords = { x: 571, y: 351 }
|
||||||
`change colour`,
|
const [clickBody1Cap] = scene.makeMouseHelpers(
|
||||||
{ tag: '@snapshot' },
|
body1CapCoords.x,
|
||||||
async ({ context, homePage, cmdBar, editor, page, scene }) => {
|
body1CapCoords.y
|
||||||
await context.addInitScript((file) => {
|
)
|
||||||
localStorage.setItem('persistCode', file)
|
const yellow: [number, number, number] = [179, 179, 131]
|
||||||
}, file)
|
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
||||||
await homePage.goToModelingScene()
|
|
||||||
await scene.waitForExecutionDone()
|
|
||||||
|
|
||||||
const body1CapCoords = { x: 571, y: 351 }
|
await test.step('wait for scene to load select body and check selection came through', async () => {
|
||||||
const [clickBody1Cap] = scene.makeMouseHelpers(
|
await scene.expectPixelColor([134, 134, 134], body1CapCoords, 15)
|
||||||
body1CapCoords.x,
|
await clickBody1Cap()
|
||||||
body1CapCoords.y
|
await scene.expectPixelColor(yellow, body1CapCoords, 20)
|
||||||
)
|
await editor.expectState({
|
||||||
const yellow: [number, number, number] = [179, 179, 131]
|
highlightedCode: '',
|
||||||
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
activeLines: ['|>startProfileAt([-73.64,-42.89],%)'],
|
||||||
|
diagnostics: [],
|
||||||
await test.step('wait for scene to load select body and check selection came through', async () => {
|
})
|
||||||
await scene.expectPixelColor([134, 134, 134], body1CapCoords, 15)
|
|
||||||
await clickBody1Cap()
|
|
||||||
await scene.expectPixelColor(yellow, body1CapCoords, 20)
|
|
||||||
await editor.expectState({
|
|
||||||
highlightedCode: '',
|
|
||||||
activeLines: ['|>startProfileAt([-73.64,-42.89],%)'],
|
|
||||||
diagnostics: [],
|
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('fire off edit prompt', async () => {
|
await test.step('fire off edit prompt', async () => {
|
||||||
await cmdBar.captureTextToCadRequestSnapshot(test.info())
|
await cmdBar.captureTextToCadRequestSnapshot(test.info())
|
||||||
await cmdBar.openCmdBar('promptToEdit')
|
await cmdBar.openCmdBar('promptToEdit')
|
||||||
// being specific about the color with a hex means asserting pixel color is more stable
|
// being specific about the color with a hex means asserting pixel color is more stable
|
||||||
await page
|
await page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
.fill('make this neon green please, use #39FF14')
|
.fill('make this neon green please, use #39FF14')
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await expect(submittingToast).toBeVisible()
|
await expect(submittingToast).toBeVisible()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
})
|
||||||
|
@ -196,64 +196,60 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`manual code selection rename`, async ({
|
test.fixme(
|
||||||
context,
|
`manual code selection rename`,
|
||||||
homePage,
|
async ({ context, homePage, cmdBar, editor, page, scene }) => {
|
||||||
cmdBar,
|
const body1CapCoords = { x: 571, y: 311 }
|
||||||
editor,
|
|
||||||
page,
|
|
||||||
scene,
|
|
||||||
}) => {
|
|
||||||
const body1CapCoords = { x: 571, y: 311 }
|
|
||||||
|
|
||||||
await context.addInitScript((file) => {
|
await context.addInitScript((file) => {
|
||||||
localStorage.setItem('persistCode', file)
|
localStorage.setItem('persistCode', file)
|
||||||
}, file)
|
}, file)
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.waitForExecutionDone()
|
||||||
|
|
||||||
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
||||||
const successToast = page.getByText('Prompt to edit successful')
|
const successToast = page.getByText('Prompt to edit successful')
|
||||||
const acceptBtn = page.getByRole('button', { name: 'checkmark Accept' })
|
const acceptBtn = page.getByRole('button', { name: 'checkmark Accept' })
|
||||||
|
|
||||||
await test.step('wait for scene to load and select code in editor', async () => {
|
await test.step('wait for scene to load and select code in editor', async () => {
|
||||||
// Find and select the text "sketch002" in the editor
|
// Find and select the text "sketch002" in the editor
|
||||||
await editor.selectText('sketch002')
|
await editor.selectText('sketch002')
|
||||||
|
|
||||||
// Verify the selection was made
|
// Verify the selection was made
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
highlightedCode: '',
|
highlightedCode: '',
|
||||||
activeLines: ["sketch002 = startSketchOn('XZ')"],
|
activeLines: ["sketch002 = startSketchOn('XZ')"],
|
||||||
diagnostics: [],
|
diagnostics: [],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('fire off edit prompt', async () => {
|
await test.step('fire off edit prompt', async () => {
|
||||||
await scene.expectPixelColor([134, 134, 134], body1CapCoords, 15)
|
await scene.expectPixelColor([134, 134, 134], body1CapCoords, 15)
|
||||||
await cmdBar.openCmdBar('promptToEdit')
|
await cmdBar.openCmdBar('promptToEdit')
|
||||||
await page
|
await page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
.fill('Please rename to mySketch001')
|
.fill('Please rename to mySketch001')
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await expect(submittingToast).toBeVisible()
|
await expect(submittingToast).toBeVisible()
|
||||||
await expect(submittingToast).not.toBeVisible({
|
await expect(submittingToast).not.toBeVisible({
|
||||||
timeout: 2 * 60_000,
|
timeout: 2 * 60_000,
|
||||||
|
})
|
||||||
|
await expect(successToast).toBeVisible()
|
||||||
})
|
})
|
||||||
await expect(successToast).toBeVisible()
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('verify rename change and accept it', async () => {
|
await test.step('verify rename change and accept it', async () => {
|
||||||
await editor.expectEditor.toContain('mySketch001 = startSketchOn')
|
await editor.expectEditor.toContain('mySketch001 = startSketchOn')
|
||||||
await editor.expectEditor.not.toContain('sketch002 = startSketchOn')
|
await editor.expectEditor.not.toContain('sketch002 = startSketchOn')
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
'extrude002 = extrude(mySketch001, length = 50)'
|
'extrude002 = extrude(mySketch001, length = 50)'
|
||||||
)
|
)
|
||||||
|
|
||||||
await acceptBtn.click()
|
await acceptBtn.click()
|
||||||
await expect(successToast).not.toBeVisible()
|
await expect(successToast).not.toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
test('multiple body selections', async ({
|
test('multiple body selections', async ({
|
||||||
context,
|
context,
|
||||||
|
@ -319,7 +319,6 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
'when engine fails export we handle the failure and alert the user',
|
'when engine fails export we handle the failure and alert the user',
|
||||||
{ tag: '@skipLocalEngine' },
|
{ tag: '@skipLocalEngine' },
|
||||||
async ({ scene, page, homePage, cmdBar }) => {
|
async ({ scene, page, homePage, cmdBar }) => {
|
||||||
const u = await getUtils(page)
|
|
||||||
await page.addInitScript(
|
await page.addInitScript(
|
||||||
async ({ code }) => {
|
async ({ code }) => {
|
||||||
localStorage.setItem('persistCode', code)
|
localStorage.setItem('persistCode', code)
|
||||||
@ -406,8 +405,9 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
await expect(successToastMessage).toBeVisible()
|
await expect(successToastMessage).toBeVisible()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
// We updated this test such that you can have multiple exports going at once.
|
||||||
test(
|
test(
|
||||||
'ensure you can not export while an export is already going',
|
'ensure you CAN export while an export is already going',
|
||||||
{ tag: ['@skipLinux', '@skipWin'] },
|
{ tag: ['@skipLinux', '@skipWin'] },
|
||||||
async ({ page, homePage }) => {
|
async ({ page, homePage }) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
@ -442,22 +442,13 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
||||||
const successToastMessage = page.getByText(`Exported successfully`)
|
const successToastMessage = page.getByText(`Exported successfully`)
|
||||||
|
|
||||||
await test.step('Blocked second export', async () => {
|
await test.step('second export', async () => {
|
||||||
await clickExportButton(page)
|
await clickExportButton(page)
|
||||||
|
|
||||||
await expect(exportingToastMessage).toBeVisible()
|
await expect(exportingToastMessage).toBeVisible()
|
||||||
|
|
||||||
await clickExportButton(page)
|
await clickExportButton(page)
|
||||||
|
|
||||||
await test.step('The second export is blocked', async () => {
|
|
||||||
// Find the toast.
|
|
||||||
// Look out for the toast message
|
|
||||||
await Promise.all([
|
|
||||||
expect(exportingToastMessage.first()).toBeVisible(),
|
|
||||||
expect(alreadyExportingToastMessage).toBeVisible(),
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('The first export still succeeds', async () => {
|
await test.step('The first export still succeeds', async () => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 }),
|
expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 }),
|
||||||
@ -487,12 +478,12 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
expect(alreadyExportingToastMessage).not.toBeVisible(),
|
expect(alreadyExportingToastMessage).not.toBeVisible(),
|
||||||
])
|
])
|
||||||
|
|
||||||
await expect(successToastMessage).toBeVisible()
|
await expect(successToastMessage).toHaveCount(2)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
test(
|
test.fixme(
|
||||||
`Network health indicator only appears in modeling view`,
|
`Network health indicator only appears in modeling view`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
@ -636,11 +627,8 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
})
|
})
|
||||||
|
|
||||||
const toolBarMode = () =>
|
|
||||||
page.locator('[data-currentMode]').getAttribute('data-currentMode')
|
|
||||||
|
|
||||||
await test.step('Start sketch and select a plane', async () => {
|
await test.step('Start sketch and select a plane', async () => {
|
||||||
await expect.poll(toolBarMode).toEqual('modeling')
|
await toolbar.expectToolbarMode.toBe('modeling')
|
||||||
// Click the start sketch button
|
// Click the start sketch button
|
||||||
await toolbar.startSketchPlaneSelection()
|
await toolbar.startSketchPlaneSelection()
|
||||||
|
|
||||||
@ -649,10 +637,10 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
|
|
||||||
// Check that the modeling toolbar doesn't appear during the animation
|
// Check that the modeling toolbar doesn't appear during the animation
|
||||||
// The animation typically takes around 500ms, so we'll check for a second
|
// The animation typically takes around 500ms, so we'll check for a second
|
||||||
await expect.poll(toolBarMode, { timeout: 1000 }).not.toEqual('modeling')
|
await toolbar.expectToolbarMode.not.toBe('modeling')
|
||||||
|
|
||||||
// After animation completes, we should see the sketching toolbar
|
// After animation completes, we should see the sketching toolbar
|
||||||
await expect.poll(toolBarMode).toEqual('sketching')
|
await toolbar.expectToolbarMode.toBe('sketching')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { readFileSync } from 'fs'
|
import { readFileSync } from 'fs'
|
||||||
|
|
||||||
const secrets: Record<string, string> = {}
|
const secrets: Record<string, string> = {}
|
||||||
|
const secretsPath = './e2e/playwright/playwright-secrets.env'
|
||||||
try {
|
try {
|
||||||
const file = readFileSync('./e2e/playwright/playwright-secrets.env', 'utf8')
|
const file = readFileSync(secretsPath, 'utf8')
|
||||||
file
|
file
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.filter((line) => line && line.length > 1)
|
.filter((line) => line && line.length > 1)
|
||||||
@ -13,11 +14,15 @@ try {
|
|||||||
// prefer env vars over secrets file
|
// prefer env vars over secrets file
|
||||||
secrets[key] = process.env[key] || (value as any).replaceAll('"', '')
|
secrets[key] = process.env[key] || (value as any).replaceAll('"', '')
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (error: unknown) {
|
||||||
|
void error
|
||||||
// probably running in CI
|
// probably running in CI
|
||||||
secrets.token = process.env.token || ''
|
console.warn(
|
||||||
secrets.snapshottoken = process.env.snapshottoken || ''
|
`Error reading ${secretsPath}; environment variables will be used`
|
||||||
// add more env vars here to make them available in CI
|
)
|
||||||
}
|
}
|
||||||
|
secrets.token = secrets.token || process.env.token || ''
|
||||||
|
secrets.snapshottoken = secrets.snapshottoken || process.env.snapshottoken || ''
|
||||||
|
// add more env vars here to make them available in CI
|
||||||
|
|
||||||
export { secrets }
|
export { secrets }
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
} from './test-utils'
|
} from './test-utils'
|
||||||
import { uuidv4, roundOff } from 'lib/utils'
|
import { uuidv4, roundOff } from 'lib/utils'
|
||||||
import { SceneFixture } from './fixtures/sceneFixture'
|
import { SceneFixture } from './fixtures/sceneFixture'
|
||||||
|
import { CmdBarFixture } from './fixtures/cmdBarFixture'
|
||||||
|
|
||||||
test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
||||||
test('multi-sketch file shows multiple Edit Sketch buttons', async ({
|
test('multi-sketch file shows multiple Edit Sketch buttons', async ({
|
||||||
@ -186,12 +187,13 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
})
|
})
|
||||||
test.describe('Can edit segments by dragging their handles', () => {
|
test.fixme('Can edit segments by dragging their handles', () => {
|
||||||
const doEditSegmentsByDraggingHandle = async (
|
const doEditSegmentsByDraggingHandle = async (
|
||||||
page: Page,
|
page: Page,
|
||||||
homePage: HomePageFixture,
|
homePage: HomePageFixture,
|
||||||
openPanes: string[],
|
openPanes: string[],
|
||||||
scene: SceneFixture
|
scene: SceneFixture,
|
||||||
|
cmdBar: CmdBarFixture
|
||||||
) => {
|
) => {
|
||||||
// Load the app with the code panes
|
// Load the app with the code panes
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
@ -201,13 +203,22 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
|> startProfileAt([4.61, -14.01], %)
|
|> startProfileAt([4.61, -14.01], %)
|
||||||
|> line(end = [12.73, -0.09])
|
|> line(end = [12.73, -0.09])
|
||||||
|> tangentialArcTo([24.95, -5.38], %)
|
|> tangentialArcTo([24.95, -5.38], %)
|
||||||
|
|> arcTo({
|
||||||
|
interior = [20.18, -1.7],
|
||||||
|
end = [11.82, -1.16]
|
||||||
|
}, %)
|
||||||
|
|> arc({
|
||||||
|
radius = 5.92,
|
||||||
|
angleStart = -89.36,
|
||||||
|
angleEnd = 135.81
|
||||||
|
}, %)
|
||||||
|> close()`
|
|> close()`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
@ -242,7 +253,17 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
|> startProfileAt([4.61, -14.01], %)
|
|> startProfileAt([4.61, -14.01], %)
|
||||||
|> line(end = [12.73, -0.09])
|
|> line(end = [12.73, -0.09])
|
||||||
|> tangentialArcTo([24.95, -5.38], %)
|
|> tangentialArcTo([24.95, -5.38], %)
|
||||||
|> close()`)
|
|> arcTo({
|
||||||
|
interior = [20.18, -1.7],
|
||||||
|
end = [11.82, -1.16]
|
||||||
|
}, %)
|
||||||
|
|> arc({
|
||||||
|
radius = 5.92,
|
||||||
|
angleStart = -89.36,
|
||||||
|
angleEnd = 135.81
|
||||||
|
}, %)
|
||||||
|
|> close()
|
||||||
|
`)
|
||||||
} else {
|
} else {
|
||||||
// Ensure we don't see the code.
|
// Ensure we don't see the code.
|
||||||
await expect(u.codeLocator).not.toBeVisible()
|
await expect(u.codeLocator).not.toBeVisible()
|
||||||
@ -272,7 +293,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
|
|
||||||
const step5 = { steps: 5 }
|
const step5 = { steps: 5 }
|
||||||
|
|
||||||
await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
|
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
|
||||||
|
|
||||||
// drag startProfileAt handle
|
// drag startProfileAt handle
|
||||||
await page.mouse.move(startPX[0], startPX[1])
|
await page.mouse.move(startPX[0], startPX[1])
|
||||||
@ -310,22 +331,93 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drag arcTo interior handle (three point arc)
|
||||||
|
const arcToHandle = await u.getBoundingBox('[data-overlay-index="2"]')
|
||||||
|
await page.mouse.move(arcToHandle.x, arcToHandle.y - 5)
|
||||||
|
await page.mouse.down()
|
||||||
|
await page.mouse.move(
|
||||||
|
arcToHandle.x - dragPX,
|
||||||
|
arcToHandle.y + dragPX,
|
||||||
|
step5
|
||||||
|
)
|
||||||
|
await page.mouse.up()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
if (openPanes.includes('code')) {
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
prevContent = await page.locator('.cm-content').innerText()
|
||||||
|
}
|
||||||
|
|
||||||
|
// drag arcTo end handle (three point arc)
|
||||||
|
const arcToEndHandle = await u.getBoundingBox('[data-overlay-index="3"]')
|
||||||
|
await page.mouse.move(arcToEndHandle.x, arcToEndHandle.y - 5)
|
||||||
|
await page.mouse.down()
|
||||||
|
await page.mouse.move(
|
||||||
|
arcToEndHandle.x - dragPX,
|
||||||
|
arcToEndHandle.y + dragPX,
|
||||||
|
step5
|
||||||
|
)
|
||||||
|
await page.mouse.up()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
if (openPanes.includes('code')) {
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
prevContent = await page.locator('.cm-content').innerText()
|
||||||
|
}
|
||||||
|
|
||||||
|
// drag arc radius handle
|
||||||
|
const arcRadiusHandle = await u.getBoundingBox('[data-overlay-index="4"]')
|
||||||
|
await page.mouse.move(arcRadiusHandle.x, arcRadiusHandle.y - 5)
|
||||||
|
await page.mouse.down()
|
||||||
|
await page.mouse.move(
|
||||||
|
arcRadiusHandle.x - dragPX,
|
||||||
|
arcRadiusHandle.y + dragPX,
|
||||||
|
step5
|
||||||
|
)
|
||||||
|
await page.mouse.up()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
if (openPanes.includes('code')) {
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// drag arc center handle (we'll have to hardcode the position because it doesn't have a overlay near the handle)
|
||||||
|
const arcCenterHandle = { x: 745, y: 214 }
|
||||||
|
await page.mouse.move(arcCenterHandle.x, arcCenterHandle.y - 5)
|
||||||
|
await page.mouse.down()
|
||||||
|
await page.mouse.move(
|
||||||
|
arcCenterHandle.x - dragPX,
|
||||||
|
arcCenterHandle.y + dragPX,
|
||||||
|
step5
|
||||||
|
)
|
||||||
|
await page.mouse.up()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
if (openPanes.includes('code')) {
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
}
|
||||||
|
|
||||||
// Open the code pane
|
// Open the code pane
|
||||||
await u.openKclCodePanel()
|
await u.openKclCodePanel()
|
||||||
|
|
||||||
// expect the code to have changed
|
// expect the code to have changed
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`sketch001 = startSketchOn('XZ')
|
.toHaveText(`sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([6.44, -12.07], %)
|
|> startProfileAt([6.44, -12.07], %)
|
||||||
|> line(end = [14.72, 1.97])
|
|> line(end = [14.72, 1.97])
|
||||||
|> tangentialArcTo([24.95, -5.38], %)
|
|> tangentialArcTo([26.92, -3.32], %)
|
||||||
|> line(end = [1.97, 2.06])
|
|> arcTo({
|
||||||
|> close()`)
|
interior = [18.11, -3.73],
|
||||||
|
end = [9.77, -3.19]
|
||||||
|
}, %)
|
||||||
|
|> arc({
|
||||||
|
radius = 3.75,
|
||||||
|
angleStart = -58.29,
|
||||||
|
angleEnd = 161.17
|
||||||
|
}, %)
|
||||||
|
|> close()
|
||||||
|
`)
|
||||||
}
|
}
|
||||||
test(
|
test(
|
||||||
'code pane open at start-handles',
|
'code pane open at start-handles',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ page, homePage, scene }) => {
|
async ({ page, homePage, scene, cmdBar }) => {
|
||||||
// Load the app with the code panes
|
// Load the app with the code panes
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -338,14 +430,20 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
await doEditSegmentsByDraggingHandle(page, homePage, ['code'], scene)
|
await doEditSegmentsByDraggingHandle(
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
['code'],
|
||||||
|
scene,
|
||||||
|
cmdBar
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'code pane closed at start-handles',
|
'code pane closed at start-handles',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ page, homePage, scene }) => {
|
async ({ page, homePage, scene, cmdBar }) => {
|
||||||
// Load the app with the code panes
|
// Load the app with the code panes
|
||||||
await page.addInitScript(async (persistModelingContext) => {
|
await page.addInitScript(async (persistModelingContext) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -353,7 +451,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
JSON.stringify({ openPanes: [] })
|
JSON.stringify({ openPanes: [] })
|
||||||
)
|
)
|
||||||
}, PERSIST_MODELING_CONTEXT)
|
}, PERSIST_MODELING_CONTEXT)
|
||||||
await doEditSegmentsByDraggingHandle(page, homePage, [], scene)
|
await doEditSegmentsByDraggingHandle(page, homePage, [], scene, cmdBar)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -362,6 +460,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
page,
|
page,
|
||||||
editor,
|
editor,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
@ -373,6 +473,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
})
|
})
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
@ -564,7 +666,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
|> line(end = [12.73, -0.09])
|
|> line(end = [12.73, -0.09])
|
||||||
|> tangentialArcTo([24.95, -5.38], %)
|
|> tangentialArcTo([24.95, -5.38], %)
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = "X",}, %)`
|
|> revolve(axis = "X")`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -651,7 +753,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
|> tangentialArcTo([24.95, -5.38], %)
|
|> tangentialArcTo([24.95, -5.38], %)
|
||||||
|> line(end = [1.97, 2.06])
|
|> line(end = [1.97, 2.06])
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = "X" }, %)`)
|
|> revolve(axis = "X")`)
|
||||||
})
|
})
|
||||||
test('Can add multiple sketches', async ({ page, homePage }) => {
|
test('Can add multiple sketches', async ({ page, homePage }) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
@ -1098,7 +1200,7 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
|
|||||||
|> xLine(endAbsolute = 0 + .001)
|
|> xLine(endAbsolute = 0 + .001)
|
||||||
|> yLine(endAbsolute = 0)
|
|> yLine(endAbsolute = 0)
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = "Y" }, %)
|
|> revolve(axis = "Y")
|
||||||
|
|
||||||
return lugSketch
|
return lugSketch
|
||||||
}
|
}
|
||||||
@ -1174,7 +1276,7 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
|
|||||||
|> line(endAbsolute = [
|
|> line(endAbsolute = [
|
||||||
railWideWidth / 2,
|
railWideWidth / 2,
|
||||||
railClampable / 2 + railBaseLength
|
railClampable / 2 + railBaseLength
|
||||||
], $seg01)
|
], tag = $seg01)
|
||||||
|> line(endAbsolute = [railTop / 2, railBaseLength])
|
|> line(endAbsolute = [railTop / 2, railBaseLength])
|
||||||
|> line(endAbsolute = [railBaseWidth / 2, railBaseLength])
|
|> line(endAbsolute = [railBaseWidth / 2, railBaseLength])
|
||||||
|> line(endAbsolute = [railBaseWidth / 2, 0])
|
|> line(endAbsolute = [railBaseWidth / 2, 0])
|
||||||
@ -1352,10 +1454,10 @@ test.describe(`Sketching with offset planes`, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test.describe('multi-profile sketching', () => {
|
test.describe('multi-profile sketching', () => {
|
||||||
test(
|
test.fixme(
|
||||||
`test it removes half-finished expressions when changing tools in sketch mode`,
|
`test it removes half-finished expressions when changing tools in sketch mode`,
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ context, page, scene, toolbar, editor, homePage }) => {
|
async ({ context, page, scene, toolbar, editor, homePage, cmdBar }) => {
|
||||||
// We seed the scene with a single offset plane
|
// We seed the scene with a single offset plane
|
||||||
await context.addInitScript(() => {
|
await context.addInitScript(() => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -1375,7 +1477,10 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [continueProfile2Clk] = scene.makeMouseHelpers(954, 282)
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
@ -1386,7 +1491,13 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
const [circlePoint1] = scene.makeMouseHelpers(700, 200)
|
const [circlePoint1] = scene.makeMouseHelpers(700, 200)
|
||||||
|
|
||||||
await test.step('equip circle tool and click first point', async () => {
|
await test.step('equip circle tool and click first point', async () => {
|
||||||
await toolbar.circleBtn.click()
|
// await page.waitForTimeout(100)
|
||||||
|
await expect
|
||||||
|
.poll(async () => {
|
||||||
|
await toolbar.circleBtn.click()
|
||||||
|
return toolbar.circleBtn.getAttribute('aria-pressed')
|
||||||
|
})
|
||||||
|
.toBe('true')
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await circlePoint1()
|
await circlePoint1()
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
@ -1401,6 +1512,7 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
|
|
||||||
const [circle3Point1] = scene.makeMouseHelpers(650, 200)
|
const [circle3Point1] = scene.makeMouseHelpers(650, 200)
|
||||||
const [circle3Point2] = scene.makeMouseHelpers(750, 200)
|
const [circle3Point2] = scene.makeMouseHelpers(750, 200)
|
||||||
|
// const [circle3Point3] = scene.makeMouseHelpers(700, 150)
|
||||||
|
|
||||||
await test.step('equip three point circle tool and click first two points', async () => {
|
await test.step('equip three point circle tool and click first two points', async () => {
|
||||||
await toolbar.selectCircleThreePoint()
|
await toolbar.selectCircleThreePoint()
|
||||||
@ -1411,25 +1523,40 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
await editor.expectEditor.toContain('profile003 = circleThreePoint(')
|
await editor.expectEditor.toContain('profile003 = circleThreePoint(')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('equip line tool and verify three point circle code is removed', async () => {
|
await test.step('equip line tool and verify three-point circle code is removed', async () => {
|
||||||
await toolbar.lineBtn.click()
|
await toolbar.lineBtn.click()
|
||||||
await editor.expectEditor.not.toContain(
|
await editor.expectEditor.not.toContain(
|
||||||
'profile003 = circleThreePoint('
|
'profile003 = circleThreePoint('
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await test.step('equip three-point-arc tool and click first two points', async () => {
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
await toolbar.selectThreePointArc()
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
await circle3Point1()
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
await circle3Point2()
|
||||||
|
await editor.expectEditor.toContain('arcTo({')
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('equip line tool and verify three-point-arc code is removed after second click', async () => {
|
||||||
|
await toolbar.lineBtn.click()
|
||||||
|
await editor.expectEditor.not.toContain('arcTo({')
|
||||||
|
})
|
||||||
|
|
||||||
const [cornerRectPoint1] = scene.makeMouseHelpers(600, 300)
|
const [cornerRectPoint1] = scene.makeMouseHelpers(600, 300)
|
||||||
|
|
||||||
await test.step('equip corner rectangle tool and click first point', async () => {
|
await test.step('equip corner rectangle tool and click first point', async () => {
|
||||||
await toolbar.rectangleBtn.click()
|
await toolbar.rectangleBtn.click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await cornerRectPoint1()
|
await cornerRectPoint1()
|
||||||
await editor.expectEditor.toContain('profile003 = startProfileAt(')
|
await editor.expectEditor.toContain('profile004 = startProfileAt(')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('equip line tool and verify corner rectangle code is removed', async () => {
|
await test.step('equip line tool and verify corner rectangle code is removed', async () => {
|
||||||
await toolbar.lineBtn.click()
|
await toolbar.lineBtn.click()
|
||||||
await editor.expectEditor.not.toContain('profile003 = startProfileAt(')
|
await editor.expectEditor.not.toContain('profile004 = startProfileAt(')
|
||||||
})
|
})
|
||||||
|
|
||||||
const [centerRectPoint1] = scene.makeMouseHelpers(700, 300)
|
const [centerRectPoint1] = scene.makeMouseHelpers(700, 300)
|
||||||
@ -1438,12 +1565,24 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
await toolbar.selectCenterRectangle()
|
await toolbar.selectCenterRectangle()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await centerRectPoint1()
|
await centerRectPoint1()
|
||||||
await editor.expectEditor.toContain('profile003 = startProfileAt(')
|
await editor.expectEditor.toContain('profile004 = startProfileAt(')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('equip line tool and verify center rectangle code is removed', async () => {
|
await test.step('equip line tool and verify center rectangle code is removed', async () => {
|
||||||
await toolbar.lineBtn.click()
|
await toolbar.lineBtn.click()
|
||||||
await editor.expectEditor.not.toContain('profile003 = startProfileAt(')
|
await editor.expectEditor.not.toContain('profile004 = startProfileAt(')
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('continue profile002 with the three point arc tool, and then switch back to the line tool to verify it only removes the last expression in the pipe', async () => {
|
||||||
|
await toolbar.selectThreePointArc()
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
await continueProfile2Clk()
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
await circle3Point1()
|
||||||
|
await editor.expectEditor.toContain('arcTo({')
|
||||||
|
await toolbar.lineBtn.click()
|
||||||
|
await editor.expectEditor.not.toContain('arcTo({')
|
||||||
|
await editor.expectEditor.toContain('profile002')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -1532,6 +1671,7 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
}) => {
|
}) => {
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
@ -1595,7 +1735,7 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
// timeout wait for engine animation is unavoidable
|
// timeout wait for engine animation is unavoidable
|
||||||
await page.waitForTimeout(600)
|
await page.waitForTimeout(600)
|
||||||
await editor.expectEditor.toContain(`sketch001 = startSketchOn('XZ')`)
|
await editor.expectEditor.toContain(`sketch001 = startSketchOn('XZ')`)
|
||||||
await test.step('Create a close profile stopping mid profile to equip the tangential arc, and than back to the line tool', async () => {
|
await test.step('Create a close profile stopping mid profile to equip the tangential arc, then three-point arc, and then back to the line tool', async () => {
|
||||||
await startProfile1()
|
await startProfile1()
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
`profile001 = startProfileAt([4.61, 12.21], sketch001)`
|
`profile001 = startProfileAt([4.61, 12.21], sketch001)`
|
||||||
@ -1613,12 +1753,45 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
`|> tangentialArcTo([16.61, 4.14], %)`
|
`|> tangentialArcTo([16.61, 4.14], %)`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Add a three-point arc segment
|
||||||
|
await toolbar.selectThreePointArc()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
|
// select end of profile again
|
||||||
|
await endLineStartTanArc()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
|
// Define points for the three-point arc
|
||||||
|
const [threePointInterior, threePointInteriorMove] =
|
||||||
|
scene.makeMouseHelpers(600, 200)
|
||||||
|
const [threePointEnd, threePointEndMove] = scene.makeMouseHelpers(
|
||||||
|
590,
|
||||||
|
270
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create the three-point arc
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await threePointInteriorMove()
|
||||||
|
await threePointInterior()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await threePointEndMove()
|
||||||
|
await threePointEnd()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
|
// Verify the three-point arc was created correctly
|
||||||
|
await editor.expectEditor.toContain(`|> arcTo(`)
|
||||||
|
|
||||||
|
// Switch back to line tool to continue
|
||||||
await toolbar.lineBtn.click()
|
await toolbar.lineBtn.click()
|
||||||
await page.waitForTimeout(300)
|
await page.waitForTimeout(300)
|
||||||
await endArcStartLine()
|
|
||||||
|
// Continue with the original line segment
|
||||||
|
await threePointEnd()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
await page.mouse.click(572, 110)
|
await page.mouse.click(572, 110)
|
||||||
await editor.expectEditor.toContain(`|> line(end = [-11.73, 5.35])`)
|
await editor.expectEditor.toContain(`|> line(end = [-1.22, 10.85])`)
|
||||||
await startProfile1()
|
await startProfile1()
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
`|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
`|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
@ -1820,8 +1993,68 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('double check that circle three point can be unequiped', async () => {
|
await test.step('create three-point arcs in a row without an unequip', async () => {
|
||||||
// this was tested implicitly for other tools, but not for circle three point since it's last
|
// Define points for the first three-point arc
|
||||||
|
const [arc1Point1, arc1Point1Move] = scene.makeMouseHelpers(700, 397)
|
||||||
|
const [arc1Point2, arc1Point2Move] = scene.makeMouseHelpers(724, 346)
|
||||||
|
const [arc1Point3, arc1Point3Move] = scene.makeMouseHelpers(785, 415)
|
||||||
|
|
||||||
|
// Define points for the second three-point arc
|
||||||
|
const [arc2Point1, arc2Point1Move] = scene.makeMouseHelpers(792, 225)
|
||||||
|
const [arc2Point2, arc2Point2Move] = scene.makeMouseHelpers(820, 207)
|
||||||
|
const [arc2Point3, arc2Point3Move] = scene.makeMouseHelpers(905, 229)
|
||||||
|
|
||||||
|
// Select the three-point arc tool
|
||||||
|
await toolbar.selectThreePointArc()
|
||||||
|
|
||||||
|
// Create the first three-point arc
|
||||||
|
await arc1Point1Move()
|
||||||
|
await arc1Point1()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await arc1Point2Move()
|
||||||
|
await arc1Point2()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await arc1Point3Move()
|
||||||
|
await arc1Point3()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
|
// Verify the first three-point arc was created correctly
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
`profile011 = startProfileAt([13.56, -9.97], sketch001)
|
||||||
|
|> arcTo({
|
||||||
|
interior = [15.19, -6.51],
|
||||||
|
end = [19.33, -11.19]
|
||||||
|
}, %)`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create the second three-point arc
|
||||||
|
await arc2Point1Move()
|
||||||
|
await arc2Point1()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await arc2Point2Move()
|
||||||
|
await arc2Point2()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await arc2Point3Move()
|
||||||
|
await arc2Point3()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
|
// Verify the second three-point arc was created correctly
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
` |> arcTo({
|
||||||
|
interior = [19.8, 1.7],
|
||||||
|
end = [21.7, 2.92]
|
||||||
|
}, %)
|
||||||
|
|> arcTo({
|
||||||
|
interior = [27.47, 1.42],
|
||||||
|
end = [27.57, 1.52]
|
||||||
|
}, %)`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('double check that three-point arc can be unequipped', async () => {
|
||||||
|
// this was tested implicitly for other tools, but not for three-point arc since it's last
|
||||||
await page.waitForTimeout(300)
|
await page.waitForTimeout(300)
|
||||||
await expect
|
await expect
|
||||||
.poll(async () => {
|
.poll(async () => {
|
||||||
@ -2085,7 +2318,7 @@ profile003 = circle(sketch001, center = [6.92, -4.2], radius = 3.16)
|
|||||||
test(
|
test(
|
||||||
'can enter sketch when there is an extrude',
|
'can enter sketch when there is an extrude',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ homePage, scene, toolbar, page }) => {
|
async ({ homePage, scene, toolbar, page, cmdBar }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -2122,6 +2355,8 @@ extrude001 = extrude(profile003, length = 5)
|
|||||||
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
@ -2134,9 +2369,11 @@ extrude001 = extrude(profile003, length = 5)
|
|||||||
await page.waitForTimeout(600)
|
await page.waitForTimeout(600)
|
||||||
|
|
||||||
await test.step('check the sketch is still drawn properly', async () => {
|
await test.step('check the sketch is still drawn properly', async () => {
|
||||||
await scene.expectPixelColor([255, 255, 255], { x: 596, y: 165 }, 15)
|
await Promise.all([
|
||||||
await scene.expectPixelColor([255, 255, 255], { x: 641, y: 220 }, 15)
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 596, y: 165 }, 15),
|
||||||
await scene.expectPixelColor([255, 255, 255], { x: 763, y: 214 }, 15)
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 641, y: 220 }, 15),
|
||||||
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 763, y: 214 }, 15),
|
||||||
|
])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -2293,7 +2530,7 @@ extrude001 = extrude(thePart, length = 75)
|
|||||||
test(
|
test(
|
||||||
'Can enter sketch on sketch of wall and cap for segment, solid2d, extrude-wall, extrude-cap selections',
|
'Can enter sketch on sketch of wall and cap for segment, solid2d, extrude-wall, extrude-cap selections',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ homePage, scene, toolbar, editor, page }) => {
|
async ({ homePage, scene, toolbar, editor, page, cmdBar }) => {
|
||||||
// TODO this test should include a test for selecting revolve walls and caps
|
// TODO this test should include a test for selecting revolve walls and caps
|
||||||
|
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
@ -2333,10 +2570,11 @@ profile006 = startProfileAt([9.65, 3.82], sketch002)
|
|||||||
|> line(end = [2.13, -5.57])
|
|> line(end = [2.13, -5.57])
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
revolve001 = revolve({
|
revolve001 = revolve(
|
||||||
|
profile004,
|
||||||
angle = 45,
|
angle = 45,
|
||||||
axis = getNextAdjacentEdge(seg01)
|
axis = getNextAdjacentEdge(seg01)
|
||||||
}, profile004)
|
)
|
||||||
extrude002 = extrude(profile006, length = 4)
|
extrude002 = extrude(profile006, length = 4)
|
||||||
sketch003 = startSketchOn('-XZ')
|
sketch003 = startSketchOn('-XZ')
|
||||||
profile007 = startProfileAt([4.8, 7.55], sketch003)
|
profile007 = startProfileAt([4.8, 7.55], sketch003)
|
||||||
@ -2371,13 +2609,15 @@ profile011 = startProfileAt([5.07, -6.39], sketch003)
|
|||||||
|> close()
|
|> close()
|
||||||
extrude003 = extrude(profile011, length = 2.5)
|
extrude003 = extrude(profile011, length = 2.5)
|
||||||
// TODO this breaks the test,
|
// TODO this breaks the test,
|
||||||
// revolve002 = revolve({ angle = 45, axis = seg02 }, profile008)
|
// revolve002 = revolve(profile008, angle = 45, axis = seg02)
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
@ -2387,11 +2627,6 @@ extrude003 = extrude(profile011, length = 2.5)
|
|||||||
{ x: 834, y: -680, z: 534 },
|
{ x: 834, y: -680, z: 534 },
|
||||||
{ x: -54, y: -476, z: 148 }
|
{ x: -54, y: -476, z: 148 }
|
||||||
)
|
)
|
||||||
const camPositionForSelectingSketchOnCapProfiles = () =>
|
|
||||||
scene.moveCameraTo(
|
|
||||||
{ x: 404, y: 690, z: 38 },
|
|
||||||
{ x: 16, y: -140, z: -10 }
|
|
||||||
)
|
|
||||||
const wallSelectionOptions = [
|
const wallSelectionOptions = [
|
||||||
{
|
{
|
||||||
title: 'select wall segment',
|
title: 'select wall segment',
|
||||||
@ -2414,103 +2649,25 @@ extrude003 = extrude(profile011, length = 2.5)
|
|||||||
selectClick: scene.makeMouseHelpers(836, 103)[0],
|
selectClick: scene.makeMouseHelpers(836, 103)[0],
|
||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
const capSelectionOptions = [
|
|
||||||
{
|
|
||||||
title: 'select cap segment',
|
|
||||||
selectClick: scene.makeMouseHelpers(688, 91)[0],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'select cap solid 2d',
|
|
||||||
selectClick: scene.makeMouseHelpers(733, 204)[0],
|
|
||||||
},
|
|
||||||
// TODO keeps failing
|
|
||||||
// {
|
|
||||||
// title: 'select cap circle',
|
|
||||||
// selectClick: scene.makeMouseHelpers(679, 290)[0],
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
title: 'select cap extrude wall',
|
|
||||||
selectClick: scene.makeMouseHelpers(649, 402)[0],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'select cap extrude cap',
|
|
||||||
selectClick: scene.makeMouseHelpers(693, 408)[0],
|
|
||||||
},
|
|
||||||
] as const
|
|
||||||
|
|
||||||
const verifyWallProfilesAreDrawn = async () =>
|
const verifyWallProfilesAreDrawn = async () =>
|
||||||
test.step('verify wall profiles are drawn', async () => {
|
test.step('verify wall profiles are drawn', async () => {
|
||||||
// open polygon
|
await Promise.all([
|
||||||
await scene.expectPixelColor(
|
// open polygon
|
||||||
TEST_COLORS.WHITE,
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 599, y: 168 }, 15),
|
||||||
{ x: 599, y: 168 },
|
// closed polygon
|
||||||
15
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 656, y: 171 }, 15),
|
||||||
)
|
// revolved profile
|
||||||
// closed polygon
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 655, y: 264 }, 15),
|
||||||
await scene.expectPixelColor(
|
// extruded profile
|
||||||
TEST_COLORS.WHITE,
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 808, y: 396 }, 15),
|
||||||
{ x: 656, y: 171 },
|
// circle (When entering via the circle, it's selected and therefore blue)
|
||||||
15
|
scene.expectPixelColor(
|
||||||
)
|
[TEST_COLORS.WHITE, TEST_COLORS.BLUE],
|
||||||
// revolved profile
|
{ x: 742, y: 386 },
|
||||||
await scene.expectPixelColor(
|
15
|
||||||
TEST_COLORS.WHITE,
|
),
|
||||||
{ x: 655, y: 264 },
|
])
|
||||||
15
|
|
||||||
)
|
|
||||||
// extruded profile
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
TEST_COLORS.WHITE,
|
|
||||||
{ x: 808, y: 396 },
|
|
||||||
15
|
|
||||||
)
|
|
||||||
// circle
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
[
|
|
||||||
TEST_COLORS.WHITE,
|
|
||||||
TEST_COLORS.BLUE, // When entering via the circle, it's selected and therefore blue
|
|
||||||
],
|
|
||||||
{ x: 742, y: 386 },
|
|
||||||
15
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const verifyCapProfilesAreDrawn = async () =>
|
|
||||||
test.step('verify cap profiles are drawn', async () => {
|
|
||||||
// open polygon
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
TEST_COLORS.WHITE,
|
|
||||||
// TEST_COLORS.BLUE, // When entering via the circle, it's selected and therefore blue
|
|
||||||
{ x: 620, y: 58 },
|
|
||||||
15
|
|
||||||
)
|
|
||||||
// revolved profile
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
TEST_COLORS.WHITE,
|
|
||||||
{ x: 641, y: 110 },
|
|
||||||
15
|
|
||||||
)
|
|
||||||
// closed polygon
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
TEST_COLORS.WHITE,
|
|
||||||
{ x: 632, y: 200 },
|
|
||||||
15
|
|
||||||
)
|
|
||||||
// extruded profile
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
TEST_COLORS.WHITE,
|
|
||||||
{ x: 628, y: 410 },
|
|
||||||
15
|
|
||||||
)
|
|
||||||
// circle
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
[
|
|
||||||
TEST_COLORS.WHITE,
|
|
||||||
TEST_COLORS.BLUE, // When entering via the circle, it's selected and therefore blue
|
|
||||||
],
|
|
||||||
{ x: 681, y: 303 },
|
|
||||||
15
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('select wall profiles', async () => {
|
await test.step('select wall profiles', async () => {
|
||||||
|
@ -7,12 +7,7 @@ import { spawn } from 'child_process'
|
|||||||
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
|
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
|
||||||
import JSZip from 'jszip'
|
import JSZip from 'jszip'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import {
|
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates'
|
||||||
IS_PLAYWRIGHT_KEY,
|
|
||||||
TEST_SETTINGS,
|
|
||||||
TEST_SETTINGS_KEY,
|
|
||||||
} from './storageStates'
|
|
||||||
import * as TOML from '@iarna/toml'
|
|
||||||
import { SceneFixture } from './fixtures/sceneFixture'
|
import { SceneFixture } from './fixtures/sceneFixture'
|
||||||
import { CmdBarFixture } from './fixtures/cmdBarFixture'
|
import { CmdBarFixture } from './fixtures/cmdBarFixture'
|
||||||
|
|
||||||
@ -410,9 +405,9 @@ test.describe(
|
|||||||
test(
|
test(
|
||||||
'Draft segments should look right',
|
'Draft segments should look right',
|
||||||
{ tag: '@snapshot' },
|
{ tag: '@snapshot' },
|
||||||
async ({ page, context, scene, cmdBar }) => {
|
async ({ page, scene, toolbar }) => {
|
||||||
// FIXME: Skip on macos its being weird.
|
// FIXME: Skip on macos its being weird.
|
||||||
test.skip(process.platform === 'darwin', 'Skip on macos')
|
// test.skip(process.platform === 'darwin', 'Skip on macos')
|
||||||
|
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
@ -421,6 +416,23 @@ test(
|
|||||||
|
|
||||||
await scene.connectionEstablished()
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
|
const startXPx = 600
|
||||||
|
const [endOfTangentClk, endOfTangentMv] = scene.makeMouseHelpers(
|
||||||
|
startXPx + PUR * 30,
|
||||||
|
500 - PUR * 20,
|
||||||
|
{ steps: 10 }
|
||||||
|
)
|
||||||
|
const [threePointArcMidPointClk, threePointArcMidPointMv] =
|
||||||
|
scene.makeMouseHelpers(800, 250, { steps: 10 })
|
||||||
|
const [threePointArcEndPointClk, threePointArcEndPointMv] =
|
||||||
|
scene.makeMouseHelpers(750, 285, { steps: 10 })
|
||||||
|
const [arcCenterClk, arcCenterMv] = scene.makeMouseHelpers(750, 210, {
|
||||||
|
steps: 10,
|
||||||
|
})
|
||||||
|
const [arcEndClk, arcEndMv] = scene.makeMouseHelpers(750, 150, {
|
||||||
|
steps: 10,
|
||||||
|
})
|
||||||
|
|
||||||
// click on "Start Sketch" button
|
// click on "Start Sketch" button
|
||||||
await u.doAndWaitForImageDiff(
|
await u.doAndWaitForImageDiff(
|
||||||
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
||||||
@ -435,7 +447,6 @@ test(
|
|||||||
|
|
||||||
await page.waitForTimeout(700) // TODO detect animation ending, or disable animation
|
await page.waitForTimeout(700) // TODO detect animation ending, or disable animation
|
||||||
|
|
||||||
const startXPx = 600
|
|
||||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||||
code += `profile001 = startProfileAt([7.19, -9.7], sketch001)`
|
code += `profile001 = startProfileAt([7.19, -9.7], sketch001)`
|
||||||
await expect(page.locator('.cm-content')).toHaveText(code)
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
||||||
@ -471,12 +482,52 @@ test(
|
|||||||
await page.mouse.move(813, 392, { steps: 10 })
|
await page.mouse.move(813, 392, { steps: 10 })
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
await page.mouse.move(startXPx + PUR * 30, 500 - PUR * 20, { steps: 10 })
|
await endOfTangentMv()
|
||||||
|
|
||||||
await expect(page).toHaveScreenshot({
|
await expect(page).toHaveScreenshot({
|
||||||
maxDiffPixels: 100,
|
maxDiffPixels: 100,
|
||||||
mask: [page.getByTestId('model-state-indicator')],
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
})
|
})
|
||||||
|
await endOfTangentClk()
|
||||||
|
|
||||||
|
await toolbar.selectThreePointArc()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
await endOfTangentClk()
|
||||||
|
await threePointArcMidPointMv()
|
||||||
|
await expect(page).toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
|
})
|
||||||
|
await threePointArcMidPointClk()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
|
await threePointArcEndPointMv()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
await expect(page).toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
|
})
|
||||||
|
|
||||||
|
await threePointArcEndPointClk()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
|
await toolbar.selectArc()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
|
// continue the profile
|
||||||
|
await threePointArcEndPointClk()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await arcCenterMv()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
await arcCenterClk()
|
||||||
|
|
||||||
|
await arcEndMv()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
await expect(page).toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
|
})
|
||||||
|
await arcEndClk()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"original_source_code": "sketch001 = startSketchOn('XZ')\nprofile001 = startProfileAt([57.81, 250.51], sketch001)\n |> line(end = [121.13, 56.63], tag = $seg02)\n |> line(end = [83.37, -34.61], tag = $seg01)\n |> line(end = [19.66, -116.4])\n |> line(end = [-221.8, -41.69])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude001 = extrude(profile001, length = 200)\nsketch002 = startSketchOn('XZ')\n |> startProfileAt([-73.64, -42.89], %)\n |> xLine(length = 173.71)\n |> line(end = [-22.12, -94.4])\n |> xLine(length = -156.98)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude002 = extrude(sketch002, length = 50)\nsketch003 = startSketchOn('XY')\n |> startProfileAt([52.92, 157.81], %)\n |> angledLine([0, 176.4], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 53.4\n ], %, $rectangleSegmentB001)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %, $rectangleSegmentC001)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude003 = extrude(sketch003, length = 20)\n",
|
||||||
|
"prompt": "make this neon green please, use #39FF14",
|
||||||
|
"source_ranges": [
|
||||||
|
{
|
||||||
|
"prompt": "The users main selection is the end cap of a general-sweep (that is an extrusion, revolve, sweep or loft).\nThe source range most likely refers to \"startProfileAt\" simply because this is the start of the profile that was swept.\nIf you need to operate on this cap, for example for sketching on the face, you can use the special string END i.e. `startSketchOn(someSweepVariable, END)`\nWhen they made this selection they main have intended this surface directly or meant something more general like the sweep body.\nSee later source ranges for more context.",
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 11,
|
||||||
|
"column": 5
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 11,
|
||||||
|
"column": 40
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"prompt": "This is the sweep's source range from the user's main selection of the end cap.",
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 17,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 17,
|
||||||
|
"column": 44
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kcl_version": "0.2.51"
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
import { MouseControlType } from '@rust/kcl-lib/bindings/MouseControlType'
|
|
||||||
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
||||||
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
|
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
|
||||||
import { Themes } from 'lib/theme'
|
import { Themes } from 'lib/theme'
|
||||||
@ -143,10 +142,10 @@ sketch001 = startSketchOn(box, revolveAxis)
|
|||||||
|> line(end = [2, 0])
|
|> line(end = [2, 0])
|
||||||
|> line(end = [0, -10])
|
|> line(end = [0, -10])
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({
|
|> revolve(
|
||||||
axis: revolveAxis,
|
axis = revolveAxis,
|
||||||
angle: 90
|
angle = 90
|
||||||
}, %)
|
)
|
||||||
|
|
||||||
sketch001 = startSketchOn('XZ')
|
sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([0.0, 0.0], %)
|
|> startProfileAt([0.0, 0.0], %)
|
||||||
|
@ -3,7 +3,7 @@ import { commonPoints, getUtils } from './test-utils'
|
|||||||
import { EngineCommand } from 'lang/std/artifactGraph'
|
import { EngineCommand } from 'lang/std/artifactGraph'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
|
|
||||||
test.describe('Test network and connection issues', () => {
|
test.fixme('Test network and connection issues', () => {
|
||||||
test(
|
test(
|
||||||
'simulate network down and network little widget',
|
'simulate network down and network little widget',
|
||||||
{ tag: '@skipLocalEngine' },
|
{ tag: '@skipLocalEngine' },
|
||||||
|
@ -2,15 +2,12 @@ import {
|
|||||||
expect,
|
expect,
|
||||||
BrowserContext,
|
BrowserContext,
|
||||||
TestInfo,
|
TestInfo,
|
||||||
_electron as electron,
|
|
||||||
ElectronApplication,
|
|
||||||
Locator,
|
Locator,
|
||||||
Page,
|
Page,
|
||||||
} from '@playwright/test'
|
} from '@playwright/test'
|
||||||
import { test } from './zoo-test'
|
import { test } from './zoo-test'
|
||||||
import { EngineCommand } from 'lang/std/artifactGraph'
|
import { EngineCommand } from 'lang/std/artifactGraph'
|
||||||
import fsp from 'fs/promises'
|
import fsp from 'fs/promises'
|
||||||
import fsSync from 'fs'
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import pixelMatch from 'pixelmatch'
|
import pixelMatch from 'pixelmatch'
|
||||||
import { PNG } from 'pngjs'
|
import { PNG } from 'pngjs'
|
||||||
@ -24,14 +21,11 @@ import {
|
|||||||
IS_PLAYWRIGHT_KEY,
|
IS_PLAYWRIGHT_KEY,
|
||||||
} from './storageStates'
|
} from './storageStates'
|
||||||
import * as TOML from '@iarna/toml'
|
import * as TOML from '@iarna/toml'
|
||||||
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
|
|
||||||
import { SETTINGS_FILE_NAME } from 'lib/constants'
|
|
||||||
import { isErrorWhitelisted } from './lib/console-error-whitelist'
|
import { isErrorWhitelisted } from './lib/console-error-whitelist'
|
||||||
import { isArray } from 'lib/utils'
|
import { isArray } from 'lib/utils'
|
||||||
import { reportRejection } from 'lib/trap'
|
import { reportRejection } from 'lib/trap'
|
||||||
import { DeepPartial } from 'lib/types'
|
import { DeepPartial } from 'lib/types'
|
||||||
import { Configuration } from 'lang/wasm'
|
import { Configuration } from 'lang/wasm'
|
||||||
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
|
||||||
|
|
||||||
const toNormalizedCode = (text: string) => {
|
const toNormalizedCode = (text: string) => {
|
||||||
return text.replace(/\s+/g, '')
|
return text.replace(/\s+/g, '')
|
||||||
@ -928,10 +922,6 @@ export async function setup(
|
|||||||
// await page.reload()
|
// await page.reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
let electronApp: ElectronApplication | undefined = undefined
|
|
||||||
let context: BrowserContext | undefined = undefined
|
|
||||||
let page: Page | undefined = undefined
|
|
||||||
|
|
||||||
function failOnConsoleErrors(page: Page, testInfo?: TestInfo) {
|
function failOnConsoleErrors(page: Page, testInfo?: TestInfo) {
|
||||||
// enabled for chrome for now
|
// enabled for chrome for now
|
||||||
if (page.context().browser()?.browserType().name() === 'chromium') {
|
if (page.context().browser()?.browserType().name() === 'chromium') {
|
||||||
|
@ -4,7 +4,6 @@ import { bracket } from 'lib/exampleKcl'
|
|||||||
import * as fsp from 'fs/promises'
|
import * as fsp from 'fs/promises'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { FILE_EXT } from 'lib/constants'
|
import { FILE_EXT } from 'lib/constants'
|
||||||
import { UnitLength_type } from '@kittycad/lib/dist/types/src/models'
|
|
||||||
|
|
||||||
test.describe('Testing in-app sample loading', () => {
|
test.describe('Testing in-app sample loading', () => {
|
||||||
/**
|
/**
|
||||||
@ -49,8 +48,6 @@ test.describe('Testing in-app sample loading', () => {
|
|||||||
})
|
})
|
||||||
const warningText = page.getByText('Overwrite current file and units?')
|
const warningText = page.getByText('Overwrite current file and units?')
|
||||||
const confirmButton = page.getByRole('button', { name: 'Submit command' })
|
const confirmButton = page.getByRole('button', { name: 'Submit command' })
|
||||||
const unitsToast = (unit: UnitLength_type) =>
|
|
||||||
page.getByText(`Set default unit to "${unit}" for this project`)
|
|
||||||
|
|
||||||
await test.step(`Precondition: check the initial code`, async () => {
|
await test.step(`Precondition: check the initial code`, async () => {
|
||||||
await u.openKclCodePanel()
|
await u.openKclCodePanel()
|
||||||
@ -125,8 +122,6 @@ test.describe('Testing in-app sample loading', () => {
|
|||||||
page.getByRole('listitem').filter({
|
page.getByRole('listitem').filter({
|
||||||
has: page.getByRole('button', { name }),
|
has: page.getByRole('button', { name }),
|
||||||
})
|
})
|
||||||
const unitsToast = (unit: UnitLength_type) =>
|
|
||||||
page.getByText(`Set default unit to "${unit}" for this project`)
|
|
||||||
|
|
||||||
await test.step(`Test setup`, async () => {
|
await test.step(`Test setup`, async () => {
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
@ -159,7 +159,6 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
const unconstrainedLocator = page.locator(
|
const unconstrainedLocator = page.locator(
|
||||||
`[data-constraint-type="${constraintType}"][data-is-constrained="false"]`
|
`[data-constraint-type="${constraintType}"][data-is-constrained="false"]`
|
||||||
)
|
)
|
||||||
await expect(unconstrainedLocator).toBeVisible()
|
|
||||||
await unconstrainedLocator.hover()
|
await unconstrainedLocator.hover()
|
||||||
await expect(
|
await expect(
|
||||||
await page.getByTestId('constraint-symbol-popover').count()
|
await page.getByTestId('constraint-symbol-popover').count()
|
||||||
@ -274,8 +273,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
|
|
||||||
let ang = 0
|
let ang = 0
|
||||||
|
|
||||||
const line = await u.getBoundingBox(`[data-overlay-index="${0}"]`)
|
const line = await u.getBoundingBox('[data-overlay-index="0"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="${0}"]`)
|
ang = await u.getAngle('[data-overlay-index="0"]')
|
||||||
console.log('line1', line, ang)
|
console.log('line1', line, ang)
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: line.x, y: line.y },
|
hoverPos: { x: line.x, y: line.y },
|
||||||
@ -297,8 +296,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
locator: '[data-overlay-index="0"]',
|
locator: '[data-overlay-index="0"]',
|
||||||
})
|
})
|
||||||
|
|
||||||
const angledLine = await u.getBoundingBox(`[data-overlay-index="1"]`)
|
const angledLine = await u.getBoundingBox('[data-overlay-index="1"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="1"]`)
|
ang = await u.getAngle('[data-overlay-index="1"]')
|
||||||
console.log('angledLine1')
|
console.log('angledLine1')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: angledLine.x, y: angledLine.y },
|
hoverPos: { x: angledLine.x, y: angledLine.y },
|
||||||
@ -327,8 +326,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.mouse.move(700, 250)
|
await page.mouse.move(700, 250)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
let lineTo = await u.getBoundingBox(`[data-overlay-index="2"]`)
|
let lineTo = await u.getBoundingBox('[data-overlay-index="2"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="2"]`)
|
ang = await u.getAngle('[data-overlay-index="2"]')
|
||||||
console.log('lineTo1')
|
console.log('lineTo1')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: lineTo.x, y: lineTo.y },
|
hoverPos: { x: lineTo.x, y: lineTo.y },
|
||||||
@ -353,8 +352,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
locator: '[data-overlay-toolbar-index="2"]',
|
locator: '[data-overlay-toolbar-index="2"]',
|
||||||
})
|
})
|
||||||
|
|
||||||
const xLineTo = await u.getBoundingBox(`[data-overlay-index="3"]`)
|
const xLineTo = await u.getBoundingBox('[data-overlay-index="3"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="3"]`)
|
ang = await u.getAngle('[data-overlay-index="3"]')
|
||||||
console.log('xlineTo1')
|
console.log('xlineTo1')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: xLineTo.x, y: xLineTo.y },
|
hoverPos: { x: xLineTo.x, y: xLineTo.y },
|
||||||
@ -419,8 +418,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
|
|
||||||
let ang = 0
|
let ang = 0
|
||||||
|
|
||||||
const yLineTo = await u.getBoundingBox(`[data-overlay-index="4"]`)
|
const yLineTo = await u.getBoundingBox('[data-overlay-index="4"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="4"]`)
|
ang = await u.getAngle('[data-overlay-index="4"]')
|
||||||
console.log('ylineTo1')
|
console.log('ylineTo1')
|
||||||
await clickUnconstrained({
|
await clickUnconstrained({
|
||||||
hoverPos: { x: yLineTo.x, y: yLineTo.y - 200 },
|
hoverPos: { x: yLineTo.x, y: yLineTo.y - 200 },
|
||||||
@ -432,8 +431,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
locator: '[data-overlay-toolbar-index="4"]',
|
locator: '[data-overlay-toolbar-index="4"]',
|
||||||
})
|
})
|
||||||
|
|
||||||
const xLine = await u.getBoundingBox(`[data-overlay-index="5"]`)
|
const xLine = await u.getBoundingBox('[data-overlay-index="5"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="5"]`)
|
ang = await u.getAngle('[data-overlay-index="5"]')
|
||||||
console.log('xline')
|
console.log('xline')
|
||||||
await clickUnconstrained({
|
await clickUnconstrained({
|
||||||
hoverPos: { x: xLine.x, y: xLine.y },
|
hoverPos: { x: xLine.x, y: xLine.y },
|
||||||
@ -501,8 +500,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
|
|
||||||
let ang = 0
|
let ang = 0
|
||||||
|
|
||||||
const yLine = await u.getBoundingBox(`[data-overlay-index="6"]`)
|
const yLine = await u.getBoundingBox('[data-overlay-index="6"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="6"]`)
|
ang = await u.getAngle('[data-overlay-index="6"]')
|
||||||
console.log('yline1')
|
console.log('yline1')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: yLine.x, y: yLine.y },
|
hoverPos: { x: yLine.x, y: yLine.y },
|
||||||
@ -515,9 +514,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const angledLineOfXLength = await u.getBoundingBox(
|
const angledLineOfXLength = await u.getBoundingBox(
|
||||||
`[data-overlay-index="7"]`
|
'[data-overlay-index="7"]'
|
||||||
)
|
)
|
||||||
ang = await u.getAngle(`[data-overlay-index="7"]`)
|
ang = await u.getAngle('[data-overlay-index="7"]')
|
||||||
console.log('angledLineOfXLength1')
|
console.log('angledLineOfXLength1')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: angledLineOfXLength.x, y: angledLineOfXLength.y },
|
hoverPos: { x: angledLineOfXLength.x, y: angledLineOfXLength.y },
|
||||||
@ -547,9 +546,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const angledLineOfYLength = await u.getBoundingBox(
|
const angledLineOfYLength = await u.getBoundingBox(
|
||||||
`[data-overlay-index="8"]`
|
'[data-overlay-index="8"]'
|
||||||
)
|
)
|
||||||
ang = await u.getAngle(`[data-overlay-index="8"]`)
|
ang = await u.getAngle('[data-overlay-index="8"]')
|
||||||
console.log('angledLineOfYLength1')
|
console.log('angledLineOfYLength1')
|
||||||
await clickUnconstrained({
|
await clickUnconstrained({
|
||||||
hoverPos: { x: angledLineOfYLength.x, y: angledLineOfYLength.y },
|
hoverPos: { x: angledLineOfYLength.x, y: angledLineOfYLength.y },
|
||||||
@ -632,8 +631,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
|
|
||||||
let ang = 0
|
let ang = 0
|
||||||
|
|
||||||
const angledLineToX = await u.getBoundingBox(`[data-overlay-index="9"]`)
|
const angledLineToX = await u.getBoundingBox('[data-overlay-index="9"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="9"]`)
|
ang = await u.getAngle('[data-overlay-index="9"]')
|
||||||
console.log('angledLineToX')
|
console.log('angledLineToX')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: angledLineToX.x, y: angledLineToX.y },
|
hoverPos: { x: angledLineToX.x, y: angledLineToX.y },
|
||||||
@ -659,9 +658,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const angledLineToY = await u.getBoundingBox(
|
const angledLineToY = await u.getBoundingBox(
|
||||||
`[data-overlay-index="10"]`
|
'[data-overlay-index="10"]'
|
||||||
)
|
)
|
||||||
ang = await u.getAngle(`[data-overlay-index="10"]`)
|
ang = await u.getAngle('[data-overlay-index="10"]')
|
||||||
console.log('angledLineToY')
|
console.log('angledLineToY')
|
||||||
await clickUnconstrained({
|
await clickUnconstrained({
|
||||||
hoverPos: { x: angledLineToY.x, y: angledLineToY.y },
|
hoverPos: { x: angledLineToY.x, y: angledLineToY.y },
|
||||||
@ -689,9 +688,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const angledLineThatIntersects = await u.getBoundingBox(
|
const angledLineThatIntersects = await u.getBoundingBox(
|
||||||
`[data-overlay-index="11"]`
|
'[data-overlay-index="11"]'
|
||||||
)
|
)
|
||||||
ang = await u.getAngle(`[data-overlay-index="11"]`)
|
ang = await u.getAngle('[data-overlay-index="11"]')
|
||||||
console.log('angledLineThatIntersects')
|
console.log('angledLineThatIntersects')
|
||||||
await clickUnconstrained({
|
await clickUnconstrained({
|
||||||
hoverPos: {
|
hoverPos: {
|
||||||
@ -821,6 +820,138 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
locator: '[data-overlay-toolbar-index="12"]',
|
locator: '[data-overlay-toolbar-index="12"]',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
test('for segment [arcTo]', async ({
|
||||||
|
page,
|
||||||
|
editor,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`sketch001 = startSketchOn('XZ')
|
||||||
|
profile001 = startProfileAt([56.37, 120.33], sketch001)
|
||||||
|
|> line(end = [162.86, 106.48])
|
||||||
|
|> arcTo({
|
||||||
|
interior = [360.16, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)
|
||||||
|
|> yLine(-131.54, %)
|
||||||
|
|> arc({
|
||||||
|
radius = 126.46,
|
||||||
|
angleStart = 33.53,
|
||||||
|
angleEnd = -141.07
|
||||||
|
}, %)
|
||||||
|
`
|
||||||
|
)
|
||||||
|
localStorage.setItem('disableAxis', 'true')
|
||||||
|
})
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
// wait for execution done
|
||||||
|
|
||||||
|
await page.getByText('line(end = [162.86, 106.48])').click()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
|
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
|
||||||
|
|
||||||
|
const clickUnconstrained = _clickUnconstrained(page, editor)
|
||||||
|
const clickConstrained = _clickConstrained(page, editor)
|
||||||
|
|
||||||
|
const arcTo = await u.getBoundingBox('[data-overlay-index="1"]')
|
||||||
|
let ang = await u.getAngle('[data-overlay-index="1"]')
|
||||||
|
console.log('arcTo interior x')
|
||||||
|
await clickUnconstrained({
|
||||||
|
hoverPos: { x: arcTo.x, y: arcTo.y },
|
||||||
|
constraintType: 'xAbsolute',
|
||||||
|
expectBeforeUnconstrained: `arcTo({
|
||||||
|
interior = [360.16, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectAfterUnconstrained: `arcTo({
|
||||||
|
interior = [360.16, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectFinal: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
ang: ang,
|
||||||
|
steps: 6,
|
||||||
|
locator: '[data-overlay-toolbar-index="1"]',
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('arcTo interior y')
|
||||||
|
await clickUnconstrained({
|
||||||
|
hoverPos: { x: arcTo.x, y: arcTo.y },
|
||||||
|
constraintType: 'yAbsolute',
|
||||||
|
expectBeforeUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectAfterUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, yAbs001],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectFinal: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
ang: ang,
|
||||||
|
steps: 10,
|
||||||
|
locator: '[data-overlay-toolbar-index="1"]',
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('arcTo end x')
|
||||||
|
await clickConstrained({
|
||||||
|
hoverPos: { x: arcTo.x, y: arcTo.y },
|
||||||
|
constraintType: 'xAbsolute',
|
||||||
|
expectBeforeUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectAfterUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectFinal: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [xAbs002, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
ang: ang + 180,
|
||||||
|
steps: 6,
|
||||||
|
locator: '[data-overlay-toolbar-index="1"]',
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('arcTo end y')
|
||||||
|
await clickUnconstrained({
|
||||||
|
hoverPos: { x: arcTo.x, y: arcTo.y },
|
||||||
|
constraintType: 'yAbsolute',
|
||||||
|
expectBeforeUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [xAbs002, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectAfterUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [xAbs002, yAbs002]
|
||||||
|
}, %)`,
|
||||||
|
expectFinal: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [xAbs002, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
ang: ang + 180,
|
||||||
|
steps: 10,
|
||||||
|
locator: '[data-overlay-toolbar-index="1"]',
|
||||||
|
})
|
||||||
|
})
|
||||||
test('for segment [circle]', async ({ page, editor, homePage }) => {
|
test('for segment [circle]', async ({ page, editor, homePage }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -928,36 +1059,55 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
shouldNormalise: true,
|
shouldNormalise: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
await page.locator(`[data-stdlib-fn-name="${stdLibFnName}"]`).click()
|
await page
|
||||||
|
.locator(`[data-stdlib-fn-name="${stdLibFnName}"]`)
|
||||||
|
.first()
|
||||||
|
.click()
|
||||||
await page.getByText('Delete Segment').click()
|
await page.getByText('Delete Segment').click()
|
||||||
|
|
||||||
await editor.expectEditor.not.toContain(codeToBeDeleted, {
|
await editor.expectEditor.not.toContain(codeToBeDeleted, {
|
||||||
shouldNormalise: true,
|
shouldNormalise: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
test('all segment types', async ({ page, editor, homePage }) => {
|
test('all segment types', async ({
|
||||||
|
page,
|
||||||
|
editor,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn('XZ')
|
`part001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|>startProfileAt([0, 0], %)
|
||||||
|> line(end = [0.5, -14 + 0])
|
|> line(end = [0.5, -14 + 0])
|
||||||
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
|
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
|
||||||
|> line(endAbsolute = [33, 11.5 + 0])
|
|> line(endAbsolute = [33, 11.5 + 0])
|
||||||
|> xLine(endAbsolute = 9 - 5)
|
|> xLine(endAbsolute = 9 - 5)
|
||||||
|> yLine(endAbsolute = -10.77, tag = $a)
|
|> yLine(endAbsolute = -10.77, tag = $a)
|
||||||
|> xLine(length = 26.04)
|
|> xLine(length = 26.04)
|
||||||
|> yLine(length = 21.14 + 0)
|
|> yLine(length = 21.14 + 0)
|
||||||
|> angledLineOfXLength({ angle = 181 + 0, length = 23.14 }, %)
|
|> angledLineOfXLength({ angle = 181 + 0, length = 23.14 }, %)
|
||||||
|> angledLineOfYLength({ angle = -91, length = 19 + 0 }, %)
|
|> angledLineOfYLength({ angle = -91, length = 19 + 0 }, %)
|
||||||
|> angledLineToX({ angle = 3 + 0, to = 26 }, %)
|
|> angledLineToX({ angle = 3 + 0, to = 26 }, %)
|
||||||
|> angledLineToY({ angle = 89, to = 9.14 + 0 }, %)
|
|> angledLineToY({ angle = 89, to = 9.14 + 0 }, %)
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle = 4.14,
|
angle = 4.14,
|
||||||
intersectTag = a,
|
intersectTag = a,
|
||||||
offset = 9
|
offset = 9
|
||||||
}, %)
|
}, %)
|
||||||
|> tangentialArcTo([3.14 + 13, 1.14], %)
|
|> tangentialArcTo([3.14 + 13, 1.14], %)
|
||||||
|
|> arcTo({
|
||||||
|
interior = [16.25, 5.12],
|
||||||
|
end = [21.61, 4.15]
|
||||||
|
}, %)
|
||||||
|
|> arc({
|
||||||
|
radius = 9.03,
|
||||||
|
angleStart = 40.27,
|
||||||
|
angleEnd = -38.05
|
||||||
|
}, %)
|
||||||
|
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
localStorage.setItem('disableAxis', 'true')
|
localStorage.setItem('disableAxis', 'true')
|
||||||
@ -966,27 +1116,55 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
// wait for execution done
|
|
||||||
await u.openDebugPanel()
|
|
||||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
|
||||||
await u.closeDebugPanel()
|
|
||||||
|
|
||||||
await page.getByText('xLine(endAbsolute = 9 - 5)').click()
|
await page.getByText('xLine(endAbsolute = 9 - 5)').click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
await expect(page.getByTestId('segment-overlay')).toHaveCount(13)
|
await expect(page.getByTestId('segment-overlay')).toHaveCount(16)
|
||||||
const deleteSegmentSequence = _deleteSegmentSequence(page, editor)
|
const deleteSegmentSequence = _deleteSegmentSequence(page, editor)
|
||||||
|
|
||||||
let segmentToDelete
|
let segmentToDelete
|
||||||
|
|
||||||
const getOverlayByIndex = (index: number) =>
|
const getOverlayByIndex = (index: number) =>
|
||||||
u.getBoundingBox(`[data-overlay-index="${index}"]`)
|
u.getBoundingBox(`[data-overlay-index="${index}"]`)
|
||||||
|
|
||||||
|
segmentToDelete = await getOverlayByIndex(14)
|
||||||
|
let ang = await u.getAngle('[data-overlay-index="14"]')
|
||||||
|
|
||||||
|
await editor.scrollToText('angleEnd')
|
||||||
|
|
||||||
|
await deleteSegmentSequence({
|
||||||
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
|
codeToBeDeleted: `arc({
|
||||||
|
radius = 9.03,
|
||||||
|
angleStart = 40.27,
|
||||||
|
angleEnd = -38.05
|
||||||
|
}, %)`,
|
||||||
|
stdLibFnName: 'arc',
|
||||||
|
ang: ang + 180,
|
||||||
|
steps: 6,
|
||||||
|
locator: '[data-overlay-toolbar-index="14"]',
|
||||||
|
})
|
||||||
|
segmentToDelete = await getOverlayByIndex(13)
|
||||||
|
ang = await u.getAngle('[data-overlay-index="13"]')
|
||||||
|
await deleteSegmentSequence({
|
||||||
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
|
codeToBeDeleted: `arcTo({
|
||||||
|
interior = [16.25, 5.12],
|
||||||
|
end = [21.61, 4.15]
|
||||||
|
}, %)`,
|
||||||
|
stdLibFnName: 'arcTo',
|
||||||
|
ang: ang,
|
||||||
|
steps: 6,
|
||||||
|
locator: '[data-overlay-toolbar-index="13"]',
|
||||||
|
})
|
||||||
segmentToDelete = await getOverlayByIndex(12)
|
segmentToDelete = await getOverlayByIndex(12)
|
||||||
let ang = await u.getAngle(`[data-overlay-index="${12}"]`)
|
ang = await u.getAngle('[data-overlay-index="12"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'tangentialArcTo([3.14 + 13, 1.14], %)',
|
codeToBeDeleted: 'tangentialArcTo([3.14 + 13, 1.14], %)',
|
||||||
@ -997,7 +1175,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(11)
|
segmentToDelete = await getOverlayByIndex(11)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${11}"]`)
|
ang = await u.getAngle('[data-overlay-index="11"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: `angledLineThatIntersects({
|
codeToBeDeleted: `angledLineThatIntersects({
|
||||||
@ -1012,7 +1190,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(10)
|
segmentToDelete = await getOverlayByIndex(10)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${10}"]`)
|
ang = await u.getAngle('[data-overlay-index="10"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'angledLineToY({ angle = 89, to = 9.14 + 0 }, %)',
|
codeToBeDeleted: 'angledLineToY({ angle = 89, to = 9.14 + 0 }, %)',
|
||||||
@ -1022,7 +1200,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(9)
|
segmentToDelete = await getOverlayByIndex(9)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${9}"]`)
|
ang = await u.getAngle('[data-overlay-index="9"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'angledLineToX({ angle = 3 + 0, to = 26 }, %)',
|
codeToBeDeleted: 'angledLineToX({ angle = 3 + 0, to = 26 }, %)',
|
||||||
@ -1032,7 +1210,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(8)
|
segmentToDelete = await getOverlayByIndex(8)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${8}"]`)
|
ang = await u.getAngle('[data-overlay-index="8"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted:
|
codeToBeDeleted:
|
||||||
@ -1043,7 +1221,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(7)
|
segmentToDelete = await getOverlayByIndex(7)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${7}"]`)
|
ang = await u.getAngle('[data-overlay-index="7"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted:
|
codeToBeDeleted:
|
||||||
@ -1054,7 +1232,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(6)
|
segmentToDelete = await getOverlayByIndex(6)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${6}"]`)
|
ang = await u.getAngle('[data-overlay-index="6"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'yLine(length = 21.14 + 0)',
|
codeToBeDeleted: 'yLine(length = 21.14 + 0)',
|
||||||
@ -1064,7 +1242,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(5)
|
segmentToDelete = await getOverlayByIndex(5)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${5}"]`)
|
ang = await u.getAngle('[data-overlay-index="5"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'xLine(length = 26.04)',
|
codeToBeDeleted: 'xLine(length = 26.04)',
|
||||||
@ -1074,7 +1252,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(4)
|
segmentToDelete = await getOverlayByIndex(4)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${4}"]`)
|
ang = await u.getAngle('[data-overlay-index="4"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'yLine(endAbsolute = -10.77, tag = $a)',
|
codeToBeDeleted: 'yLine(endAbsolute = -10.77, tag = $a)',
|
||||||
@ -1084,7 +1262,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(3)
|
segmentToDelete = await getOverlayByIndex(3)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${3}"]`)
|
ang = await u.getAngle('[data-overlay-index="3"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'xLine(endAbsolute = 9 - 5)',
|
codeToBeDeleted: 'xLine(endAbsolute = 9 - 5)',
|
||||||
@ -1094,7 +1272,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(2)
|
segmentToDelete = await getOverlayByIndex(2)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${2}"]`)
|
ang = await u.getAngle('[data-overlay-index="2"]')
|
||||||
await expect(page.getByText('Added variable')).not.toBeVisible()
|
await expect(page.getByText('Added variable')).not.toBeVisible()
|
||||||
|
|
||||||
const hoverPos = { x: segmentToDelete.x, y: segmentToDelete.y }
|
const hoverPos = { x: segmentToDelete.x, y: segmentToDelete.y }
|
||||||
@ -1127,7 +1305,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(1)
|
segmentToDelete = await getOverlayByIndex(1)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${1}"]`)
|
ang = await u.getAngle('[data-overlay-index="1"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'angledLine({ angle = 3 + 0, length = 32 + 0 }, %)',
|
codeToBeDeleted: 'angledLine({ angle = 3 + 0, length = 32 + 0 }, %)',
|
||||||
@ -1137,7 +1315,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(0)
|
segmentToDelete = await getOverlayByIndex(0)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${0}"]`)
|
ang = await u.getAngle('[data-overlay-index="0"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'line(end = [0.5, -14 + 0])',
|
codeToBeDeleted: 'line(end = [0.5, -14 + 0])',
|
||||||
@ -1208,7 +1386,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
page.getByRole('button', { name: 'Edit Sketch' })
|
page.getByRole('button', { name: 'Edit Sketch' })
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
return true
|
return true
|
||||||
} catch (_) {
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
} catch (_e) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -1366,7 +1545,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await expect(page.getByText('Added variable')).not.toBeVisible()
|
await expect(page.getByText('Added variable')).not.toBeVisible()
|
||||||
|
|
||||||
const hoverPos = await u.getBoundingBox(`[data-overlay-index="0"]`)
|
const hoverPos = await u.getBoundingBox(`[data-overlay-index="0"]`)
|
||||||
let ang = await u.getAngle(`[data-overlay-index="${0}"]`)
|
let ang = await u.getAngle('[data-overlay-index="0"]')
|
||||||
ang += 180
|
ang += 180
|
||||||
|
|
||||||
await page.mouse.move(0, 0)
|
await page.mouse.move(0, 0)
|
||||||
|
@ -323,7 +323,7 @@ part009 = startSketchOn('XY')
|
|||||||
|> line(end = [0, pipeLength])
|
|> line(end = [0, pipeLength])
|
||||||
|> angledLineToX({ angle = 60, to = pipeLargeDia }, %)
|
|> angledLineToX({ angle = 60, to = pipeLargeDia }, %)
|
||||||
|> close()
|
|> close()
|
||||||
rev = revolve({ axis = 'y' }, part009)
|
rev = revolve(part009, axis = 'y')
|
||||||
sketch006 = startSketchOn('XY')
|
sketch006 = startSketchOn('XY')
|
||||||
profile001 = circle(
|
profile001 = circle(
|
||||||
sketch006,
|
sketch006,
|
||||||
@ -364,7 +364,6 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
|||||||
await camPosition1()
|
await camPosition1()
|
||||||
|
|
||||||
const revolve = { x: 635, y: 253 }
|
const revolve = { x: 635, y: 253 }
|
||||||
const parentExtrude = { x: 915, y: 133 }
|
|
||||||
const solid2d = { x: 770, y: 167 }
|
const solid2d = { x: 770, y: 167 }
|
||||||
const individualProfile = { x: 694, y: 432 }
|
const individualProfile = { x: 694, y: 432 }
|
||||||
|
|
||||||
@ -380,7 +379,7 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
|||||||
await page.waitForTimeout(200)
|
await page.waitForTimeout(200)
|
||||||
|
|
||||||
await expect(u.codeLocator).not.toContainText(
|
await expect(u.codeLocator).not.toContainText(
|
||||||
`rev = revolve({ axis: 'y' }, part009)`
|
`rev = revolve(part009, axis: 'y')`
|
||||||
)
|
)
|
||||||
|
|
||||||
// FIXME (commented section below), this test would select a wall that had a sketch on it, and delete the underlying extrude
|
// FIXME (commented section below), this test would select a wall that had a sketch on it, and delete the underlying extrude
|
||||||
@ -452,19 +451,15 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
|||||||
await page.waitForTimeout(200)
|
await page.waitForTimeout(200)
|
||||||
await expect(u.codeLocator).not.toContainText(codeToBeDeletedSnippet)
|
await expect(u.codeLocator).not.toContainText(codeToBeDeletedSnippet)
|
||||||
})
|
})
|
||||||
test('parent Solid should be select and deletable and uses custom planes to position children', async ({
|
test.fixme(
|
||||||
page,
|
'parent Solid should be select and deletable and uses custom planes to position children',
|
||||||
homePage,
|
async ({ page, homePage, scene, cmdBar, editor }) => {
|
||||||
scene,
|
test.setTimeout(90_000)
|
||||||
cmdBar,
|
const u = await getUtils(page)
|
||||||
editor,
|
await page.addInitScript(async () => {
|
||||||
}) => {
|
localStorage.setItem(
|
||||||
test.setTimeout(90_000)
|
'persistCode',
|
||||||
const u = await getUtils(page)
|
`part001 = startSketchOn('XY')
|
||||||
await page.addInitScript(async () => {
|
|
||||||
localStorage.setItem(
|
|
||||||
'persistCode',
|
|
||||||
`part001 = startSketchOn('XY')
|
|
||||||
yo = startProfileAt([4.83, 12.56], part001)
|
yo = startProfileAt([4.83, 12.56], part001)
|
||||||
|> line(end = [15.1, 2.48])
|
|> line(end = [15.1, 2.48])
|
||||||
|> line(end = [3.15, -9.85], tag = $seg01)
|
|> line(end = [3.15, -9.85], tag = $seg01)
|
||||||
@ -495,34 +490,35 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
|
|||||||
|> close()
|
|> close()
|
||||||
|
|
||||||
`
|
`
|
||||||
|
)
|
||||||
|
}, KCL_DEFAULT_LENGTH)
|
||||||
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
|
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])'
|
||||||
)
|
)
|
||||||
}, KCL_DEFAULT_LENGTH)
|
await u.openAndClearDebugPanel()
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.keyboard.press('Delete')
|
||||||
|
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await editor.expectEditor.not.toContain(`yoo = extrude(yo, length = 4)`, {
|
||||||
await scene.settled(cmdBar)
|
shouldNormalise: true,
|
||||||
|
})
|
||||||
const extrudeWall = { x: 575, y: 238 }
|
await editor.expectEditor.toContain(`startSketchOn({plane={origin`, {
|
||||||
|
shouldNormalise: true,
|
||||||
// DELETE with selection on face of parent
|
})
|
||||||
await page.mouse.click(extrudeWall.x, extrudeWall.y)
|
await editor.snapshot()
|
||||||
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 ({
|
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
createProject,
|
createProject,
|
||||||
tomlToSettings,
|
tomlToSettings,
|
||||||
} from './test-utils'
|
} from './test-utils'
|
||||||
import { SaveSettingsPayload, SettingsLevel } from 'lib/settings/settingsTypes'
|
import { SettingsLevel } from 'lib/settings/settingsTypes'
|
||||||
import { SETTINGS_FILE_NAME, PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
|
import { SETTINGS_FILE_NAME, PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
|
||||||
import {
|
import {
|
||||||
TEST_SETTINGS_KEY,
|
TEST_SETTINGS_KEY,
|
||||||
@ -15,7 +15,6 @@ import {
|
|||||||
TEST_SETTINGS,
|
TEST_SETTINGS,
|
||||||
TEST_SETTINGS_DEFAULT_THEME,
|
TEST_SETTINGS_DEFAULT_THEME,
|
||||||
} from './storageStates'
|
} from './storageStates'
|
||||||
import * as TOML from '@iarna/toml'
|
|
||||||
import { DeepPartial } from 'lib/types'
|
import { DeepPartial } from 'lib/types'
|
||||||
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
||||||
|
|
||||||
@ -978,72 +977,63 @@ fn cube`
|
|||||||
/**
|
/**
|
||||||
* This test assumes that the default value of the "highlight edges" setting is "on".
|
* This test assumes that the default value of the "highlight edges" setting is "on".
|
||||||
*/
|
*/
|
||||||
test(`Toggle stream settings multiple times`, async ({
|
test.fixme(
|
||||||
page,
|
`Toggle stream settings multiple times`,
|
||||||
scene,
|
async ({ page, scene, homePage, context, toolbar, cmdBar }, testInfo) => {
|
||||||
homePage,
|
await context.folderSetupFn(async (dir) => {
|
||||||
context,
|
const projectDir = join(dir, 'project-000')
|
||||||
toolbar,
|
await fsp.mkdir(projectDir, { recursive: true })
|
||||||
cmdBar,
|
await fsp.copyFile(
|
||||||
}, testInfo) => {
|
executorInputPath('cube.kcl'),
|
||||||
await context.folderSetupFn(async (dir) => {
|
join(projectDir, 'main.kcl')
|
||||||
const projectDir = join(dir, 'project-000')
|
)
|
||||||
await fsp.mkdir(projectDir, { recursive: true })
|
})
|
||||||
await fsp.copyFile(
|
|
||||||
executorInputPath('cube.kcl'),
|
await test.step(`First snapshot`, async () => {
|
||||||
join(projectDir, 'main.kcl')
|
await homePage.openProject('project-000')
|
||||||
|
await toolbar.closePane('code')
|
||||||
|
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 })
|
||||||
|
await scene.clickNoWhere()
|
||||||
|
})
|
||||||
|
|
||||||
|
const toast = (value: boolean) =>
|
||||||
|
page.getByText(
|
||||||
|
`Set highlight edges to "${String(value)}" as a user default`
|
||||||
|
)
|
||||||
|
|
||||||
|
await test.step(`Toggle highlightEdges off`, async () => {
|
||||||
|
await cmdBar.openCmdBar()
|
||||||
|
await cmdBar.chooseCommand('Settings · modeling · highlight edges')
|
||||||
|
await cmdBar.selectOption({ name: 'off' }).click()
|
||||||
|
const falseToast = toast(false)
|
||||||
|
await expect(falseToast).toBeVisible()
|
||||||
|
await falseToast.waitFor({ state: 'detached' })
|
||||||
|
})
|
||||||
|
|
||||||
|
await expect(scene.streamWrapper).not.toHaveScreenshot(
|
||||||
|
'toggle-settings-initial.png',
|
||||||
|
{
|
||||||
|
maxDiffPixels: 15,
|
||||||
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
|
}
|
||||||
)
|
)
|
||||||
})
|
|
||||||
|
|
||||||
await test.step(`First snapshot`, async () => {
|
await test.step(`Toggle highlightEdges on`, async () => {
|
||||||
await homePage.openProject('project-000')
|
await cmdBar.openCmdBar()
|
||||||
await toolbar.closePane('code')
|
await cmdBar.chooseCommand('Settings · modeling · highlight edges')
|
||||||
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 })
|
await cmdBar.selectOption({ name: 'on' }).click()
|
||||||
await scene.clickNoWhere()
|
const trueToast = toast(true)
|
||||||
})
|
await expect(trueToast).toBeVisible()
|
||||||
|
await trueToast.waitFor({ state: 'detached' })
|
||||||
|
})
|
||||||
|
|
||||||
const toast = (value: boolean) =>
|
await expect(scene.streamWrapper).toHaveScreenshot(
|
||||||
page.getByText(
|
'toggle-settings-initial.png',
|
||||||
`Set highlight edges to "${String(value)}" as a user default`
|
{
|
||||||
|
maxDiffPixels: 15,
|
||||||
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
|
}
|
||||||
)
|
)
|
||||||
const initialPath = testInfo.snapshotPath('toggle-settings-initial.png')
|
}
|
||||||
const initialScreenshot = await scene.streamWrapper.screenshot({
|
)
|
||||||
path: initialPath,
|
|
||||||
mask: [page.getByTestId('model-state-indicator')],
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step(`Toggle highlightEdges off`, async () => {
|
|
||||||
await cmdBar.openCmdBar()
|
|
||||||
await cmdBar.chooseCommand('Settings · modeling · highlight edges')
|
|
||||||
await cmdBar.selectOption({ name: 'off' }).click()
|
|
||||||
const falseToast = toast(false)
|
|
||||||
await expect(falseToast).toBeVisible()
|
|
||||||
await falseToast.waitFor({ state: 'detached' })
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(scene.streamWrapper).not.toHaveScreenshot(
|
|
||||||
'toggle-settings-initial.png',
|
|
||||||
{
|
|
||||||
maxDiffPixels: 15,
|
|
||||||
mask: [page.getByTestId('model-state-indicator')],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
await test.step(`Toggle highlightEdges on`, async () => {
|
|
||||||
await cmdBar.openCmdBar()
|
|
||||||
await cmdBar.chooseCommand('Settings · modeling · highlight edges')
|
|
||||||
await cmdBar.selectOption({ name: 'on' }).click()
|
|
||||||
const trueToast = toast(true)
|
|
||||||
await expect(trueToast).toBeVisible()
|
|
||||||
await trueToast.waitFor({ state: 'detached' })
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(scene.streamWrapper).toHaveScreenshot(
|
|
||||||
'toggle-settings-initial.png',
|
|
||||||
{
|
|
||||||
maxDiffPixels: 15,
|
|
||||||
mask: [page.getByTestId('model-state-indicator')],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
@ -619,7 +619,7 @@ async function sendPromptFromCommandBar(page: Page, promptStr: string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test(
|
test.fixme(
|
||||||
'Text-to-CAD functionality',
|
'Text-to-CAD functionality',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable react-hooks/rules-of-hooks */
|
/* eslint-disable react-hooks/rules-of-hooks */
|
||||||
|
|
||||||
import { test as playwrightTestFn, ElectronApplication } from '@playwright/test'
|
import { test as playwrightTestFn } from '@playwright/test'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
fixturesBasedOnProcessEnvPlatform,
|
fixturesBasedOnProcessEnvPlatform,
|
||||||
@ -8,8 +8,6 @@ import {
|
|||||||
ElectronZoo,
|
ElectronZoo,
|
||||||
} from './fixtures/fixtureSetup'
|
} from './fixtures/fixtureSetup'
|
||||||
|
|
||||||
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
|
||||||
import { DeepPartial } from 'lib/types'
|
|
||||||
export { expect } from '@playwright/test'
|
export { expect } from '@playwright/test'
|
||||||
|
|
||||||
declare module '@playwright/test' {
|
declare module '@playwright/test' {
|
||||||
|
56
package.json
@ -12,17 +12,17 @@
|
|||||||
"main": ".vite/build/main.js",
|
"main": ".vite/build/main.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.17.0",
|
"@codemirror/autocomplete": "^6.18.6",
|
||||||
"@codemirror/commands": "^6.8.0",
|
"@codemirror/commands": "^6.8.0",
|
||||||
"@codemirror/language": "^6.10.8",
|
"@codemirror/language": "^6.11.0",
|
||||||
"@codemirror/lint": "^6.8.4",
|
"@codemirror/lint": "^6.8.4",
|
||||||
"@codemirror/search": "^6.5.10",
|
"@codemirror/search": "^6.5.10",
|
||||||
"@codemirror/state": "^6.4.1",
|
"@codemirror/state": "^6.4.1",
|
||||||
"@codemirror/theme-one-dark": "^6.1.2",
|
"@codemirror/theme-one-dark": "^6.1.2",
|
||||||
"@csstools/postcss-oklab-function": "^4.0.7",
|
"@csstools/postcss-oklab-function": "^4.0.7",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@headlessui/react": "^1.7.19",
|
"@headlessui/react": "^1.7.19",
|
||||||
"@headlessui/tailwindcss": "^0.2.0",
|
"@headlessui/tailwindcss": "^0.2.0",
|
||||||
@ -35,35 +35,36 @@
|
|||||||
"@tweenjs/tween.js": "^23.1.1",
|
"@tweenjs/tween.js": "^23.1.1",
|
||||||
"@xstate/inspect": "^0.8.0",
|
"@xstate/inspect": "^0.8.0",
|
||||||
"@xstate/react": "^4.1.1",
|
"@xstate/react": "^4.1.1",
|
||||||
"bonjour-service": "^1.2.1",
|
"bonjour-service": "^1.3.0",
|
||||||
|
"bson": "^6.10.3",
|
||||||
"chokidar": "^4.0.1",
|
"chokidar": "^4.0.1",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"decamelize": "^6.0.0",
|
"decamelize": "^6.0.0",
|
||||||
"diff": "^7.0.0",
|
"diff": "^7.0.0",
|
||||||
"electron-updater": "^6.6.0",
|
"electron-updater": "^6.6.0",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.1.0",
|
||||||
"html2canvas-pro": "^1.5.8",
|
"html2canvas-pro": "^1.5.8",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"json-rpc-2.0": "^1.6.0",
|
"json-rpc-2.0": "^1.6.0",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"minimist": "^1.2.8",
|
"minimist": "^1.2.8",
|
||||||
"openid-client": "^5.6.5",
|
"openid-client": "^5.6.5",
|
||||||
"re-resizable": "^6.9.11",
|
"re-resizable": "^6.11.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hot-toast": "^2.4.1",
|
"react-hot-toast": "^2.5.2",
|
||||||
"react-hotkeys-hook": "^4.6.1",
|
"react-hotkeys-hook": "^4.6.1",
|
||||||
"react-json-view": "^1.21.3",
|
"react-json-view": "^1.21.3",
|
||||||
"react-modal": "^3.16.3",
|
"react-modal": "^3.16.3",
|
||||||
"react-modal-promise": "^1.0.2",
|
"react-modal-promise": "^1.0.2",
|
||||||
"react-router-dom": "^6.28.0",
|
"react-router-dom": "^6.28.0",
|
||||||
"sketch-helpers": "^0.0.4",
|
"sketch-helpers": "^0.0.4",
|
||||||
"three": "^0.172.0",
|
"three": "^0.174.0",
|
||||||
"ua-parser-js": "^1.0.37",
|
"ua-parser-js": "^1.0.37",
|
||||||
"uuid": "^11.0.2",
|
"uuid": "^11.1.0",
|
||||||
"vscode-jsonrpc": "^8.2.1",
|
"vscode-jsonrpc": "^8.2.1",
|
||||||
"vscode-languageserver-protocol": "^3.17.5",
|
"vscode-languageserver-protocol": "^3.17.5",
|
||||||
"vscode-uri": "^3.0.8",
|
"vscode-uri": "^3.1.0",
|
||||||
"web-vitals": "^3.5.2",
|
"web-vitals": "^3.5.2",
|
||||||
"xstate": "^5.19.2",
|
"xstate": "^5.19.2",
|
||||||
"yargs": "^17.7.2"
|
"yargs": "^17.7.2"
|
||||||
@ -71,7 +72,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"install:rust": "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none && source \"$HOME/.cargo/env\" && (cd rust && (rustup show active-toolchain || rustup toolchain install))",
|
"install:rust": "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none && source \"$HOME/.cargo/env\" && (cd rust && (rustup show active-toolchain || rustup toolchain install))",
|
||||||
"install:rust:windows": "winget install Microsoft.VisualStudio.2022.Community --silent --override \"--wait --quiet --add ProductLang En-us --add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended\" && winget install Rustlang.Rustup",
|
"install:rust:windows": "winget install Microsoft.VisualStudio.2022.Community --silent --override \"--wait --quiet --add ProductLang En-us --add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended\" && winget install Rustlang.Rustup",
|
||||||
"install:wasm-pack:sh": ". $HOME/.cargo/env && curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -y",
|
"install:wasm-pack:sh": ". $HOME/.cargo/env && curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f",
|
||||||
"install:wasm-pack:cargo": "cargo install wasm-pack",
|
"install:wasm-pack:cargo": "cargo install wasm-pack",
|
||||||
"install:tools:windows": "winget install jqlang.jq MikeFarah.yq GitHub.cli",
|
"install:tools:windows": "winget install jqlang.jq MikeFarah.yq GitHub.cli",
|
||||||
"start": "vite --port=3000 --host=0.0.0.0",
|
"start": "vite --port=3000 --host=0.0.0.0",
|
||||||
@ -93,11 +94,9 @@
|
|||||||
"fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1",
|
"fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1",
|
||||||
"fetch:samples": "rm -rf public/kcl-samples* && curl -L -o public/kcl-samples.zip https://github.com/KittyCAD/kcl-samples/archive/refs/heads/achalmers/kw-args-xylineto.zip && unzip -o public/kcl-samples.zip -d public && mv public/kcl-samples-* public/kcl-samples",
|
"fetch:samples": "rm -rf public/kcl-samples* && curl -L -o public/kcl-samples.zip https://github.com/KittyCAD/kcl-samples/archive/refs/heads/achalmers/kw-args-xylineto.zip && unzip -o public/kcl-samples.zip -d public && mv public/kcl-samples-* public/kcl-samples",
|
||||||
"build:wasm-dev": "yarn wasm-prep && (cd rust && wasm-pack build kcl-wasm-lib --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && yarn isomorphic-copy-wasm && yarn fmt",
|
"build:wasm-dev": "yarn wasm-prep && (cd rust && wasm-pack build kcl-wasm-lib --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && yarn isomorphic-copy-wasm && yarn fmt",
|
||||||
"build:wasm:nocopy": "yarn wasm-prep && cd rust && RUSTFLAGS='--cfg getrandom_backend=\"wasm_js\"' wasm-pack build kcl-wasm-lib --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings",
|
"build:wasm": "./scripts/build-wasm.sh",
|
||||||
"build:wasm": "yarn build:wasm:nocopy && cp rust/kcl-wasm-lib/pkg/kcl_wasm_lib_bg.wasm public && yarn fmt",
|
"build:wasm:windows": "./scripts/build-wasm.ps1",
|
||||||
"build:wasm:windows": "yarn install:wasm-pack:cargo && yarn build:wasm:nocopy && ./scripts/copy-wasm.ps1 && yarn fmt",
|
|
||||||
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
||||||
"wasm-prep": "rimraf rust/kcl-wasm-lib/pkg && mkdirp rust/kcl-wasm-lib/pkg && rimraf rust/kcl-lib/bindings",
|
|
||||||
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
|
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
|
||||||
"lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
|
"lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
|
||||||
"files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
|
"files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
|
||||||
@ -153,16 +152,16 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"@babel/preset-env": "^7.25.4",
|
"@babel/preset-env": "^7.26.9",
|
||||||
"@electron-forge/cli": "^7.6.1",
|
"@electron-forge/cli": "^7.7.0",
|
||||||
"@electron-forge/plugin-fuses": "^7.6.1",
|
"@electron-forge/plugin-fuses": "^7.7.0",
|
||||||
"@electron-forge/plugin-vite": "^7.6.1",
|
"@electron-forge/plugin-vite": "^7.7.0",
|
||||||
"@electron/fuses": "^1.8.0",
|
"@electron/fuses": "^1.8.0",
|
||||||
"@electron/notarize": "^2.5.0",
|
"@electron/notarize": "^2.5.0",
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@lezer/generator": "^1.7.2",
|
"@lezer/generator": "^1.7.2",
|
||||||
"@nabla/vite-plugin-eslint": "^2.0.5",
|
"@nabla/vite-plugin-eslint": "^2.0.5",
|
||||||
"@playwright/test": "^1.49.0",
|
"@playwright/test": "^1.51.0",
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
"@testing-library/react": "^15.0.2",
|
"@testing-library/react": "^15.0.2",
|
||||||
"@types/diff": "^7.0.1",
|
"@types/diff": "^7.0.1",
|
||||||
@ -176,7 +175,7 @@
|
|||||||
"@types/react": "^18.3.4",
|
"@types/react": "^18.3.4",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@types/react-modal": "^3.16.3",
|
"@types/react-modal": "^3.16.3",
|
||||||
"@types/three": "^0.172.0",
|
"@types/three": "^0.174.0",
|
||||||
"@types/ua-parser-js": "^0.7.39",
|
"@types/ua-parser-js": "^0.7.39",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"@types/wicg-file-system-access": "^2023.10.5",
|
"@types/wicg-file-system-access": "^2023.10.5",
|
||||||
@ -189,11 +188,11 @@
|
|||||||
"electron-builder": "^26.0.6",
|
"electron-builder": "^26.0.6",
|
||||||
"eslint": "^8.0.1",
|
"eslint": "^8.0.1",
|
||||||
"eslint-plugin-css-modules": "^2.12.0",
|
"eslint-plugin-css-modules": "^2.12.0",
|
||||||
"eslint-plugin-import": "^2.30.0",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-jest": "^28.10.0",
|
"eslint-plugin-jest": "^28.11.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||||
"eslint-plugin-react": "^7.37.4",
|
"eslint-plugin-react": "^7.37.4",
|
||||||
"eslint-plugin-react-hooks": "^5.1.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"eslint-plugin-react-perf": "^3.3.3",
|
"eslint-plugin-react-perf": "^3.3.3",
|
||||||
"eslint-plugin-suggest-no-throw": "^1.0.0",
|
"eslint-plugin-suggest-no-throw": "^1.0.0",
|
||||||
"eslint-plugin-testing-library": "^7.1.1",
|
"eslint-plugin-testing-library": "^7.1.1",
|
||||||
@ -210,10 +209,11 @@
|
|||||||
"setimmediate": "^1.0.5",
|
"setimmediate": "^1.0.5",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"ts-node": "^10.0.0",
|
"ts-node": "^10.0.0",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.8.2",
|
||||||
"typescript-eslint": "^8.23.0",
|
"typescript-eslint": "^8.26.1",
|
||||||
"vite": "^5.4.12",
|
"vite": "^5.4.12",
|
||||||
"vite-plugin-package-version": "^1.1.0",
|
"vite-plugin-package-version": "^1.1.0",
|
||||||
|
"vite-plugin-top-level-await": "^1.5.0",
|
||||||
"vite-tsconfig-paths": "^4.3.2",
|
"vite-tsconfig-paths": "^4.3.2",
|
||||||
"vitest": "^1.6.1",
|
"vitest": "^1.6.1",
|
||||||
"vitest-webgl-canvas-mock": "^1.1.0",
|
"vitest-webgl-canvas-mock": "^1.1.0",
|
||||||
|
@ -19,14 +19,14 @@
|
|||||||
"private": false,
|
"private": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "6.18.6",
|
"@codemirror/autocomplete": "6.18.6",
|
||||||
"@codemirror/language": "^6.10.2",
|
"@codemirror/language": "^6.11.0",
|
||||||
"@codemirror/state": "^6.4.1",
|
"@codemirror/state": "^6.5.2",
|
||||||
"@lezer/highlight": "^1.2.0",
|
"@lezer/highlight": "^1.2.0",
|
||||||
"@ts-stack/markdown": "^1.5.0",
|
"@ts-stack/markdown": "^1.5.0",
|
||||||
"json-rpc-2.0": "^1.7.0",
|
"json-rpc-2.0": "^1.7.0",
|
||||||
"typescript": "^5.7.2",
|
"typescript": "^5.8.2",
|
||||||
"vscode-languageserver-protocol": "^3.17.5",
|
"vscode-languageserver-protocol": "^3.17.5",
|
||||||
"vscode-uri": "^3.0.8"
|
"vscode-uri": "^3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.13.9",
|
"@types/node": "^22.13.9",
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
"@codemirror/view" "^6.17.0"
|
"@codemirror/view" "^6.17.0"
|
||||||
"@lezer/common" "^1.0.0"
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
"@codemirror/language@^6.0.0", "@codemirror/language@^6.10.2":
|
"@codemirror/language@^6.0.0", "@codemirror/language@^6.11.0":
|
||||||
version "6.10.2"
|
version "6.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.10.2.tgz#4056dc219619627ffe995832eeb09cea6060be61"
|
resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.11.0.tgz#5ae90972601497f4575f30811519d720bf7232c9"
|
||||||
integrity sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==
|
integrity sha512-A7+f++LodNNc1wGgoRDTt78cOwWm9KVezApgjOMp1W4hM0898nsqBXwF+sbePE7ZRcjN7Sa1Z5m2oN27XkmEjQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@codemirror/state" "^6.0.0"
|
"@codemirror/state" "^6.0.0"
|
||||||
"@codemirror/view" "^6.23.0"
|
"@codemirror/view" "^6.23.0"
|
||||||
@ -24,10 +24,12 @@
|
|||||||
"@lezer/lr" "^1.0.0"
|
"@lezer/lr" "^1.0.0"
|
||||||
style-mod "^4.0.0"
|
style-mod "^4.0.0"
|
||||||
|
|
||||||
"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.4.1":
|
"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.5.2":
|
||||||
version "6.4.1"
|
version "6.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.4.1.tgz#da57143695c056d9a3c38705ed34136e2b68171b"
|
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6"
|
||||||
integrity sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==
|
integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==
|
||||||
|
dependencies:
|
||||||
|
"@marijn/find-cluster-break" "^1.0.0"
|
||||||
|
|
||||||
"@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0":
|
"@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0":
|
||||||
version "6.28.2"
|
version "6.28.2"
|
||||||
@ -82,6 +84,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@lezer/common" "^1.0.0"
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
|
"@marijn/find-cluster-break@^1.0.0":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8"
|
||||||
|
integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==
|
||||||
|
|
||||||
"@ts-stack/markdown@^1.5.0":
|
"@ts-stack/markdown@^1.5.0":
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@ts-stack/markdown/-/markdown-1.5.0.tgz#5dc298a20dc3dc040143c5a5948201eb6bf5419d"
|
resolved "https://registry.yarnpkg.com/@ts-stack/markdown/-/markdown-1.5.0.tgz#5dc298a20dc3dc040143c5a5948201eb6bf5419d"
|
||||||
@ -182,10 +189,10 @@ tslib@^2.3.0:
|
|||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
|
||||||
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
||||||
|
|
||||||
typescript@^5.7.2:
|
typescript@^5.8.2:
|
||||||
version "5.7.2"
|
version "5.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4"
|
||||||
integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
|
integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==
|
||||||
|
|
||||||
undici-types@~6.20.0:
|
undici-types@~6.20.0:
|
||||||
version "6.20.0"
|
version "6.20.0"
|
||||||
@ -215,10 +222,10 @@ vscode-languageserver-types@3.17.5:
|
|||||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a"
|
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a"
|
||||||
integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==
|
integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==
|
||||||
|
|
||||||
vscode-uri@^3.0.8:
|
vscode-uri@^3.1.0:
|
||||||
version "3.0.8"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f"
|
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c"
|
||||||
integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==
|
integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==
|
||||||
|
|
||||||
w3c-keyname@^2.2.4:
|
w3c-keyname@^2.2.4:
|
||||||
version "2.2.8"
|
version "2.2.8"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { defineConfig, devices } from '@playwright/test'
|
import { defineConfig, devices } from '@playwright/test'
|
||||||
|
import { platform } from 'os'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See https://playwright.dev/docs/test-configuration.
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
@ -13,7 +14,7 @@ export default defineConfig({
|
|||||||
/* Do not retry */
|
/* Do not retry */
|
||||||
retries: 0,
|
retries: 0,
|
||||||
/* Different amount of parallelism on CI and local. */
|
/* Different amount of parallelism on CI and local. */
|
||||||
workers: 8,
|
workers: platform() === 'win32' ? 1 : 2,
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
reporter: [
|
reporter: [
|
||||||
['dot'],
|
['dot'],
|
||||||
|
@ -41,7 +41,7 @@ ballsSketch = startSketchOn("XY")
|
|||||||
|> close()
|
|> close()
|
||||||
|
|
||||||
// Revolve the ball to make a sphere and pattern around the inside wall
|
// Revolve the ball to make a sphere and pattern around the inside wall
|
||||||
balls = revolve({ axis = "X" }, ballsSketch)
|
balls = revolve(ballsSketch, axis = "X")
|
||||||
|> patternCircular3d(
|
|> patternCircular3d(
|
||||||
arcDegrees = 360,
|
arcDegrees = 360,
|
||||||
axis = [0, 0, 1],
|
axis = [0, 0, 1],
|
||||||
@ -66,7 +66,7 @@ chainSketch = startSketchOn("XY")
|
|||||||
|> close()
|
|> close()
|
||||||
|
|
||||||
// Revolve the chain sketch
|
// Revolve the chain sketch
|
||||||
chainHead = revolve({ axis = "X" }, chainSketch)
|
chainHead = revolve(chainSketch, axis = "X")
|
||||||
|> patternCircular3d(
|
|> patternCircular3d(
|
||||||
arcDegrees = 360,
|
arcDegrees = 360,
|
||||||
axis = [0, 0, 1],
|
axis = [0, 0, 1],
|
||||||
@ -86,7 +86,7 @@ linkSketch = startSketchOn("XZ")
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Revolve the link sketch
|
// Revolve the link sketch
|
||||||
linkRevolve = revolve({ axis = 'Y', angle = 360 / nBalls }, linkSketch)
|
linkRevolve = revolve(linkSketch, axis = 'Y', angle = 360 / nBalls)
|
||||||
|> patternCircular3d(
|
|> patternCircular3d(
|
||||||
arcDegrees = 360,
|
arcDegrees = 360,
|
||||||
axis = [0, 0, 1],
|
axis = [0, 0, 1],
|
||||||
|
@ -82,5 +82,5 @@ brakeCaliperSketch = startSketchOn('XY')
|
|||||||
|> close()
|
|> close()
|
||||||
|
|
||||||
// Revolve the brake caliper sketch
|
// Revolve the brake caliper sketch
|
||||||
revolve({ axis = "Y", angle = -70 }, brakeCaliperSketch)
|
revolve(brakeCaliperSketch, axis = "Y", angle = -70)
|
||||||
|> appearance(color = "#c82d2d", metalness = 90, roughness = 90)
|
|> appearance(color = "#c82d2d", metalness = 90, roughness = 90)
|
||||||
|
@ -40,5 +40,5 @@ tireSketch = startSketchOn("XY")
|
|||||||
|> close()
|
|> close()
|
||||||
|
|
||||||
// Revolve the sketch to create the tire
|
// Revolve the sketch to create the tire
|
||||||
revolve({ axis = "Y" }, tireSketch)
|
revolve(tireSketch, axis = "Y")
|
||||||
|> appearance(color = "#0f0f0f", roughness = 80)
|
|> appearance(color = "#0f0f0f", roughness = 80)
|
||||||
|
@ -74,7 +74,7 @@ wheelCenterInner = startSketchOn('XY')
|
|||||||
|> yLine(endAbsolute = 0)
|
|> yLine(endAbsolute = 0)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = 'y' }, %)
|
|> revolve(axis = 'y')
|
||||||
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
||||||
|
|
||||||
wheelCenterOuter = startSketchOn('XY')
|
wheelCenterOuter = startSketchOn('XY')
|
||||||
@ -88,7 +88,7 @@ wheelCenterOuter = startSketchOn('XY')
|
|||||||
|> yLine(endAbsolute = -wheelWidth / 20)
|
|> yLine(endAbsolute = -wheelWidth / 20)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = 'y' }, %)
|
|> revolve(axis = 'y')
|
||||||
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
||||||
|
|
||||||
// Write a function that defines the spoke geometry, patterns and extrudes it
|
// Write a function that defines the spoke geometry, patterns and extrudes it
|
||||||
@ -193,5 +193,5 @@ startSketchOn('XY')
|
|||||||
|> xLine(length = wheelWidth * 0.03)
|
|> xLine(length = wheelWidth * 0.03)
|
||||||
|> yLine(length = wheelWidth * 0.05)
|
|> yLine(length = wheelWidth * 0.05)
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = 'y' }, %)
|
|> revolve(axis = 'y')
|
||||||
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
|
||||||
|
@ -34,7 +34,7 @@ fn lug(plane, length, diameter) {
|
|||||||
|> xLine(endAbsolute = lugThreadDiameter)
|
|> xLine(endAbsolute = lugThreadDiameter)
|
||||||
|> yLine(endAbsolute = 0)
|
|> yLine(endAbsolute = 0)
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = "Y" }, %)
|
|> revolve(axis = "Y")
|
||||||
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
||||||
return lugSketch
|
return lugSketch
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// Set units
|
// Set units
|
||||||
@settings(defaultLengthUnit = in)
|
@settings(defaultLengthUnit = in)
|
||||||
|
|
||||||
import 'car-wheel.kcl' as carWheel
|
import 'car-wheel.kcl' as carWheel
|
||||||
import 'car-rotor.kcl' as carRotor
|
import 'car-rotor.kcl' as carRotor
|
||||||
import "brake-caliper.kcl" as brakeCaliper
|
import "brake-caliper.kcl" as brakeCaliper
|
||||||
import 'lug-nut.kcl' as lugNut
|
import 'lug-nut.kcl' as lugNut
|
||||||
|
@ -23,7 +23,7 @@ sketch001 = startSketchOn('XZ')
|
|||||||
], %, $rectangleSegmentC001)
|
], %, $rectangleSegmentC001)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ angle = 360, axis = 'Y' }, %)
|
|> revolve(angle = 360, axis = 'Y')
|
||||||
|
|
||||||
// Create an angled plane to sketch the supports
|
// Create an angled plane to sketch the supports
|
||||||
plane001 = {
|
plane001 = {
|
||||||
@ -135,7 +135,7 @@ sketch005 = startSketchOn('XZ')
|
|||||||
|> xLine(endAbsolute = 0.15)
|
|> xLine(endAbsolute = 0.15)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = 'y' }, %)
|
|> revolve(axis = 'y')
|
||||||
|
|
||||||
// Plunger and stem
|
// Plunger and stem
|
||||||
sketch006 = startSketchOn('XZ')
|
sketch006 = startSketchOn('XZ')
|
||||||
@ -148,7 +148,7 @@ sketch006 = startSketchOn('XZ')
|
|||||||
|> tangentialArc({ radius = 0.6, offset = -90 }, %)
|
|> tangentialArc({ radius = 0.6, offset = -90 }, %)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = 'y' }, %)
|
|> revolve(axis = 'y')
|
||||||
|
|
||||||
// Spiral plate
|
// Spiral plate
|
||||||
sketch007 = startSketchOn(offsetPlane('XY', offset = 1.12))
|
sketch007 = startSketchOn(offsetPlane('XY', offset = 1.12))
|
||||||
@ -210,7 +210,7 @@ sketch011 = startSketchOn('XZ')
|
|||||||
}, %)
|
}, %)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = 'y' }, %)
|
|> revolve(axis = 'y')
|
||||||
|
|
||||||
// Draw and extrude handle
|
// Draw and extrude handle
|
||||||
sketch012 = startSketchOn(offsetPlane('XZ', offset = handleThickness / 2))
|
sketch012 = startSketchOn(offsetPlane('XZ', offset = handleThickness / 2))
|
||||||
|
@ -55,7 +55,7 @@ axis000 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create a single corner of the bin
|
// create a single corner of the bin
|
||||||
singleCorner = revolve({ angle = -90, axis = axis000 }, face(offsetPlane("YZ", offset = cornerRadius)))
|
singleCorner = revolve(face(offsetPlane("YZ", offset = cornerRadius)), angle = -90, axis = axis000)
|
||||||
|
|
||||||
// create the corners of the bin
|
// create the corners of the bin
|
||||||
corners = patternCircular3d(
|
corners = patternCircular3d(
|
||||||
|
@ -52,7 +52,7 @@ axis000 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create a single corner of the bin
|
// create a single corner of the bin
|
||||||
singleCorner = revolve({ angle = -90, axis = axis000 }, face(offsetPlane("YZ", offset = cornerRadius)))
|
singleCorner = revolve(face(offsetPlane("YZ", offset = cornerRadius)), angle = -90, axis = axis000)
|
||||||
|
|
||||||
// create the corners of the bin
|
// create the corners of the bin
|
||||||
corners = patternCircular3d(
|
corners = patternCircular3d(
|
||||||
|
@ -75,7 +75,7 @@ axis000 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create a single corner of the bin
|
// create a single corner of the bin
|
||||||
singleCorner = revolve({ angle = -90, axis = axis000 }, face(offsetPlane("YZ", offset = cornerRadius + binTol)))
|
singleCorner = revolve(face(offsetPlane("YZ", offset = cornerRadius + binTol)), angle = -90, axis = axis000)
|
||||||
|
|
||||||
// create the corners of the bin
|
// create the corners of the bin
|
||||||
corners = patternCircular3d(
|
corners = patternCircular3d(
|
||||||
@ -291,10 +291,10 @@ axis001 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create a single corner of the bin
|
// create a single corner of the bin
|
||||||
lipSingleLengthCorner = revolve({ angle = -90, axis = axis001 }, lipFace(plane000))
|
lipSingleLengthCorner = revolve(lipFace(plane000), angle = -90, axis = axis001)
|
||||||
|
|
||||||
// create a single corner of the bin
|
// create a single corner of the bin
|
||||||
lipSingleWidthCorner = revolve({ angle = 90, axis = axis001 }, lipFace(plane002))
|
lipSingleWidthCorner = revolve(lipFace(plane002), angle = 90, axis = axis001)
|
||||||
|
|
||||||
// create the corners of the bin
|
// create the corners of the bin
|
||||||
lipCorners000 = patternCircular3d(
|
lipCorners000 = patternCircular3d(
|
||||||
|
@ -68,7 +68,7 @@ axis000 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create a single corner of the bin
|
// create a single corner of the bin
|
||||||
singleCorner = revolve({ angle = -90, axis = axis000 }, face(offsetPlane("YZ", offset = cornerRadius + binTol)))
|
singleCorner = revolve(face(offsetPlane("YZ", offset = cornerRadius + binTol)), angle = -90, axis = axis000)
|
||||||
|
|
||||||
// create the corners of the bin
|
// create the corners of the bin
|
||||||
corners = patternCircular3d(
|
corners = patternCircular3d(
|
||||||
|
@ -190,7 +190,7 @@ pipe = startSketchOn('XY')
|
|||||||
|> line(end = [0, -1])
|
|> line(end = [0, -1])
|
||||||
|> angledLine({ angle = 240, length = .5 }, %)
|
|> angledLine({ angle = 240, length = .5 }, %)
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve({ axis = 'y' }, %)
|
|> revolve(axis = 'y')
|
||||||
|> appearance(color = "#7b79d7")
|
|> appearance(color = "#7b79d7")
|
||||||
|
|
||||||
// Sketch and extrude the wall
|
// Sketch and extrude the wall
|
||||||
|
@ -32,4 +32,4 @@ pipeProfile = outerProfile
|
|||||||
|> hole(innerProfile, %)
|
|> hole(innerProfile, %)
|
||||||
|
|
||||||
// revolve the pipe profile at the desired angle
|
// revolve the pipe profile at the desired angle
|
||||||
pipe = revolve({ axis = "Y", angle = bendAngle }, pipeProfile)
|
pipe = revolve(pipeProfile, axis = "Y", angle = bendAngle)
|
||||||
|
@ -33,4 +33,4 @@ pipeSketch = startSketchOn('XY')
|
|||||||
|> close()
|
|> close()
|
||||||
|
|
||||||
// Revolve the sketch to create the pipe
|
// Revolve the sketch to create the pipe
|
||||||
pipe = revolve({ axis = 'y' }, pipeSketch)
|
pipe = revolve(pipeSketch, axis = 'y')
|
||||||
|
@ -30,7 +30,8 @@ sketch001 = startSketchOn("-YZ")
|
|||||||
|> yLine(endAbsolute = segEndY(seg01))
|
|> yLine(endAbsolute = segEndY(seg01))
|
||||||
|> angledLineToY({ angle = 180 - 60, to = 0 }, %)
|
|> angledLineToY({ angle = 180 - 60, to = 0 }, %)
|
||||||
|> close()
|
|> close()
|
||||||
part001 = revolve({
|
part001 = revolve(
|
||||||
|
sketch001,
|
||||||
angle = 90,
|
angle = 90,
|
||||||
axis = {
|
axis = {
|
||||||
custom = {
|
custom = {
|
||||||
@ -38,7 +39,7 @@ part001 = revolve({
|
|||||||
origin = [0.0, height + .0001]
|
origin = [0.0, height + .0001]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, sketch001)
|
)
|
||||||
|
|
||||||
sketch002 = startSketchOn('-YZ')
|
sketch002 = startSketchOn('-YZ')
|
||||||
|> startProfileAt([wallsWidth / 2, 0], %)
|
|> startProfileAt([wallsWidth / 2, 0], %)
|
||||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 29 KiB |