Compare commits
42 Commits
Author | SHA1 | Date | |
---|---|---|---|
befac6ad87 | |||
60bc38559b | |||
2a56155587 | |||
87c3673a71 | |||
21889162ff | |||
f1cccc22cd | |||
10c1f3a849 | |||
d168ef94e9 | |||
29f8b05f56 | |||
af482c30bd | |||
4e36e398ee | |||
b5f81b9384 | |||
879b471aed | |||
964d81dc0e | |||
443f7cd5fd | |||
2fc8cb5376 | |||
ee20a09e7e | |||
f4e801351c | |||
7329753211 | |||
7d46e7e271 | |||
0583eb07d5 | |||
73694563cf | |||
bb4ed59191 | |||
566143757f | |||
822f2ffc73 | |||
eb3ceba497 | |||
2c6d0621c9 | |||
d8e84cb5e3 | |||
0b1e79871f | |||
954fddf578 | |||
f94f748339 | |||
e2b7b22ca9 | |||
efc8c82d8b | |||
eac5abba79 | |||
1956c14b8a | |||
017fac7041 | |||
0bdc50c78f | |||
57d78b6094 | |||
db5ce7ba85 | |||
51c16d0048 | |||
6532b23f1c | |||
49304b9ecd |
91
.eslintrc
@ -1,91 +0,0 @@
|
|||||||
{
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"project": "./tsconfig.json"
|
|
||||||
},
|
|
||||||
"plugins": [
|
|
||||||
"react-perf",
|
|
||||||
"css-modules",
|
|
||||||
"jest",
|
|
||||||
"jsx-a11y",
|
|
||||||
"react",
|
|
||||||
"react-hooks",
|
|
||||||
"suggest-no-throw",
|
|
||||||
"testing-library",
|
|
||||||
"@typescript-eslint"
|
|
||||||
],
|
|
||||||
"extends": [
|
|
||||||
"plugin:css-modules/recommended",
|
|
||||||
"plugin:jsx-a11y/recommended",
|
|
||||||
"plugin:react-hooks/recommended"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"no-array-constructor": "off", // This is wrong; use the @typescript-eslint one instead.
|
|
||||||
"@typescript-eslint/no-array-constructor": "error",
|
|
||||||
"@typescript-eslint/no-array-delete": "error",
|
|
||||||
"@typescript-eslint/no-duplicate-enum-values": "error",
|
|
||||||
"@typescript-eslint/no-duplicate-type-constituents": "error",
|
|
||||||
"@typescript-eslint/no-empty-object-type": "error",
|
|
||||||
"@typescript-eslint/no-floating-promises": "error",
|
|
||||||
"no-implied-eval": "off", // This is wrong; use the @typescript-eslint one instead.
|
|
||||||
"@typescript-eslint/no-implied-eval": "error",
|
|
||||||
"@typescript-eslint/no-misused-promises": "error",
|
|
||||||
"@typescript-eslint/no-namespace": "error",
|
|
||||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
|
||||||
"@typescript-eslint/no-unnecessary-type-constraint": "error",
|
|
||||||
"no-unused-vars": "off", // This is wrong; use the @typescript-eslint one instead.
|
|
||||||
"@typescript-eslint/no-unused-vars": ["error", {
|
|
||||||
"varsIgnorePattern": "^_",
|
|
||||||
"argsIgnorePattern": "^_",
|
|
||||||
"ignoreRestSiblings": true,
|
|
||||||
"vars": "all",
|
|
||||||
"args": "none"
|
|
||||||
}],
|
|
||||||
"@typescript-eslint/prefer-as-const": "warn",
|
|
||||||
"jsx-a11y/click-events-have-key-events": "off",
|
|
||||||
"jsx-a11y/no-autofocus": "off",
|
|
||||||
"jsx-a11y/no-noninteractive-element-interactions": "off",
|
|
||||||
"no-restricted-globals": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"name": "isNaN",
|
|
||||||
"message": "Use Number.isNaN() instead."
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"no-restricted-syntax": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"selector": "CallExpression[callee.object.name='Array'][callee.property.name='isArray']",
|
|
||||||
"message": "Use isArray() in lib/utils.ts instead of Array.isArray()."
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"semi": [
|
|
||||||
"error",
|
|
||||||
"never"
|
|
||||||
],
|
|
||||||
"react-hooks/exhaustive-deps": "off",
|
|
||||||
"suggest-no-throw/suggest-no-throw": "warn",
|
|
||||||
},
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"files": ["e2e/**/*.ts"], // Update the pattern based on your file structure
|
|
||||||
"extends": [
|
|
||||||
"plugin:testing-library/react"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"suggest-no-throw/suggest-no-throw": "off",
|
|
||||||
"testing-library/prefer-screen-queries": "off",
|
|
||||||
"jest/valid-expect": "off"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"files": ["src/**/*.test.ts"],
|
|
||||||
"extends": [
|
|
||||||
"plugin:testing-library/react"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"suggest-no-throw/suggest-no-throw": "off",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
127
.eslintrc.json
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
{
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"project": "./tsconfig.json"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"react-perf",
|
||||||
|
"css-modules",
|
||||||
|
"jest",
|
||||||
|
"jsx-a11y",
|
||||||
|
"react",
|
||||||
|
"react-hooks",
|
||||||
|
"suggest-no-throw",
|
||||||
|
"testing-library",
|
||||||
|
"@typescript-eslint"
|
||||||
|
],
|
||||||
|
"extends": [
|
||||||
|
"plugin:css-modules/recommended",
|
||||||
|
"plugin:jsx-a11y/recommended",
|
||||||
|
"plugin:react-hooks/recommended"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"no-array-constructor": "off", // This is wrong; use the @typescript-eslint one instead.
|
||||||
|
"@typescript-eslint/no-array-constructor": "error",
|
||||||
|
"@typescript-eslint/no-array-delete": "error",
|
||||||
|
"@typescript-eslint/no-duplicate-enum-values": "error",
|
||||||
|
"@typescript-eslint/no-duplicate-type-constituents": "error",
|
||||||
|
"@typescript-eslint/no-empty-object-type": "error",
|
||||||
|
"@typescript-eslint/no-extra-non-null-assertion": "error",
|
||||||
|
"@typescript-eslint/no-floating-promises": "error",
|
||||||
|
"@typescript-eslint/no-for-in-array": "error",
|
||||||
|
"no-implied-eval": "off", // This is wrong; use the @typescript-eslint one instead.
|
||||||
|
"@typescript-eslint/no-implied-eval": "error",
|
||||||
|
"@typescript-eslint/no-misused-new": "error",
|
||||||
|
"@typescript-eslint/no-misused-promises": "error",
|
||||||
|
"@typescript-eslint/no-namespace": "error",
|
||||||
|
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
|
||||||
|
"@typescript-eslint/no-redundant-type-constituents": "error",
|
||||||
|
"@typescript-eslint/no-this-alias": "warn",
|
||||||
|
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||||
|
"@typescript-eslint/no-unnecessary-type-constraint": "error",
|
||||||
|
"no-unused-vars": "off", // This is wrong; use the @typescript-eslint one instead.
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"varsIgnorePattern": "^_",
|
||||||
|
"argsIgnorePattern": "^_",
|
||||||
|
"ignoreRestSiblings": true,
|
||||||
|
"vars": "all",
|
||||||
|
"args": "none"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-unsafe-unary-minus": "error",
|
||||||
|
"@typescript-eslint/no-wrapper-object-types": "error",
|
||||||
|
"no-throw-literal": "off", // Use @typescript-eslint/only-throw-error instead.
|
||||||
|
"@typescript-eslint/only-throw-error": "error",
|
||||||
|
"@typescript-eslint/prefer-as-const": "warn",
|
||||||
|
"@typescript-eslint/prefer-namespace-keyword": "error",
|
||||||
|
"@typescript-eslint/consistent-type-imports": "error",
|
||||||
|
"@typescript-eslint/restrict-plus-operands": "error",
|
||||||
|
"jsx-a11y/click-events-have-key-events": "off",
|
||||||
|
"jsx-a11y/no-autofocus": "off",
|
||||||
|
"jsx-a11y/no-noninteractive-element-interactions": "off",
|
||||||
|
"no-restricted-globals": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"name": "isNaN",
|
||||||
|
"message": "Use Number.isNaN() instead."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-restricted-syntax": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"selector": "CallExpression[callee.object.name='Array'][callee.property.name='isArray']",
|
||||||
|
"message": "Use isArray() in lib/utils.ts instead of Array.isArray()."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selector": "CallExpression[callee.object.name='TOML'][callee.property.name='stringify']",
|
||||||
|
"message": "Do not use TOML.stringify directly. Use the wrappers in test-utils instead like settingsToToml."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selector": "CallExpression[callee.object.name='TOML'][callee.property.name='parse']",
|
||||||
|
"message": "Do not use TOML.parse directly. Use the wrappers in test-utils instead like tomlToSettings."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"patterns": [
|
||||||
|
// Restrict all relative imports except for .css files.
|
||||||
|
{
|
||||||
|
"group": ["./*", "../*", "!./*.css", "!../*.css"],
|
||||||
|
"message": "Use absolute imports instead."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"semi": ["error", "never"],
|
||||||
|
"react-hooks/exhaustive-deps": "off",
|
||||||
|
"suggest-no-throw/suggest-no-throw": "error"
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["e2e/**/*.ts"], // Update the pattern based on your file structure
|
||||||
|
"extends": ["plugin:testing-library/react"],
|
||||||
|
"rules": {
|
||||||
|
"suggest-no-throw/suggest-no-throw": "off",
|
||||||
|
"testing-library/prefer-screen-queries": "off",
|
||||||
|
"jest/valid-expect": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["src/**/*.test.ts"],
|
||||||
|
"extends": ["plugin:testing-library/react"],
|
||||||
|
"rules": {
|
||||||
|
"suggest-no-throw/suggest-no-throw": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["packages/**/*.ts", "rust/**/*.ts"],
|
||||||
|
"extends": [],
|
||||||
|
"rules": {
|
||||||
|
"no-restricted-imports": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
8
.github/workflows/e2e-tests.yml
vendored
@ -229,10 +229,6 @@ jobs:
|
|||||||
timeout_minutes: 30
|
timeout_minutes: 30
|
||||||
max_attempts: 3
|
max_attempts: 3
|
||||||
env:
|
env:
|
||||||
CI: true
|
|
||||||
NODE_ENV: development
|
|
||||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
|
||||||
VITE_KC_SKIP_AUTH: true
|
|
||||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
|
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
|
||||||
|
|
||||||
@ -377,11 +373,7 @@ jobs:
|
|||||||
timeout_minutes: 45
|
timeout_minutes: 45
|
||||||
max_attempts: 15
|
max_attempts: 15
|
||||||
env:
|
env:
|
||||||
CI: true
|
|
||||||
FAIL_ON_CONSOLE_ERRORS: true
|
FAIL_ON_CONSOLE_ERRORS: true
|
||||||
NODE_ENV: development
|
|
||||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
|
||||||
VITE_KC_SKIP_AUTH: true
|
|
||||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
|
30
.github/workflows/static-analysis.yml
vendored
@ -136,6 +136,36 @@ jobs:
|
|||||||
|
|
||||||
- run: yarn lint
|
- run: yarn lint
|
||||||
|
|
||||||
|
yarn-circular-dependencies:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: yarn-build-wasm
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'yarn'
|
||||||
|
- run: yarn install
|
||||||
|
|
||||||
|
- name: Download all artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
|
- name: Copy prepared wasm
|
||||||
|
run: |
|
||||||
|
ls -R prepared-wasm
|
||||||
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
|
mkdir rust/kcl-wasm-lib/pkg
|
||||||
|
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
|
- name: Copy prepared ts-rs bindings
|
||||||
|
run: |
|
||||||
|
ls -R prepared-ts-rs-bindings
|
||||||
|
mkdir rust/kcl-lib/bindings
|
||||||
|
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
||||||
|
|
||||||
|
- run: yarn circular-deps:diff
|
||||||
|
|
||||||
python-codespell:
|
python-codespell:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
|
50
Makefile
@ -4,18 +4,38 @@ all: install build check
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
# INSTALL
|
# INSTALL
|
||||||
|
|
||||||
WASM_PACK ?= ~/.cargo/bin/wasm-pack
|
ifeq ($(OS),Windows_NT)
|
||||||
|
CARGO ?= ~/.cargo/bin/cargo.exe
|
||||||
|
WASM_PACK ?= ~/.cargo/bin/wasm-pack.exe
|
||||||
|
else
|
||||||
|
CARGO ?= ~/.cargo/bin/cargo
|
||||||
|
WASM_PACK ?= ~/.cargo/bin/wasm-pack
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: install
|
.PHONY: install
|
||||||
install: node_modules/.yarn-integrity $(WASM_PACK) ## Install dependencies
|
install: node_modules/.yarn-integrity $(CARGO) $(WASM_PACK) ## Install dependencies
|
||||||
|
|
||||||
node_modules/.yarn-integrity: package.json yarn.lock
|
node_modules/.yarn-integrity: package.json yarn.lock
|
||||||
yarn install
|
yarn install
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
@ type nul > $@
|
||||||
|
else
|
||||||
@ touch $@
|
@ touch $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(CARGO):
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
yarn install:rust:windows
|
||||||
|
else
|
||||||
|
yarn install:rust
|
||||||
|
endif
|
||||||
|
|
||||||
$(WASM_PACK):
|
$(WASM_PACK):
|
||||||
yarn install:rust
|
ifeq ($(OS),Windows_NT)
|
||||||
|
yarn install:wasm-pack:cargo
|
||||||
|
else
|
||||||
yarn install:wasm-pack:sh
|
yarn install:wasm-pack:sh
|
||||||
|
endif
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# BUILD
|
# BUILD
|
||||||
@ -31,13 +51,17 @@ VITE_SOURCES := $(wildcard vite.*) $(wildcard vite/**/*.tsx)
|
|||||||
build: build-web build-desktop
|
build: build-web build-desktop
|
||||||
|
|
||||||
.PHONY: build-web
|
.PHONY: build-web
|
||||||
build-web: public/kcl_wasm_lib_bg.wasm build/index.html
|
build-web: install public/kcl_wasm_lib_bg.wasm build/index.html
|
||||||
|
|
||||||
.PHONY: build-desktop
|
.PHONY: build-desktop
|
||||||
build-desktop: public/kcl_wasm_lib_bg.wasm .vite/build/main.js
|
build-desktop: install public/kcl_wasm_lib_bg.wasm .vite/build/main.js
|
||||||
|
|
||||||
public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES)$(RUST_SOURCES)
|
public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES) $(RUST_SOURCES)
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
yarn build:wasm:dev:windows
|
||||||
|
else
|
||||||
yarn build:wasm:dev
|
yarn build:wasm:dev
|
||||||
|
endif
|
||||||
|
|
||||||
build/index.html: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
|
build/index.html: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
|
||||||
yarn build:local
|
yarn build:local
|
||||||
@ -63,8 +87,10 @@ lint: install ## Lint the code
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
# RUN
|
# RUN
|
||||||
|
|
||||||
|
TARGET ?= web
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: run-web
|
run: run-$(TARGET)
|
||||||
|
|
||||||
.PHONY: run-web
|
.PHONY: run-web
|
||||||
run-web: install build-web ## Start the web app
|
run-web: install build-web ## Start the web app
|
||||||
@ -90,7 +116,7 @@ test-unit: install ## Run the unit tests
|
|||||||
yarn test:unit
|
yarn test:unit
|
||||||
|
|
||||||
.PHONY: test-e2e
|
.PHONY: test-e2e
|
||||||
test-e2e: test-e2e-desktop
|
test-e2e: test-e2e-$(TARGET)
|
||||||
|
|
||||||
.PHONY: test-e2e-web
|
.PHONY: test-e2e-web
|
||||||
test-e2e-web: install build-web ## Run the web e2e tests
|
test-e2e-web: install build-web ## Run the web e2e tests
|
||||||
@ -106,15 +132,23 @@ test-e2e-desktop: install build-desktop ## Run the desktop e2e tests
|
|||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean: ## Delete all artifacts
|
clean: ## Delete all artifacts
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
git clean --force -d -X
|
||||||
|
else
|
||||||
rm -rf .vite/ build/
|
rm -rf .vite/ build/
|
||||||
rm -rf trace.zip playwright-report/ test-results/
|
rm -rf trace.zip playwright-report/ test-results/
|
||||||
rm -rf public/kcl_wasm_lib_bg.wasm
|
rm -rf public/kcl_wasm_lib_bg.wasm
|
||||||
rm -rf rust/*/bindings/ rust/*/pkg/ rust/target/
|
rm -rf rust/*/bindings/ rust/*/pkg/ rust/target/
|
||||||
rm -rf node_modules/ rust/*/node_modules/
|
rm -rf node_modules/ rust/*/node_modules/
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: help
|
.PHONY: help
|
||||||
help: install
|
help: install
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
@ powershell -Command "Get-Content $(MAKEFILE_LIST) | Select-String -Pattern '^[^\s]+:.*##\s.*$$' | ForEach-Object { $$line = $$_.Line -split ':.*?##\s+'; Write-Host -NoNewline $$line[0].PadRight(30) -ForegroundColor Cyan; Write-Host $$line[1] }"
|
||||||
|
else
|
||||||
@ grep -E '^[^[:space:]]+:.*## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
@ grep -E '^[^[:space:]]+:.*## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||||
|
endif
|
||||||
|
|
||||||
.DEFAULT_GOAL := help
|
.DEFAULT_GOAL := help
|
||||||
|
|
||||||
|
@ -9,13 +9,9 @@ layout: manual
|
|||||||
|
|
||||||
### `std`
|
### `std`
|
||||||
|
|
||||||
- [`HALF_TURN`](/docs/kcl/consts/std-HALF_TURN)
|
|
||||||
- [`QUARTER_TURN`](/docs/kcl/consts/std-QUARTER_TURN)
|
|
||||||
- [`THREE_QUARTER_TURN`](/docs/kcl/consts/std-THREE_QUARTER_TURN)
|
|
||||||
- [`XY`](/docs/kcl/consts/std-XY)
|
- [`XY`](/docs/kcl/consts/std-XY)
|
||||||
- [`XZ`](/docs/kcl/consts/std-XZ)
|
- [`XZ`](/docs/kcl/consts/std-XZ)
|
||||||
- [`YZ`](/docs/kcl/consts/std-YZ)
|
- [`YZ`](/docs/kcl/consts/std-YZ)
|
||||||
- [`ZERO`](/docs/kcl/consts/std-ZERO)
|
|
||||||
|
|
||||||
### `std::math`
|
### `std::math`
|
||||||
|
|
||||||
@ -23,3 +19,10 @@ layout: manual
|
|||||||
- [`PI`](/docs/kcl/consts/std-math-PI)
|
- [`PI`](/docs/kcl/consts/std-math-PI)
|
||||||
- [`TAU`](/docs/kcl/consts/std-math-TAU)
|
- [`TAU`](/docs/kcl/consts/std-math-TAU)
|
||||||
|
|
||||||
|
### `std::turns`
|
||||||
|
|
||||||
|
- [`HALF_TURN`](/docs/kcl/consts/std-turns-HALF_TURN)
|
||||||
|
- [`QUARTER_TURN`](/docs/kcl/consts/std-turns-QUARTER_TURN)
|
||||||
|
- [`THREE_QUARTER_TURN`](/docs/kcl/consts/std-turns-THREE_QUARTER_TURN)
|
||||||
|
- [`ZERO`](/docs/kcl/consts/std-turns-ZERO)
|
||||||
|
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
title: "std::HALF_TURN"
|
|
||||||
excerpt: ""
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```js
|
|
||||||
std::HALF_TURN: number(deg) = 180deg
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
title: "std::QUARTER_TURN"
|
|
||||||
excerpt: ""
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```js
|
|
||||||
std::QUARTER_TURN: number(deg) = 90deg
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
title: "std::THREE_QUARTER_TURN"
|
|
||||||
excerpt: ""
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```js
|
|
||||||
std::THREE_QUARTER_TURN: number(deg) = 270deg
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
title: "std::ZERO"
|
|
||||||
excerpt: ""
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```js
|
|
||||||
std::ZERO: number = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
15
docs/kcl/consts/std-turns-HALF_TURN.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: "std::turns::HALF_TURN"
|
||||||
|
excerpt: ""
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
std::turns::HALF_TURN: number(deg) = 180deg
|
||||||
|
```
|
||||||
|
|
||||||
|
|
15
docs/kcl/consts/std-turns-QUARTER_TURN.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: "std::turns::QUARTER_TURN"
|
||||||
|
excerpt: ""
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
std::turns::QUARTER_TURN: number(deg) = 90deg
|
||||||
|
```
|
||||||
|
|
||||||
|
|
15
docs/kcl/consts/std-turns-THREE_QUARTER_TURN.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: "std::turns::THREE_QUARTER_TURN"
|
||||||
|
excerpt: ""
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
std::turns::THREE_QUARTER_TURN: number(deg) = 270deg
|
||||||
|
```
|
||||||
|
|
||||||
|
|
15
docs/kcl/consts/std-turns-ZERO.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: "std::turns::ZERO"
|
||||||
|
excerpt: ""
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
std::turns::ZERO: number = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -23,19 +23,15 @@ layout: manual
|
|||||||
* [`tag`](kcl/types/tag)
|
* [`tag`](kcl/types/tag)
|
||||||
* **std**
|
* **std**
|
||||||
* [`Face`](kcl/types/Face)
|
* [`Face`](kcl/types/Face)
|
||||||
* [`HALF_TURN`](kcl/consts/std-HALF_TURN)
|
|
||||||
* [`Helix`](kcl/types/Helix)
|
* [`Helix`](kcl/types/Helix)
|
||||||
* [`Plane`](kcl/types/Plane)
|
* [`Plane`](kcl/types/Plane)
|
||||||
* [`Point2d`](kcl/types/Point2d)
|
* [`Point2d`](kcl/types/Point2d)
|
||||||
* [`Point3d`](kcl/types/Point3d)
|
* [`Point3d`](kcl/types/Point3d)
|
||||||
* [`QUARTER_TURN`](kcl/consts/std-QUARTER_TURN)
|
|
||||||
* [`Sketch`](kcl/types/Sketch)
|
* [`Sketch`](kcl/types/Sketch)
|
||||||
* [`Solid`](kcl/types/Solid)
|
* [`Solid`](kcl/types/Solid)
|
||||||
* [`THREE_QUARTER_TURN`](kcl/consts/std-THREE_QUARTER_TURN)
|
|
||||||
* [`XY`](kcl/consts/std-XY)
|
* [`XY`](kcl/consts/std-XY)
|
||||||
* [`XZ`](kcl/consts/std-XZ)
|
* [`XZ`](kcl/consts/std-XZ)
|
||||||
* [`YZ`](kcl/consts/std-YZ)
|
* [`YZ`](kcl/consts/std-YZ)
|
||||||
* [`ZERO`](kcl/consts/std-ZERO)
|
|
||||||
* [`abs`](kcl/abs)
|
* [`abs`](kcl/abs)
|
||||||
* [`acos`](kcl/acos)
|
* [`acos`](kcl/acos)
|
||||||
* [`angleToMatchLengthX`](kcl/angleToMatchLengthX)
|
* [`angleToMatchLengthX`](kcl/angleToMatchLengthX)
|
||||||
@ -146,3 +142,8 @@ layout: manual
|
|||||||
* [`tan`](kcl/std-math-tan)
|
* [`tan`](kcl/std-math-tan)
|
||||||
* **std::sketch**
|
* **std::sketch**
|
||||||
* [`circle`](kcl/std-sketch-circle)
|
* [`circle`](kcl/std-sketch-circle)
|
||||||
|
* **std::turns**
|
||||||
|
* [`turns::HALF_TURN`](kcl/consts/std-turns-HALF_TURN)
|
||||||
|
* [`turns::QUARTER_TURN`](kcl/consts/std-turns-QUARTER_TURN)
|
||||||
|
* [`turns::THREE_QUARTER_TURN`](kcl/consts/std-turns-THREE_QUARTER_TURN)
|
||||||
|
* [`turns::ZERO`](kcl/consts/std-turns-ZERO)
|
||||||
|
@ -17,7 +17,7 @@ circle(@sketch_or_surface: Sketch | Plane | Face, center: Point2d, radius: numbe
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketch_or_surface` | [`Sketch`](/docs/kcl/types/Sketch) `|` [`Plane`](/docs/kcl/types/Face) `|` [`Plane`](/docs/kcl/types/Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
|
| `sketch_or_surface` | [`Sketch`](/docs/kcl/types/Sketch) OR [`Plane`](/docs/kcl/types/Plane) OR [`Face`](/docs/kcl/types/Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
|
||||||
| `center` | [`Point2d`](/docs/kcl/types/Point2d) | The center of the circle. | Yes |
|
| `center` | [`Point2d`](/docs/kcl/types/Point2d) | The center of the circle. | Yes |
|
||||||
| `radius` | [`number`](/docs/kcl/types/number) | The radius of the circle. | Yes |
|
| `radius` | [`number`](/docs/kcl/types/number) | The radius of the circle. | Yes |
|
||||||
| [`tag`](/docs/kcl/types/tag) | [`tag`](/docs/kcl/types/tag) | Create a new tag which refers to this circle. | No |
|
| [`tag`](/docs/kcl/types/tag) | [`tag`](/docs/kcl/types/tag) | Create a new tag which refers to this circle. | No |
|
||||||
|
@ -207302,372 +207302,8 @@
|
|||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"TyF64": {
|
"TyF64": {
|
||||||
"type": "object",
|
"type": "number",
|
||||||
"required": [
|
"format": "double"
|
||||||
"n",
|
|
||||||
"ty"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"n": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
},
|
|
||||||
"ty": {
|
|
||||||
"$ref": "#/components/schemas/NumericType"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"NumericType": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Count"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "A unit of length.",
|
|
||||||
"type": "object",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Mm"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Cm"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"M"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Inches"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Feet"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Yards"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Length"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "A unit of angle.",
|
|
||||||
"type": "object",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Degrees"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Radians"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Angle"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Known"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"angle",
|
|
||||||
"len",
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Default"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"len": {
|
|
||||||
"$ref": "#/components/schemas/UnitLen"
|
|
||||||
},
|
|
||||||
"angle": {
|
|
||||||
"$ref": "#/components/schemas/UnitAngle"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Unknown"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Any"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"UnitLen": {
|
|
||||||
"description": "A unit of length.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Mm"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Cm"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"M"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Inches"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Feet"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Yards"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"UnitAngle": {
|
|
||||||
"description": "A unit of angle.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Degrees"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"type"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Radians"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -256756,7 +256392,7 @@
|
|||||||
},
|
},
|
||||||
"required": false,
|
"required": false,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
"description": "The roll angle in degrees. Must be used with `pitch` and `yaw`. Must be between -360 and 360.",
|
"description": "The roll angle in degrees. Must be between -360 and 360. Default is 0 if not given.",
|
||||||
"labelRequired": true
|
"labelRequired": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -258354,7 +257990,7 @@
|
|||||||
},
|
},
|
||||||
"required": false,
|
"required": false,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
"description": "The pitch angle in degrees. Must be used with `roll` and `yaw`. Must be between -360 and 360.",
|
"description": "The pitch angle in degrees. Must be between -360 and 360. Default is 0 if not given.",
|
||||||
"labelRequired": true
|
"labelRequired": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -259952,7 +259588,7 @@
|
|||||||
},
|
},
|
||||||
"required": false,
|
"required": false,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
"description": "The yaw angle in degrees. Must be used with `roll` and `pitch`. Must be between -360 and 360.",
|
"description": "The yaw angle in degrees. Must be between -360 and 360. Default is 0 if not given.",
|
||||||
"labelRequired": true
|
"labelRequired": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -266421,6 +266057,7 @@
|
|||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"examples": [
|
"examples": [
|
||||||
"// Rotate a pipe with roll, pitch, and yaw.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> rotate(roll = 10, pitch = 10, yaw = 90)",
|
"// Rotate a pipe with roll, pitch, and yaw.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> rotate(roll = 10, pitch = 10, yaw = 90)",
|
||||||
|
"// Rotate a pipe with just roll.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> rotate(roll = 10)",
|
||||||
"// Rotate a pipe about an axis with an angle.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> rotate(axis = [0, 0, 1.0], angle = 90)",
|
"// Rotate a pipe about an axis with an angle.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> rotate(axis = [0, 0, 1.0], angle = 90)",
|
||||||
"// Rotate an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> rotate(axis = [0, 0, 1.0], angle = 90)",
|
"// Rotate an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> rotate(axis = [0, 0, 1.0], angle = 90)",
|
||||||
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Rotate the sweeps.\nrotate(parts, axis = [0, 0, 1.0], angle = 90)",
|
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Rotate the sweeps.\nrotate(parts, axis = [0, 0, 1.0], angle = 90)",
|
||||||
@ -268148,9 +267785,10 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "Nullable_double",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double",
|
"format": "double",
|
||||||
|
"nullable": true,
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"Solid": {
|
"Solid": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -269735,9 +269373,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": false,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
"description": "The scale factor for the x axis.",
|
"description": "The scale factor for the x axis. Default is 1 if not provided.",
|
||||||
"labelRequired": true
|
"labelRequired": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -269745,9 +269383,10 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "Nullable_double",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double",
|
"format": "double",
|
||||||
|
"nullable": true,
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"Solid": {
|
"Solid": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -271332,9 +270971,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": false,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
"description": "The scale factor for the y axis.",
|
"description": "The scale factor for the y axis. Default is 1 if not provided.",
|
||||||
"labelRequired": true
|
"labelRequired": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -271342,9 +270981,10 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "Nullable_double",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double",
|
"format": "double",
|
||||||
|
"nullable": true,
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"Solid": {
|
"Solid": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -272929,9 +272569,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": false,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
"description": "The scale factor for the z axis.",
|
"description": "The scale factor for the z axis. Default is 1 if not provided.",
|
||||||
"labelRequired": true
|
"labelRequired": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -276200,9 +275840,9 @@
|
|||||||
"unpublished": false,
|
"unpublished": false,
|
||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"examples": [
|
"examples": [
|
||||||
"// Scale a pipe.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> scale(x = 1.0, y = 1.0, z = 2.5)",
|
"// Scale a pipe.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> scale(z = 2.5)",
|
||||||
"// Scale an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> scale(x = 1.0, y = 1.0, z = 2.5)",
|
"// Scale an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> scale(z = 2.5)",
|
||||||
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Scale the sweep.\nscale(\n parts,\n x = 1.0,\n y = 1.0,\n z = 0.5,\n)"
|
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Scale the sweep.\nscale(parts, z = 0.5)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -326415,9 +326055,10 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "Nullable_double",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double",
|
"format": "double",
|
||||||
|
"nullable": true,
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"Solid": {
|
"Solid": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -328002,9 +327643,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": false,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
"description": "The amount to move the solid or sketch along the x axis.",
|
"description": "The amount to move the solid or sketch along the x axis. Defaults to 0 if not provided.",
|
||||||
"labelRequired": true
|
"labelRequired": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -328012,9 +327653,10 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "Nullable_double",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double",
|
"format": "double",
|
||||||
|
"nullable": true,
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"Solid": {
|
"Solid": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -329599,9 +329241,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": false,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
"description": "The amount to move the solid or sketch along the y axis.",
|
"description": "The amount to move the solid or sketch along the y axis. Defaults to 0 if not provided.",
|
||||||
"labelRequired": true
|
"labelRequired": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -329609,9 +329251,10 @@
|
|||||||
"type": "number",
|
"type": "number",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||||
"title": "double",
|
"title": "Nullable_double",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "double",
|
"format": "double",
|
||||||
|
"nullable": true,
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"Solid": {
|
"Solid": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -331196,9 +330839,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": true,
|
"required": false,
|
||||||
"includeInSnippet": true,
|
"includeInSnippet": true,
|
||||||
"description": "The amount to move the solid or sketch along the z axis.",
|
"description": "The amount to move the solid or sketch along the z axis. Defaults to 0 if not provided.",
|
||||||
"labelRequired": true
|
"labelRequired": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -334470,8 +334113,8 @@
|
|||||||
"// Move a pipe.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> translate(x = 1.0, y = 1.0, z = 2.5)",
|
"// Move a pipe.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> translate(x = 1.0, y = 1.0, z = 2.5)",
|
||||||
"// Move an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> translate(x = 1.0, y = 1.0, z = 2.5)",
|
"// Move an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> translate(x = 1.0, y = 1.0, z = 2.5)",
|
||||||
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Move the sweeps.\ntranslate(\n parts,\n x = 1.0,\n y = 1.0,\n z = 2.5,\n)",
|
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Move the sweeps.\ntranslate(\n parts,\n x = 1.0,\n y = 1.0,\n z = 2.5,\n)",
|
||||||
"// Move a sketch.\n\n\nfn square(length) {\n l = length / 2\n p0 = [-l, -l]\n p1 = [-l, l]\n p2 = [l, l]\n p3 = [l, -l]\n\n return startSketchOn(XY)\n |> startProfileAt(p0, %)\n |> line(endAbsolute = p1)\n |> line(endAbsolute = p2)\n |> line(endAbsolute = p3)\n |> close()\n}\n\nsquare(10)\n |> translate(x = 5, y = 5, z = 0)\n |> extrude(length = 10)",
|
"// Move a sketch.\n\n\nfn square(length) {\n l = length / 2\n p0 = [-l, -l]\n p1 = [-l, l]\n p2 = [l, l]\n p3 = [l, -l]\n\n return startSketchOn(XY)\n |> startProfileAt(p0, %)\n |> line(endAbsolute = p1)\n |> line(endAbsolute = p2)\n |> line(endAbsolute = p3)\n |> close()\n}\n\nsquare(10)\n |> translate(x = 5, y = 5)\n |> extrude(length = 10)",
|
||||||
"// Translate and rotate a sketch to create a loft.\nsketch001 = startSketchOn(XY)\n\nfn square() {\n return startProfileAt([-10, 10], sketch001)\n |> xLine(length = 20)\n |> yLine(length = -20)\n |> xLine(length = -20)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n}\n\nprofile001 = square()\n\nprofile002 = square()\n |> translate(x = 0, y = 0, z = 20)\n |> rotate(axis = [0, 0, 1.0], angle = 45)\n\nloft([profile001, profile002])"
|
"// Translate and rotate a sketch to create a loft.\nsketch001 = startSketchOn(XY)\n\nfn square() {\n return startProfileAt([-10, 10], sketch001)\n |> xLine(length = 20)\n |> yLine(length = -20)\n |> xLine(length = -20)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n}\n\nprofile001 = square()\n\nprofile002 = square()\n |> translate(z = 20)\n |> rotate(axis = [0, 0, 1.0], angle = 45)\n\nloft([profile001, profile002])"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -13,9 +13,9 @@ Translate is really useful for sketches if you want to move a sketch and then ro
|
|||||||
```js
|
```js
|
||||||
translate(
|
translate(
|
||||||
objects: SolidOrSketchOrImportedGeometry,
|
objects: SolidOrSketchOrImportedGeometry,
|
||||||
x: number,
|
x?: number,
|
||||||
y: number,
|
y?: number,
|
||||||
z: number,
|
z?: number,
|
||||||
global?: bool,
|
global?: bool,
|
||||||
): SolidOrSketchOrImportedGeometry
|
): SolidOrSketchOrImportedGeometry
|
||||||
```
|
```
|
||||||
@ -26,9 +26,9 @@ translate(
|
|||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `objects` | [`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) | The solid, sketch, or set of solids or sketches to move. | Yes |
|
| `objects` | [`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) | The solid, sketch, or set of solids or sketches to move. | Yes |
|
||||||
| `x` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the x axis. | Yes |
|
| `x` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the x axis. Defaults to 0 if not provided. | No |
|
||||||
| `y` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the y axis. | Yes |
|
| `y` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the y axis. Defaults to 0 if not provided. | No |
|
||||||
| `z` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the z axis. | Yes |
|
| `z` | [`number`](/docs/kcl/types/number) | The amount to move the solid or sketch along the z axis. Defaults to 0 if not provided. | 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 |
|
| `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
|
||||||
@ -134,7 +134,7 @@ fn square(length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
square(10)
|
square(10)
|
||||||
|> translate(x = 5, y = 5, z = 0)
|
|> translate(x = 5, y = 5)
|
||||||
|> extrude(length = 10)
|
|> extrude(length = 10)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ fn square() {
|
|||||||
profile001 = square()
|
profile001 = square()
|
||||||
|
|
||||||
profile002 = square()
|
profile002 = square()
|
||||||
|> translate(x = 0, y = 0, z = 20)
|
|> translate(z = 20)
|
||||||
|> rotate(axis = [0, 0, 1.0], angle = 45)
|
|> rotate(axis = [0, 0, 1.0], angle = 45)
|
||||||
|
|
||||||
loft([profile001, profile002])
|
loft([profile001, profile002])
|
||||||
|
@ -28,7 +28,7 @@ An extrude plane.
|
|||||||
| `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No |
|
| `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No |
|
||||||
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
|
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
|
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
|
||||||
| `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No |
|
| `sourceRange` |`[integer, integer, integer]`| The source range. | No |
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -48,7 +48,7 @@ An extruded arc.
|
|||||||
| `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No |
|
| `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No |
|
||||||
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
|
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
|
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
|
||||||
| `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No |
|
| `sourceRange` |`[integer, integer, integer]`| The source range. | No |
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -68,7 +68,7 @@ Geometry metadata.
|
|||||||
| `faceId` |[`string`](/docs/kcl/types/string)| The id for the chamfer surface. | No |
|
| `faceId` |[`string`](/docs/kcl/types/string)| The id for the chamfer surface. | No |
|
||||||
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
|
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
|
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
|
||||||
| `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No |
|
| `sourceRange` |`[integer, integer, integer]`| The source range. | No |
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -88,7 +88,7 @@ Geometry metadata.
|
|||||||
| `faceId` |[`string`](/docs/kcl/types/string)| The id for the fillet surface. | No |
|
| `faceId` |[`string`](/docs/kcl/types/string)| The id for the fillet surface. | No |
|
||||||
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
|
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
|
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
|
||||||
| `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No |
|
| `sourceRange` |`[integer, integer, integer]`| The source range. | No |
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
@ -17,6 +17,6 @@ Geometry metadata.
|
|||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
|
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
|
||||||
| `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No |
|
| `sourceRange` |`[integer, integer, integer]`| The source range. | No |
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ A helix.
|
|||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `value` |[`string`](/docs/kcl/types/string)| The id of the helix. | No |
|
| `value` |[`string`](/docs/kcl/types/string)| The id of the helix. | No |
|
||||||
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID. | No |
|
| `artifactId` |[`string`](/docs/kcl/types/string)| The artifact ID. | No |
|
||||||
| `revolutions` |[`number`](/docs/kcl/types/number)| Number of revolutions. | No |
|
| `revolutions` |[`number`](/docs/kcl/types/number)| Number of revolutions. | No |
|
||||||
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
|
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
|
||||||
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
||||||
|
@ -285,7 +285,7 @@ Data for an imported geometry.
|
|||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `Module`| | No |
|
| `type` |enum: `Module`| | No |
|
||||||
| `value` |[`ModuleId`](/docs/kcl/types/ModuleId)| Identifier of a source file. Uses a u32 to keep the size small. | No |
|
| `value` |`integer`| Identifier of a source file. Uses a u32 to keep the size small. | No |
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
@ -17,6 +17,6 @@ Data for polar coordinates.
|
|||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `angle` |[`number`](/docs/kcl/types/number)| The angle of the line (in degrees). | No |
|
| `angle` |[`number`](/docs/kcl/types/number)| The angle of the line (in degrees). | No |
|
||||||
| `length` |[`TyF64`](/docs/kcl/types/TyF64)| The length of the line. | No |
|
| `length` |[`number`](/docs/kcl/types/number)| The length of the line. | No |
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ A sketch type.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `plane`| | No |
|
| `type` |enum: `plane`| | No |
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the plane. | No |
|
| `id` |[`string`](/docs/kcl/types/string)| The id of the plane. | No |
|
||||||
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID. | No |
|
| `artifactId` |[`string`](/docs/kcl/types/string)| The artifact ID. | No |
|
||||||
| `value` |[`PlaneType`](/docs/kcl/types/PlaneType)| Type for a plane. | No |
|
| `value` |[`PlaneType`](/docs/kcl/types/PlaneType)| Type for a plane. | No |
|
||||||
| `origin` |[`Point3d`](/docs/kcl/types/Point3d)| Origin of the plane. | No |
|
| `origin` |[`Point3d`](/docs/kcl/types/Point3d)| Origin of the plane. | No |
|
||||||
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's X axis be? | No |
|
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's X axis be? | No |
|
||||||
@ -49,7 +49,7 @@ A face.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `face`| | No |
|
| `type` |enum: `face`| | No |
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the face. | No |
|
| `id` |[`string`](/docs/kcl/types/string)| The id of the face. | No |
|
||||||
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID. | No |
|
| `artifactId` |[`string`](/docs/kcl/types/string)| The artifact ID. | No |
|
||||||
| `value` |[`string`](/docs/kcl/types/string)| The tag of the face. | No |
|
| `value` |[`string`](/docs/kcl/types/string)| The tag of the face. | No |
|
||||||
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's X axis be? | No |
|
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's X axis be? | No |
|
||||||
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's Y axis be? | No |
|
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's Y axis be? | No |
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
title: "SourceRange"
|
|
||||||
excerpt: ""
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
**Type:** `integer` (`uint`)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5,17 +5,11 @@ layout: manual
|
|||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
**Type:** `object`
|
**Type:** [`number`](/docs/kcl/types/number) (`double`)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `n` |[`number`](/docs/kcl/types/number)| | No |
|
|
||||||
| `ty` |[`NumericType`](/docs/kcl/types/NumericType)| | No |
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Electron app header tests', () => {
|
test.describe('Electron app header tests', () => {
|
||||||
test(
|
test(
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { Page } from '@playwright/test'
|
import type { Page } from '@playwright/test'
|
||||||
import { test, expect } from './zoo-test'
|
|
||||||
|
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
|
||||||
import {
|
import {
|
||||||
getUtils,
|
PERSIST_MODELING_CONTEXT,
|
||||||
TEST_COLORS,
|
TEST_COLORS,
|
||||||
commonPoints,
|
commonPoints,
|
||||||
PERSIST_MODELING_CONTEXT,
|
getUtils,
|
||||||
orRunWhenFullSuiteEnabled,
|
orRunWhenFullSuiteEnabled,
|
||||||
} from './test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
import { HomePageFixture } from './fixtures/homePageFixture'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.setTimeout(120000)
|
test.setTimeout(120000)
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ async function doBasicSketch(
|
|||||||
await page.mouse.click(startXPx, 500 - PUR * 20)
|
await page.mouse.click(startXPx, 500 - PUR * 20)
|
||||||
if (openPanes.includes('code')) {
|
if (openPanes.includes('code')) {
|
||||||
await expect(u.codeLocator)
|
await expect(u.codeLocator)
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
|
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
|
||||||
commonPoints.startAt
|
commonPoints.startAt
|
||||||
}, sketch001)
|
}, sketch001)
|
||||||
|> xLine(length = ${commonPoints.num1})
|
|> xLine(length = ${commonPoints.num1})
|
||||||
@ -119,10 +120,7 @@ async function doBasicSketch(
|
|||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
if (openPanes.includes('code')) {
|
if (openPanes.includes('code')) {
|
||||||
await expect(
|
expect(await u.getGreatestPixDiff(line1, TEST_COLORS.BLUE)).toBeLessThan(3)
|
||||||
await u.getGreatestPixDiff(line1, TEST_COLORS.BLUE)
|
|
||||||
).toBeLessThan(3)
|
|
||||||
await expect(await u.getGreatestPixDiff(line1, [0, 0, 255])).toBeLessThan(3)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hold down shift
|
// hold down shift
|
||||||
@ -145,7 +143,7 @@ async function doBasicSketch(
|
|||||||
// Open the code pane.
|
// Open the code pane.
|
||||||
await u.openKclCodePanel()
|
await u.openKclCodePanel()
|
||||||
await expect(u.codeLocator)
|
await expect(u.codeLocator)
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
|
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
|
||||||
commonPoints.startAt
|
commonPoints.startAt
|
||||||
}, sketch001)
|
}, sketch001)
|
||||||
|> xLine(length = ${commonPoints.num1}, tag = $seg01)
|
|> xLine(length = ${commonPoints.num1}, tag = $seg01)
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { test, expect } from './zoo-test'
|
|
||||||
import fs from 'node:fs/promises'
|
import fs from 'node:fs/promises'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Point and click for boolean workflows', () => {
|
test.describe('Point and click for boolean workflows', () => {
|
||||||
// Boolean operations to test
|
// Boolean operations to test
|
||||||
const booleanOperations = [
|
const booleanOperations = [
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { Page } from '@playwright/test'
|
import type { Page } from '@playwright/test'
|
||||||
import { test, expect } from './zoo-test'
|
import type { EngineCommand } from '@src/lang/std/artifactGraph'
|
||||||
import { HomePageFixture } from './fixtures/homePageFixture'
|
import { uuidv4 } from '@src/lib/utils'
|
||||||
import { getUtils } from './test-utils'
|
|
||||||
import { EngineCommand } from 'lang/std/artifactGraph'
|
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||||
import { SceneFixture } from './fixtures/sceneFixture'
|
import { getUtils } from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe(
|
test.describe(
|
||||||
'Can create sketches on all planes and their back sides',
|
'Can create sketches on all planes and their back sides',
|
||||||
@ -46,7 +47,7 @@ test.describe(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = `sketch001 = startSketchOn(${plane})profile001 = startProfileAt([0.91, -1.22], sketch001)`
|
const code = `@settings(defaultLengthUnit = in)sketch001 = startSketchOn(${plane})profile001 = startProfileAt([0.91, -1.22], sketch001)`
|
||||||
|
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { bracket } from '@src/lib/exampleKcl'
|
||||||
import {
|
|
||||||
orRunWhenFullSuiteEnabled,
|
|
||||||
getUtils,
|
|
||||||
executorInputPath,
|
|
||||||
} from './test-utils'
|
|
||||||
import { join } from 'path'
|
|
||||||
import { bracket } from 'lib/exampleKcl'
|
|
||||||
import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from './storageStates'
|
|
||||||
import fsp from 'fs/promises'
|
import fsp from 'fs/promises'
|
||||||
|
import { join } from 'path'
|
||||||
|
|
||||||
|
import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from '@e2e/playwright/storageStates'
|
||||||
|
import {
|
||||||
|
executorInputPath,
|
||||||
|
getUtils,
|
||||||
|
orRunWhenFullSuiteEnabled,
|
||||||
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
|
test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
|
||||||
test('Typing KCL errors induces a badge on the code pane button', async ({
|
test('Typing KCL errors induces a badge on the code pane button', async ({
|
||||||
@ -251,11 +252,11 @@ test(
|
|||||||
])
|
])
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
fsp.copyFile(
|
fsp.copyFile(
|
||||||
executorInputPath('router-template-slate.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
join(routerTemplateDir, 'main.kcl')
|
join(routerTemplateDir, 'main.kcl')
|
||||||
),
|
),
|
||||||
fsp.copyFile(
|
fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
|
||||||
join(bracketDir, 'main.kcl')
|
join(bracketDir, 'main.kcl')
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
|
||||||
import * as fsp from 'fs/promises'
|
import * as fsp from 'fs/promises'
|
||||||
|
import path, { join } from 'path'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
executorInputPath,
|
executorInputPath,
|
||||||
getUtils,
|
getUtils,
|
||||||
orRunWhenFullSuiteEnabled,
|
orRunWhenFullSuiteEnabled,
|
||||||
} from './test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
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 ({
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { getUtils } from '@e2e/playwright/test-utils'
|
||||||
import { getUtils } from './test-utils'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Copilot ghost text', () => {
|
test.describe('Copilot ghost text', () => {
|
||||||
// eslint-disable-next-line jest/valid-title
|
// eslint-disable-next-line jest/valid-title
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { getUtils } from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
import { getUtils } from './test-utils'
|
|
||||||
|
|
||||||
function countNewlines(input: string): number {
|
function countNewlines(input: string): number {
|
||||||
let count = 0
|
let count = 0
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import fsp from 'fs/promises'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getUtils,
|
|
||||||
executorInputPath,
|
executorInputPath,
|
||||||
getPlaywrightDownloadDir,
|
getPlaywrightDownloadDir,
|
||||||
} from './test-utils'
|
getUtils,
|
||||||
import fsp from 'fs/promises'
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'export works on the first try',
|
'export works on the first try',
|
||||||
@ -20,11 +21,11 @@ test(
|
|||||||
await Promise.all([fsp.mkdir(bracketDir, { recursive: true })])
|
await Promise.all([fsp.mkdir(bracketDir, { recursive: true })])
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
fsp.copyFile(
|
fsp.copyFile(
|
||||||
executorInputPath('router-template-slate.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
path.join(bracketDir, 'other.kcl')
|
path.join(bracketDir, 'other.kcl')
|
||||||
),
|
),
|
||||||
fsp.copyFile(
|
fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
|
||||||
path.join(bracketDir, 'main.kcl')
|
path.join(bracketDir, 'main.kcl')
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
@ -107,7 +108,7 @@ test(
|
|||||||
},
|
},
|
||||||
{ timeout: 15_000 }
|
{ timeout: 15_000 }
|
||||||
)
|
)
|
||||||
.toBeGreaterThan(300_000)
|
.toBeGreaterThan(30_000)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -187,7 +188,7 @@ test(
|
|||||||
},
|
},
|
||||||
{ timeout: 15_000 }
|
{ timeout: 15_000 }
|
||||||
)
|
)
|
||||||
.toBeGreaterThan(70_000)
|
.toBeGreaterThan(50_000)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { uuidv4 } from '@src/lib/utils'
|
||||||
import fsp from 'fs/promises'
|
import fsp from 'fs/promises'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { join } from 'path'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
TEST_COLORS,
|
||||||
executorInputPath,
|
executorInputPath,
|
||||||
getUtils,
|
getUtils,
|
||||||
orRunWhenFullSuiteEnabled,
|
orRunWhenFullSuiteEnabled,
|
||||||
TEST_COLORS,
|
} from '@e2e/playwright/test-utils'
|
||||||
} from './test-utils'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
import { join } from 'path'
|
|
||||||
|
|
||||||
test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
||||||
test('can comment out code with ctrl+/', async ({ page, homePage }) => {
|
test('can comment out code with ctrl+/', async ({ page, homePage }) => {
|
||||||
@ -32,26 +32,30 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.keyboard.press('/')
|
await page.keyboard.press('/')
|
||||||
await page.keyboard.up('ControlOrMeta')
|
await page.keyboard.up('ControlOrMeta')
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XY)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XY)
|
||||||
|> startProfileAt([-10, -10], %)
|
|> startProfileAt([-10, -10], %)
|
||||||
|> line(end = [20, 0])
|
|> line(end = [20, 0])
|
||||||
|> line(end = [0, 20])
|
|> line(end = [0, 20])
|
||||||
|> line(end = [-20, 0])
|
|> line(end = [-20, 0])
|
||||||
// |> close()`)
|
// |> close()`.replaceAll('\n', '')
|
||||||
|
)
|
||||||
|
|
||||||
// uncomment the code
|
// uncomment the code
|
||||||
await page.keyboard.down('ControlOrMeta')
|
await page.keyboard.down('ControlOrMeta')
|
||||||
await page.keyboard.press('/')
|
await page.keyboard.press('/')
|
||||||
await page.keyboard.up('ControlOrMeta')
|
await page.keyboard.up('ControlOrMeta')
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XY)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XY)
|
||||||
|> startProfileAt([-10, -10], %)
|
|> startProfileAt([-10, -10], %)
|
||||||
|> line(end = [20, 0])
|
|> line(end = [20, 0])
|
||||||
|> line(end = [0, 20])
|
|> line(end = [0, 20])
|
||||||
|> line(end = [-20, 0])
|
|> line(end = [-20, 0])
|
||||||
|> close()`)
|
|> close()`.replaceAll('\n', '')
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('ensure we use the cache, and do not re-execute', async ({
|
test('ensure we use the cache, and do not re-execute', async ({
|
||||||
@ -178,13 +182,15 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.locator('#code-pane button:first-child').click()
|
await page.locator('#code-pane button:first-child').click()
|
||||||
await page.locator('button:has-text("Format code")').click()
|
await page.locator('button:has-text("Format code")').click()
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XY)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XY)
|
||||||
|> startProfileAt([-10, -10], %)
|
|> startProfileAt([-10, -10], %)
|
||||||
|> line(end = [20, 0])
|
|> line(end = [20, 0])
|
||||||
|> line(end = [0, 20])
|
|> line(end = [0, 20])
|
||||||
|> line(end = [-20, 0])
|
|> line(end = [-20, 0])
|
||||||
|> close()`)
|
|> close()`.replaceAll('\n', '')
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('if you click the format button it formats your code and executes so lints are still there', async ({
|
test('if you click the format button it formats your code and executes so lints are still there', async ({
|
||||||
@ -227,13 +233,15 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
.toHaveText(`sketch_001 = startSketchOn(XY)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch_001 = startSketchOn(XY)
|
||||||
|> startProfileAt([-10, -10], %)
|
|> startProfileAt([-10, -10], %)
|
||||||
|> line(end = [20, 0])
|
|> line(end = [20, 0])
|
||||||
|> line(end = [0, 20])
|
|> line(end = [0, 20])
|
||||||
|> line(end = [-20, 0])
|
|> line(end = [-20, 0])
|
||||||
|> close()`)
|
|> close()`.replaceAll('\n', '')
|
||||||
|
)
|
||||||
|
|
||||||
// error in guter
|
// error in guter
|
||||||
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
|
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
|
||||||
@ -471,6 +479,7 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
test('if you write kcl with lint errors you get lints', async ({
|
test('if you write kcl with lint errors you get lints', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
@ -490,10 +499,7 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.keyboard.press('ArrowLeft')
|
await page.keyboard.press('ArrowLeft')
|
||||||
await page.keyboard.press('ArrowRight')
|
await page.keyboard.press('ArrowRight')
|
||||||
|
|
||||||
// FIXME: lsp errors do not propagate to the frontend until engine is connected and code is executed
|
await scene.waitForExecutionDone()
|
||||||
// This timeout is to wait for engine connection. LSP and code execution errors should be handled differently
|
|
||||||
// LSP can emit errors as fast as it waits and show them in the editor
|
|
||||||
await page.waitForTimeout(10000)
|
|
||||||
|
|
||||||
// error in guter
|
// error in guter
|
||||||
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
|
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
|
||||||
@ -815,10 +821,12 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
// there shouldn't be any auto complete options for 'lin' in the comment
|
// there shouldn't be any auto complete options for 'lin' in the comment
|
||||||
await expect(page.locator('.cm-completionLabel')).not.toBeVisible()
|
await expect(page.locator('.cm-completionLabel')).not.toBeVisible()
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([3.14, 12], %)
|
|> startProfileAt([3.14, 12], %)
|
||||||
|> xLine(%, length = 5) // lin`)
|
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|
||||||
|
)
|
||||||
|
|
||||||
// expect there to be no KCL errors
|
// expect there to be no KCL errors
|
||||||
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(0)
|
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(0)
|
||||||
@ -888,10 +896,12 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
// there shouldn't be any auto complete options for 'lin' in the comment
|
// there shouldn't be any auto complete options for 'lin' in the comment
|
||||||
await expect(page.locator('.cm-completionLabel')).not.toBeVisible()
|
await expect(page.locator('.cm-completionLabel')).not.toBeVisible()
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([3.14, 12], %)
|
|> startProfileAt([3.14, 12], %)
|
||||||
|> xLine(%, length = 5) // lin`)
|
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
test('Can undo a click and point extrude with ctrl+z', async ({
|
test('Can undo a click and point extrude with ctrl+z', async ({
|
||||||
@ -975,12 +985,13 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
test(
|
test(
|
||||||
'Can undo a sketch modification with ctrl+z',
|
'Can undo a sketch modification with ctrl+z',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ page, homePage }) => {
|
async ({ page, homePage, editor }) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit=in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([4.61, -10.01], %)
|
|> startProfileAt([4.61, -10.01], %)
|
||||||
|> line(end = [12.73, -0.09])
|
|> line(end = [12.73, -0.09])
|
||||||
|> tangentialArcTo([24.95, -0.38], %)
|
|> tangentialArcTo([24.95, -0.38], %)
|
||||||
@ -1070,41 +1081,45 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
|
||||||
// expect the code to have changed
|
// expect the code to have changed
|
||||||
await expect(page.locator('.cm-content'))
|
await editor.expectEditor.toContain(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)
|
`sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([2.71, -2.71], %)
|
|> startProfileAt([2.71, -2.71], %)
|
||||||
|> line(end = [15.4, -2.78])
|
|> line(end = [15.4, -2.78])
|
||||||
|> tangentialArcTo([27.6, -3.05], %)
|
|> tangentialArcTo([27.6, -3.05], %)
|
||||||
|> close()
|
|> close()
|
||||||
|> extrude(length = 5)
|
|> extrude(length = 5)`,
|
||||||
`)
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
|
||||||
// Hit undo
|
// Hit undo
|
||||||
await page.keyboard.down('Control')
|
await page.keyboard.down('Control')
|
||||||
await page.keyboard.press('KeyZ')
|
await page.keyboard.press('KeyZ')
|
||||||
await page.keyboard.up('Control')
|
await page.keyboard.up('Control')
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await editor.expectEditor.toContain(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)
|
`sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([2.71, -2.71], %)
|
|> startProfileAt([2.71, -2.71], %)
|
||||||
|> line(end = [15.4, -2.78])
|
|> line(end = [15.4, -2.78])
|
||||||
|> tangentialArcTo([24.95, -0.38], %)
|
|> tangentialArcTo([24.95, -0.38], %)
|
||||||
|> close()
|
|> close()
|
||||||
|> extrude(length = 5)`)
|
|> extrude(length = 5)`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
|
||||||
// Hit undo again.
|
// Hit undo again.
|
||||||
await page.keyboard.down('Control')
|
await page.keyboard.down('Control')
|
||||||
await page.keyboard.press('KeyZ')
|
await page.keyboard.press('KeyZ')
|
||||||
await page.keyboard.up('Control')
|
await page.keyboard.up('Control')
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await editor.expectEditor.toContain(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)
|
`sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([2.71, -2.71], %)
|
|> startProfileAt([2.71, -2.71], %)
|
||||||
|> line(end = [12.73, -0.09])
|
|> line(end = [12.73, -0.09])
|
||||||
|> tangentialArcTo([24.95, -0.38], %)
|
|> tangentialArcTo([24.95, -0.38], %)
|
||||||
|> close()
|
|> close()
|
||||||
|> extrude(length = 5)
|
|> extrude(length = 5)`,
|
||||||
`)
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
|
||||||
// Hit undo again.
|
// Hit undo again.
|
||||||
await page.keyboard.down('Control')
|
await page.keyboard.down('Control')
|
||||||
@ -1112,13 +1127,15 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.keyboard.up('Control')
|
await page.keyboard.up('Control')
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await expect(page.locator('.cm-content'))
|
await editor.expectEditor.toContain(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)
|
`sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([4.61, -10.01], %)
|
|> startProfileAt([4.61, -10.01], %)
|
||||||
|> line(end = [12.73, -0.09])
|
|> line(end = [12.73, -0.09])
|
||||||
|> tangentialArcTo([24.95, -0.38], %)
|
|> tangentialArcTo([24.95, -0.38], %)
|
||||||
|> close()
|
|> close()
|
||||||
|> extrude(length = 5)`)
|
|> extrude(length = 5)`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1206,4 +1223,55 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test('Rectangle tool panning with middle click', async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
toolbar,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
editor,
|
||||||
|
}) => {
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 900 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
// wait until scene is ready to be interacted with
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||||
|
|
||||||
|
// select an axis plane
|
||||||
|
await page.mouse.click(700, 200)
|
||||||
|
|
||||||
|
// Needed as we don't yet have a way to get a signal from the engine that the camera has animated to the sketch plane
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
|
|
||||||
|
const middleMousePan = async (
|
||||||
|
startX: number,
|
||||||
|
startY: number,
|
||||||
|
endX: number,
|
||||||
|
endY: number
|
||||||
|
) => {
|
||||||
|
const initialCode = await editor.getCurrentCode()
|
||||||
|
|
||||||
|
await page.mouse.click(startX, startY, { button: 'middle' })
|
||||||
|
await page.mouse.move(endX, endY, {
|
||||||
|
steps: 10,
|
||||||
|
})
|
||||||
|
|
||||||
|
// We expect the code to be the same, middle mouse click should not modify the code, only do panning
|
||||||
|
await editor.expectEditor.toBe(initialCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
await test.step(`Verify corner rectangle panning`, async () => {
|
||||||
|
await page.getByTestId('corner-rectangle').click()
|
||||||
|
await middleMousePan(800, 500, 900, 600)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Verify center rectangle panning`, async () => {
|
||||||
|
await toolbar.selectCenterRectangle()
|
||||||
|
await middleMousePan(800, 200, 900, 300)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { test, expect } from './zoo-test'
|
|
||||||
import * as fsp from 'fs/promises'
|
import * as fsp from 'fs/promises'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
|
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
const FEATURE_TREE_EXAMPLE_CODE = `export fn timesFive(x) {
|
const FEATURE_TREE_EXAMPLE_CODE = `export fn timesFive(x) {
|
||||||
return 5 * x
|
return 5 * x
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { FILE_EXT } from '@src/lib/constants'
|
||||||
import * as fsp from 'fs/promises'
|
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
|
import * as fsp from 'fs/promises'
|
||||||
|
import { join } from 'path'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createProject,
|
createProject,
|
||||||
executorInputPath,
|
executorInputPath,
|
||||||
getUtils,
|
getUtils,
|
||||||
orRunWhenFullSuiteEnabled,
|
orRunWhenFullSuiteEnabled,
|
||||||
runningOnWindows,
|
runningOnWindows,
|
||||||
} from './test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
import { join } from 'path'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
import { FILE_EXT } from 'lib/constants'
|
|
||||||
|
|
||||||
test.describe('integrations tests', () => {
|
test.describe('integrations tests', () => {
|
||||||
test(
|
test(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { Page, Locator, Route, Request } from '@playwright/test'
|
import type { Locator, Page, Request, Route, TestInfo } from '@playwright/test'
|
||||||
import { expect, TestInfo } from '@playwright/test'
|
import { expect } from '@playwright/test'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import type { Page, Locator } from '@playwright/test'
|
import type { Locator, Page } from '@playwright/test'
|
||||||
import { expect } from '@playwright/test'
|
import { expect } from '@playwright/test'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
closePane,
|
|
||||||
checkIfPaneIsOpen,
|
checkIfPaneIsOpen,
|
||||||
|
closePane,
|
||||||
openPane,
|
openPane,
|
||||||
sansWhitespace,
|
sansWhitespace,
|
||||||
} from '../test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
|
|
||||||
interface EditorState {
|
interface EditorState {
|
||||||
activeLines: Array<string>
|
activeLines: Array<string>
|
||||||
@ -81,6 +82,13 @@ export class EditorFixture {
|
|||||||
expectEditor = {
|
expectEditor = {
|
||||||
toContain: this._expectEditorToContain(),
|
toContain: this._expectEditorToContain(),
|
||||||
not: { toContain: this._expectEditorToContain(true) },
|
not: { toContain: this._expectEditorToContain(true) },
|
||||||
|
toBe: async (code: string) => {
|
||||||
|
const currentCode = await this.getCurrentCode()
|
||||||
|
return expect(currentCode).toBe(code)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
getCurrentCode = async () => {
|
||||||
|
return await this.codeContent.innerText()
|
||||||
}
|
}
|
||||||
snapshot = async (options?: { timeout?: number; name?: string }) => {
|
snapshot = async (options?: { timeout?: number; name?: string }) => {
|
||||||
const wasPaneOpen = await this.checkIfPaneIsOpen()
|
const wasPaneOpen = await this.checkIfPaneIsOpen()
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
/* eslint-disable react-hooks/rules-of-hooks */
|
/* eslint-disable react-hooks/rules-of-hooks */
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
BrowserContext,
|
BrowserContext,
|
||||||
ElectronApplication,
|
ElectronApplication,
|
||||||
TestInfo,
|
|
||||||
Page,
|
Page,
|
||||||
|
TestInfo,
|
||||||
} from '@playwright/test'
|
} from '@playwright/test'
|
||||||
|
|
||||||
import { _electron as electron } from '@playwright/test'
|
import { _electron as electron } from '@playwright/test'
|
||||||
|
|
||||||
import * as TOML from '@iarna/toml'
|
import { SETTINGS_FILE_NAME } from '@src/lib/constants'
|
||||||
import { TEST_SETTINGS } from '../storageStates'
|
import type { DeepPartial } from '@src/lib/types'
|
||||||
import { SETTINGS_FILE_NAME } from 'lib/constants'
|
|
||||||
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'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { CmdBarFixture } from './cmdBarFixture'
|
|
||||||
import { EditorFixture } from './editorFixture'
|
import type { Settings } from '@rust/kcl-lib/bindings/Settings'
|
||||||
import { ToolbarFixture } from './toolbarFixture'
|
|
||||||
import { SceneFixture } from './sceneFixture'
|
import { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||||
import { HomePageFixture } from './homePageFixture'
|
import { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
|
||||||
import { DeepPartial } from 'lib/types'
|
import { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
|
||||||
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
import { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||||
|
import { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
||||||
|
|
||||||
|
import { TEST_SETTINGS } from '@e2e/playwright/storageStates'
|
||||||
|
import { getUtils, settingsToToml, setup } from '@e2e/playwright/test-utils'
|
||||||
|
|
||||||
export class AuthenticatedApp {
|
export class AuthenticatedApp {
|
||||||
public readonly page: Page
|
public readonly page: Page
|
||||||
@ -124,6 +124,7 @@ export class ElectronZoo {
|
|||||||
|
|
||||||
// We need to expose this in order for some tests that require folder
|
// We need to expose this in order for some tests that require folder
|
||||||
// creation and some code below.
|
// creation and some code below.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
const that = this
|
const that = this
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
@ -286,26 +287,30 @@ export class ElectronZoo {
|
|||||||
let settingsOverridesToml = ''
|
let settingsOverridesToml = ''
|
||||||
|
|
||||||
if (appSettings) {
|
if (appSettings) {
|
||||||
settingsOverridesToml = TOML.stringify({
|
settingsOverridesToml = settingsToToml({
|
||||||
// @ts-expect-error
|
|
||||||
settings: {
|
settings: {
|
||||||
...TEST_SETTINGS,
|
...TEST_SETTINGS,
|
||||||
...appSettings,
|
...appSettings,
|
||||||
app: {
|
app: {
|
||||||
...TEST_SETTINGS.app,
|
...TEST_SETTINGS.app,
|
||||||
project_directory: this.projectDirName,
|
|
||||||
...appSettings.app,
|
...appSettings.app,
|
||||||
},
|
},
|
||||||
|
project: {
|
||||||
|
...TEST_SETTINGS.project,
|
||||||
|
directory: this.projectDirName,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
settingsOverridesToml = TOML.stringify({
|
settingsOverridesToml = settingsToToml({
|
||||||
// @ts-expect-error
|
|
||||||
settings: {
|
settings: {
|
||||||
...TEST_SETTINGS,
|
...TEST_SETTINGS,
|
||||||
app: {
|
app: {
|
||||||
...TEST_SETTINGS.app,
|
...TEST_SETTINGS.app,
|
||||||
project_directory: this.projectDirName,
|
},
|
||||||
|
project: {
|
||||||
|
...TEST_SETTINGS.project,
|
||||||
|
directory: this.projectDirName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { Page, Locator } from '@playwright/test'
|
import type { Locator, Page } from '@playwright/test'
|
||||||
import { expect } from '@playwright/test'
|
import { expect } from '@playwright/test'
|
||||||
|
|
||||||
interface ProjectCardState {
|
interface ProjectCardState {
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import type { Page, Locator } from '@playwright/test'
|
import type { Locator, Page } from '@playwright/test'
|
||||||
import { expect } from '../zoo-test'
|
import { isArray, uuidv4 } from '@src/lib/utils'
|
||||||
import { isArray, uuidv4 } from 'lib/utils'
|
|
||||||
import { CmdBarFixture } from './cmdBarFixture'
|
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
closeDebugPanel,
|
closeDebugPanel,
|
||||||
doAndWaitForImageDiff,
|
doAndWaitForImageDiff,
|
||||||
getPixelRGBs,
|
getPixelRGBs,
|
||||||
|
getUtils,
|
||||||
openAndClearDebugPanel,
|
openAndClearDebugPanel,
|
||||||
sendCustomCmd,
|
sendCustomCmd,
|
||||||
getUtils,
|
} from '@e2e/playwright/test-utils'
|
||||||
} from '../test-utils'
|
import { expect } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
type MouseParams = {
|
type MouseParams = {
|
||||||
pixelDiff?: number
|
pixelDiff?: number
|
||||||
@ -310,7 +312,9 @@ export async function expectPixelColor(
|
|||||||
.toBeTruthy()
|
.toBeTruthy()
|
||||||
.catch((cause) => {
|
.catch((cause) => {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`ExpectPixelColor: expecting ${colour} got ${finalValue}`,
|
`ExpectPixelColor: point ${JSON.stringify(
|
||||||
|
coords
|
||||||
|
)} was expecting ${colour} but got ${finalValue}`,
|
||||||
{ cause }
|
{ cause }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
import { type Page, type Locator, test } from '@playwright/test'
|
import { type Locator, type Page, test } from '@playwright/test'
|
||||||
import { expect } from '../zoo-test'
|
import type { SidebarType } from '@src/components/ModelingSidebar/ModelingPanes'
|
||||||
|
import { SIDEBAR_BUTTON_SUFFIX } from '@src/lib/constants'
|
||||||
|
import type { ToolbarModeName } from '@src/lib/toolbar'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkIfPaneIsOpen,
|
checkIfPaneIsOpen,
|
||||||
closePane,
|
closePane,
|
||||||
doAndWaitForImageDiff,
|
doAndWaitForImageDiff,
|
||||||
openPane,
|
openPane,
|
||||||
} from '../test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
import { expect } from '@e2e/playwright/zoo-test'
|
||||||
import { SIDEBAR_BUTTON_SUFFIX } from 'lib/constants'
|
import { type baseUnitLabels } from '@src/lib/settings/settingsTypes'
|
||||||
import { ToolbarModeName } from 'lib/toolbar'
|
|
||||||
|
type LengthUnitLabel = (typeof baseUnitLabels)[keyof typeof baseUnitLabels]
|
||||||
|
|
||||||
export class ToolbarFixture {
|
export class ToolbarFixture {
|
||||||
public page: Page
|
public page: Page
|
||||||
@ -235,6 +239,12 @@ export class ToolbarFixture {
|
|||||||
async checkIfFeatureTreePaneIsOpen() {
|
async checkIfFeatureTreePaneIsOpen() {
|
||||||
return this.checkIfPaneIsOpen(this.featureTreeId)
|
return this.checkIfPaneIsOpen(this.featureTreeId)
|
||||||
}
|
}
|
||||||
|
async selectUnit(unit: LengthUnitLabel) {
|
||||||
|
await this.page.getByTestId('units-menu').click()
|
||||||
|
const optionLocator = this.page.getByRole('button', { name: unit })
|
||||||
|
await expect(optionLocator).toBeVisible()
|
||||||
|
await optionLocator.click()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a specific operation button from the Feature Tree pane.
|
* Get a specific operation button from the Feature Tree pane.
|
||||||
|
@ -272,14 +272,6 @@ export const isErrorWhitelisted = (exception: Error) => {
|
|||||||
project: 'Google Chrome',
|
project: 'Google Chrome',
|
||||||
foundInSpec: 'e2e/playwright/snapshot-tests.spec.ts',
|
foundInSpec: 'e2e/playwright/snapshot-tests.spec.ts',
|
||||||
},
|
},
|
||||||
// TODO: fix this error in the code
|
|
||||||
{
|
|
||||||
name: 'ReferenceError',
|
|
||||||
message: 'createNewVariableCheckbox is not defined',
|
|
||||||
stack: '',
|
|
||||||
project: 'Google Chrome',
|
|
||||||
foundInSpec: 'e2e/playwright/testing-constraints.spec.ts',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Error',
|
name: 'Error',
|
||||||
message: 'The "path" argument must be of type string. Received undefined',
|
message: 'The "path" argument must be of type string. Received undefined',
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { test, expect } from './zoo-test'
|
|
||||||
import { executorInputPath } from './test-utils'
|
|
||||||
import { join } from 'path'
|
|
||||||
import fsp from 'fs/promises'
|
import fsp from 'fs/promises'
|
||||||
|
import { join } from 'path'
|
||||||
|
|
||||||
|
import { executorInputPath } from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'When machine-api server not found butt is disabled and shows the reason',
|
'When machine-api server not found butt is disabled and shows the reason',
|
||||||
@ -11,7 +12,7 @@ test(
|
|||||||
const bracketDir = join(dir, 'bracket')
|
const bracketDir = join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
join(bracketDir, 'main.kcl')
|
join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -51,7 +52,7 @@ test(
|
|||||||
const bracketDir = join(dir, 'bracket')
|
const bracketDir = join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
join(bracketDir, 'main.kcl')
|
join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { PROJECT_SETTINGS_FILE_NAME } from '@src/lib/constants'
|
||||||
import { PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
|
|
||||||
import * as fsp from 'fs/promises'
|
import * as fsp from 'fs/promises'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
|
|
||||||
|
import type { NamedView } from '@rust/kcl-lib/bindings/NamedView'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createProject,
|
createProject,
|
||||||
tomlToPerProjectSettings,
|
|
||||||
perProjectsettingsToToml,
|
perProjectsettingsToToml,
|
||||||
} from './test-utils'
|
tomlToPerProjectSettings,
|
||||||
import { NamedView } from '@rust/kcl-lib/bindings/NamedView'
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
// Helper function to determine if the file path on disk exists
|
// Helper function to determine if the file path on disk exists
|
||||||
// Specifically this is used to check if project.toml exists on disk
|
// Specifically this is used to check if project.toml exists on disk
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not all menu actions are tested. Some are default electron menu actions.
|
* Not all menu actions are tested. Some are default electron menu actions.
|
||||||
@ -10,6 +10,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
test('File.Create project', async ({ tronApp, cmdBar, page }) => {
|
test('File.Create project', async ({ tronApp, cmdBar, page }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const newProject =
|
const newProject =
|
||||||
@ -29,6 +30,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
test('File.Open project', async ({ tronApp, cmdBar, page }) => {
|
test('File.Open project', async ({ tronApp, cmdBar, page }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const openProject =
|
const openProject =
|
||||||
@ -52,6 +54,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
}) => {
|
}) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const userSettings = app.applicationMenu.getMenuItemById(
|
const userSettings = app.applicationMenu.getMenuItemById(
|
||||||
@ -75,6 +78,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
}) => {
|
}) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const keybindings = app.applicationMenu.getMenuItemById(
|
const keybindings = app.applicationMenu.getMenuItemById(
|
||||||
@ -96,6 +100,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
}) => {
|
}) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
@ -112,6 +117,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
test('File.Preferences.Theme', async ({ tronApp, cmdBar, page }) => {
|
test('File.Preferences.Theme', async ({ tronApp, cmdBar, page }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
@ -136,6 +142,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
}) => {
|
}) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
@ -152,6 +159,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
test('File.Preferences.Sign out', async ({ tronApp, cmdBar, page }) => {
|
test('File.Preferences.Sign out', async ({ tronApp, cmdBar, page }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById('File.Sign out')
|
const menu = app.applicationMenu.getMenuItemById('File.Sign out')
|
||||||
@ -170,6 +178,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
test('Edit.Rename project', async ({ tronApp, cmdBar, page }) => {
|
test('Edit.Rename project', async ({ tronApp, cmdBar, page }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
@ -188,6 +197,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
test('Edit.Delete project', async ({ tronApp, cmdBar, page }) => {
|
test('Edit.Delete project', async ({ tronApp, cmdBar, page }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
@ -210,6 +220,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
}) => {
|
}) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
@ -228,6 +239,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
test('View.Command Palette...', async ({ tronApp, cmdBar, page }) => {
|
test('View.Command Palette...', async ({ tronApp, cmdBar, page }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
@ -245,6 +257,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
test('Help.Show all commands', async ({ tronApp, cmdBar, page }) => {
|
test('Help.Show all commands', async ({ tronApp, cmdBar, page }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
@ -260,6 +273,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
test('Help.KCL code samples', async ({ tronApp, cmdBar, page }) => {
|
test('Help.KCL code samples', async ({ tronApp, cmdBar, page }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
@ -275,6 +289,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
}) => {
|
}) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
@ -293,6 +308,7 @@ test.describe('Native file menu', { tag: ['@electron'] }, () => {
|
|||||||
test('Help.Reset onboarding', async ({ tronApp, cmdBar, page }) => {
|
test('Help.Reset onboarding', async ({ tronApp, cmdBar, page }) => {
|
||||||
if (!tronApp) fail()
|
if (!tronApp) fail()
|
||||||
// Run electron snippet to find the Menu!
|
// Run electron snippet to find the Menu!
|
||||||
|
await page.waitForTimeout(100) // wait for createModelingPageMenu() to run
|
||||||
await tronApp.electron.evaluate(async ({ app }) => {
|
await tronApp.electron.evaluate(async ({ app }) => {
|
||||||
if (!app || !app.applicationMenu) fail()
|
if (!app || !app.applicationMenu) fail()
|
||||||
const menu = app.applicationMenu.getMenuItemById(
|
const menu = app.applicationMenu.getMenuItemById(
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
// application, check it can make it to the project pane, and nothing more.
|
// application, check it can make it to the project pane, and nothing more.
|
||||||
// It also tests our test wrappers are working.
|
// It also tests our test wrappers are working.
|
||||||
// Additionally this serves as a nice minimal example.
|
// Additionally this serves as a nice minimal example.
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
import { test, expect } from './zoo-test'
|
|
||||||
|
|
||||||
test.describe('Open the application', () => {
|
test.describe('Open the application', () => {
|
||||||
test('see the project view', async ({ page, context }) => {
|
test('see the project view', async ({ page, context }) => {
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { bracket } from '@src/lib/exampleKcl'
|
||||||
import { join } from 'path'
|
import { onboardingPaths } from '@src/routes/Onboarding/paths'
|
||||||
import fsp from 'fs/promises'
|
import fsp from 'fs/promises'
|
||||||
import {
|
import { join } from 'path'
|
||||||
getUtils,
|
|
||||||
executorInputPath,
|
import { expectPixelColor } from '@e2e/playwright/fixtures/sceneFixture'
|
||||||
createProject,
|
|
||||||
settingsToToml,
|
|
||||||
orRunWhenFullSuiteEnabled,
|
|
||||||
} from './test-utils'
|
|
||||||
import { bracket } from 'lib/exampleKcl'
|
|
||||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
|
||||||
import {
|
import {
|
||||||
TEST_SETTINGS_KEY,
|
TEST_SETTINGS_KEY,
|
||||||
TEST_SETTINGS_ONBOARDING_START,
|
|
||||||
TEST_SETTINGS_ONBOARDING_EXPORT,
|
TEST_SETTINGS_ONBOARDING_EXPORT,
|
||||||
|
TEST_SETTINGS_ONBOARDING_START,
|
||||||
TEST_SETTINGS_ONBOARDING_USER_MENU,
|
TEST_SETTINGS_ONBOARDING_USER_MENU,
|
||||||
} from './storageStates'
|
} from '@e2e/playwright/storageStates'
|
||||||
import { expectPixelColor } from './fixtures/sceneFixture'
|
import {
|
||||||
|
createProject,
|
||||||
|
executorInputPath,
|
||||||
|
getUtils,
|
||||||
|
orRunWhenFullSuiteEnabled,
|
||||||
|
settingsToToml,
|
||||||
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
// Because our default test settings have the onboardingStatus set to 'dismissed',
|
// Because our default test settings have the onboardingStatus set to 'dismissed',
|
||||||
// we must set it to empty for the tests where we want to see the onboarding immediately.
|
// we must set it to empty for the tests where we want to see the onboarding immediately.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { test, expect } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
|
|
||||||
/** @deprecated, import from ./fixtureSetup.ts instead */
|
/** @deprecated, import from ./fixtureSetup.ts instead */
|
||||||
export const _test = test
|
export const _test = test
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { Page } from '@playwright/test'
|
import type { Locator, Page } from '@playwright/test'
|
||||||
import { test, expect } from './zoo-test'
|
|
||||||
import { EditorFixture } from './fixtures/editorFixture'
|
|
||||||
import { SceneFixture } from './fixtures/sceneFixture'
|
|
||||||
import { ToolbarFixture } from './fixtures/toolbarFixture'
|
|
||||||
import fs from 'node:fs/promises'
|
import fs from 'node:fs/promises'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
|
|
||||||
import { Locator } from '@playwright/test'
|
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
|
||||||
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||||
|
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
||||||
|
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
// test file is for testing point an click code gen functionality that's not sketch mode related
|
// test file is for testing point an click code gen functionality that's not sketch mode related
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ test.describe('Point-and-click tests', () => {
|
|||||||
|
|
||||||
await scene.moveCameraTo(cameraPos, cameraTarget)
|
await scene.moveCameraTo(cameraPos, cameraTarget)
|
||||||
|
|
||||||
await test.step('check chamfer selection changes cursor positon', async () => {
|
await test.step('check chamfer selection changes cursor position', async () => {
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
// sometimes initial click doesn't register
|
// sometimes initial click doesn't register
|
||||||
await clickChamfer()
|
await clickChamfer()
|
||||||
@ -173,7 +173,7 @@ test.describe('Point-and-click tests', () => {
|
|||||||
})
|
})
|
||||||
await test.step('Check there is no errors after code created in previous steps executes', async () => {
|
await test.step('Check there is no errors after code created in previous steps executes', async () => {
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
activeLines: ['sketch001 = startSketchOn(XZ)'],
|
activeLines: ['@settings(defaultLengthUnit = in)'],
|
||||||
highlightedCode: '',
|
highlightedCode: '',
|
||||||
diagnostics: [],
|
diagnostics: [],
|
||||||
})
|
})
|
||||||
@ -299,7 +299,8 @@ test.describe('Point-and-click tests', () => {
|
|||||||
|
|
||||||
await test.step('verify at the end of the test that final code is what is expected', async () => {
|
await test.step('verify at the end of the test that final code is what is expected', async () => {
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
||||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||||
|> angledLine([
|
|> angledLine([
|
||||||
@ -369,7 +370,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Works on chamfers that are non in a pipeExpression can break up multi edges in a chamfer array', async ({
|
test('Works on chamfers that are not in a pipeExpression can break up multi edges in a chamfer array', async ({
|
||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
@ -418,7 +419,8 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|
|||||||
|>close()`,
|
|>close()`,
|
||||||
})
|
})
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([75.8, 317.2], %)
|
|> startProfileAt([75.8, 317.2], %)
|
||||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||||
|> angledLine([
|
|> angledLine([
|
||||||
@ -1639,9 +1641,10 @@ loft001 = loft([sketch001, sketch002])
|
|||||||
{
|
{
|
||||||
targetType: 'circle',
|
targetType: 'circle',
|
||||||
testPoint: { x: 700, y: 250 },
|
testPoint: { x: 700, y: 250 },
|
||||||
initialCode: `sketch001 = startSketchOn('YZ')
|
initialCode: `@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(YZ)
|
||||||
profile001 = circle(sketch001, center = [0, 0], radius = 500)
|
profile001 = circle(sketch001, center = [0, 0], radius = 500)
|
||||||
sketch002 = startSketchOn('XZ')
|
sketch002 = startSketchOn(XZ)
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> xLine(length = -500)
|
|> xLine(length = -500)
|
||||||
|> tangentialArcTo([-2000, 500], %)`,
|
|> tangentialArcTo([-2000, 500], %)`,
|
||||||
@ -1649,7 +1652,8 @@ sketch002 = startSketchOn('XZ')
|
|||||||
{
|
{
|
||||||
targetType: 'rectangle',
|
targetType: 'rectangle',
|
||||||
testPoint: { x: 710, y: 255 },
|
testPoint: { x: 710, y: 255 },
|
||||||
initialCode: `sketch001 = startSketchOn('YZ')
|
initialCode: `@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(YZ)
|
||||||
profile001 = startProfileAt([-400, -400], sketch001)
|
profile001 = startProfileAt([-400, -400], sketch001)
|
||||||
|> angledLine([0, 800], %, $rectangleSegmentA001)
|
|> angledLine([0, 800], %, $rectangleSegmentA001)
|
||||||
|> angledLine([
|
|> angledLine([
|
||||||
@ -1662,7 +1666,7 @@ profile001 = startProfileAt([-400, -400], sketch001)
|
|||||||
], %)
|
], %)
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
sketch002 = startSketchOn('XZ')
|
sketch002 = startSketchOn(XZ)
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> xLine(length = -500)
|
|> xLine(length = -500)
|
||||||
|> tangentialArcTo([-2000, 500], %)`,
|
|> tangentialArcTo([-2000, 500], %)`,
|
||||||
@ -1806,7 +1810,8 @@ sketch002 = startSketchOn('XZ')
|
|||||||
toolbar,
|
toolbar,
|
||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `sketch001 = startSketchOn(YZ)
|
const initialCode = `@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(YZ)
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [0, 0],
|
center = [0, 0],
|
||||||
radius = 500
|
radius = 500
|
||||||
@ -2475,7 +2480,8 @@ extrude001 = extrude(profile001, length = 5)
|
|||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
// Code samples
|
// Code samples
|
||||||
const initialCode = `sketch001 = startSketchOn(XY)
|
const initialCode = `@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XY)
|
||||||
|> startProfileAt([-12, -6], %)
|
|> startProfileAt([-12, -6], %)
|
||||||
|> line(end = [0, 12])
|
|> line(end = [0, 12])
|
||||||
|> line(end = [24, 0])
|
|> line(end = [24, 0])
|
||||||
@ -2767,7 +2773,8 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
toolbar,
|
toolbar,
|
||||||
}) => {
|
}) => {
|
||||||
// Code samples
|
// Code samples
|
||||||
const initialCode = `sketch001 = startSketchOn(XY)
|
const initialCode = `@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XY)
|
||||||
|> startProfileAt([-12, -6], %)
|
|> startProfileAt([-12, -6], %)
|
||||||
|> line(end = [0, 12])
|
|> line(end = [0, 12])
|
||||||
|> line(end = [24, 0], tag = $seg02)
|
|> line(end = [24, 0], tag = $seg02)
|
||||||
@ -2921,7 +2928,8 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
toolbar,
|
toolbar,
|
||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
const initialCode = `@settings(defaultLengthUnit = in)
|
||||||
|
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)
|
||||||
`
|
`
|
||||||
@ -3056,7 +3064,8 @@ extrude001 = extrude(sketch001, length = 30)
|
|||||||
toolbar,
|
toolbar,
|
||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `sketch001 = startSketchOn(XY)
|
const initialCode = `@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XY)
|
||||||
|> startProfileAt([-20, 20], %)
|
|> startProfileAt([-20, 20], %)
|
||||||
|> xLine(length = 40)
|
|> xLine(length = 40)
|
||||||
|> yLine(length = -60)
|
|> yLine(length = -60)
|
||||||
@ -3174,7 +3183,8 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
})
|
})
|
||||||
|
|
||||||
const shellSketchOnFacesCases = [
|
const shellSketchOnFacesCases = [
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> circle(center = [0, 0], radius = 100)
|
|> circle(center = [0, 0], radius = 100)
|
||||||
|> extrude(length = 100)
|
|> extrude(length = 100)
|
||||||
|
|
||||||
@ -3182,7 +3192,8 @@ sketch002 = startSketchOn(sketch001, 'END')
|
|||||||
|> circle(center = [0, 0], radius = 50)
|
|> circle(center = [0, 0], radius = 50)
|
||||||
|> extrude(length = 50)
|
|> extrude(length = 50)
|
||||||
`,
|
`,
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> circle(center = [0, 0], radius = 100)
|
|> circle(center = [0, 0], radius = 100)
|
||||||
extrude001 = extrude(sketch001, length = 100)
|
extrude001 = extrude(sketch001, length = 100)
|
||||||
|
|
||||||
@ -3465,6 +3476,39 @@ segAng(rectangleSegmentA002),
|
|||||||
|
|
||||||
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = 'X')`
|
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = 'X')`
|
||||||
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
||||||
|
|
||||||
|
// Edit flow
|
||||||
|
const newAngle = '90'
|
||||||
|
await toolbar.openPane('feature-tree')
|
||||||
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
|
'Revolve',
|
||||||
|
0
|
||||||
|
)
|
||||||
|
await operationButton.dblclick({ button: 'left' })
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Revolve',
|
||||||
|
currentArgKey: 'angle',
|
||||||
|
currentArgValue: '360',
|
||||||
|
headerArguments: {
|
||||||
|
Angle: '360',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'angle',
|
||||||
|
stage: 'arguments',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText(newAngle)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Angle: newAngle,
|
||||||
|
},
|
||||||
|
commandName: 'Revolve',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await toolbar.closePane('feature-tree')
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
newCodeToFind.replace('angle = 360', 'angle = ' + newAngle)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
test('revolve surface around edge from an extruded solid2d', async ({
|
test('revolve surface around edge from an extruded solid2d', async ({
|
||||||
context,
|
context,
|
||||||
@ -3475,26 +3519,22 @@ segAng(rectangleSegmentA002),
|
|||||||
toolbar,
|
toolbar,
|
||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
||||||
sketch001 = startSketchOn(XZ)
|
|> startProfileAt([-102.57, 101.72], %)
|
||||||
|> startProfileAt([-102.57, 101.72], %)
|
|> angledLine([0, 202.6], %, $rectangleSegmentA001)
|
||||||
|> angledLine([0, 202.6], %, $rectangleSegmentA001)
|
|> angledLine([
|
||||||
|> angledLine([
|
segAng(rectangleSegmentA001) - 90,
|
||||||
segAng(rectangleSegmentA001) - 90,
|
202.6
|
||||||
202.6
|
], %, $rectangleSegmentB001)
|
||||||
], %, $rectangleSegmentB001)
|
|> angledLine([
|
||||||
|> angledLine([
|
segAng(rectangleSegmentA001),
|
||||||
segAng(rectangleSegmentA001),
|
-segLen(rectangleSegmentA001)
|
||||||
-segLen(rectangleSegmentA001)
|
], %, $rectangleSegmentC001)
|
||||||
], %, $rectangleSegmentC001)
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> close()
|
||||||
|> close()
|
|
||||||
extrude001 = extrude(sketch001, length = 50)
|
extrude001 = extrude(sketch001, length = 50)
|
||||||
sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
|
sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
|
||||||
|> circle(
|
|> circle(center = [-11.34, 10.0], radius = 8.69)
|
||||||
center = [-11.34, 10.0],
|
|
||||||
radius = 8.69
|
|
||||||
)
|
|
||||||
`
|
`
|
||||||
await context.addInitScript((initialCode) => {
|
await context.addInitScript((initialCode) => {
|
||||||
localStorage.setItem('persistCode', initialCode)
|
localStorage.setItem('persistCode', initialCode)
|
||||||
@ -3512,9 +3552,49 @@ radius = 8.69
|
|||||||
const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)`
|
const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)`
|
||||||
await page.getByText(lineCodeToSelection).click()
|
await page.getByText(lineCodeToSelection).click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
|
||||||
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = getOppositeEdge(rectangleSegmentA001)) `
|
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = rectangleSegmentA001)`
|
||||||
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
await editor.expectEditor.toContain(newCodeToFind)
|
||||||
|
|
||||||
|
// Edit flow
|
||||||
|
const newAngle = '180'
|
||||||
|
await toolbar.openPane('feature-tree')
|
||||||
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
|
'Revolve',
|
||||||
|
0
|
||||||
|
)
|
||||||
|
await operationButton.dblclick({ button: 'left' })
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Revolve',
|
||||||
|
currentArgKey: 'angle',
|
||||||
|
currentArgValue: '360',
|
||||||
|
headerArguments: {
|
||||||
|
Angle: '360',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'angle',
|
||||||
|
stage: 'arguments',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText(newAngle)
|
||||||
|
await page.getByRole('button', { name: 'Create new variable' }).click()
|
||||||
|
await expect(page.getByPlaceholder('Variable name')).toHaveValue(
|
||||||
|
'angle001'
|
||||||
|
)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Angle: newAngle,
|
||||||
|
},
|
||||||
|
commandName: 'Revolve',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await toolbar.closePane('feature-tree')
|
||||||
|
await editor.expectEditor.toContain('angle001 = ' + newAngle)
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
newCodeToFind.replace('angle = 360', 'angle = angle001')
|
||||||
|
)
|
||||||
})
|
})
|
||||||
test('revolve sketch circle around line segment from startProfileAt sketch', async ({
|
test('revolve sketch circle around line segment from startProfileAt sketch', async ({
|
||||||
context,
|
context,
|
||||||
@ -3525,26 +3605,22 @@ radius = 8.69
|
|||||||
toolbar,
|
toolbar,
|
||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `
|
const initialCode = `sketch002 = startSketchOn(XY)
|
||||||
sketch002 = startSketchOn(XY)
|
|> startProfileAt([-2.02, 1.79], %)
|
||||||
|> startProfileAt([-2.02, 1.79], %)
|
|> xLine(length = 2.6)
|
||||||
|> xLine(length = 2.6)
|
sketch001 = startSketchOn(-XY)
|
||||||
sketch001 = startSketchOn('-XY')
|
|> startProfileAt([-0.48, 1.25], %)
|
||||||
|> startProfileAt([-0.48, 1.25], %)
|
|> angledLine([0, 2.38], %, $rectangleSegmentA001)
|
||||||
|> angledLine([0, 2.38], %, $rectangleSegmentA001)
|
|> angledLine([segAng(rectangleSegmentA001) - 90, 2.4], %, $rectangleSegmentB001)
|
||||||
|> angledLine([segAng(rectangleSegmentA001) - 90, 2.4], %, $rectangleSegmentB001)
|
|> angledLine([
|
||||||
|> angledLine([
|
segAng(rectangleSegmentA001),
|
||||||
segAng(rectangleSegmentA001),
|
-segLen(rectangleSegmentA001)
|
||||||
-segLen(rectangleSegmentA001)
|
], %, $rectangleSegmentC001)
|
||||||
], %, $rectangleSegmentC001)
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> close()
|
||||||
|> close()
|
extrude001 = extrude(sketch001, length = 5)
|
||||||
extrude001 = extrude(sketch001, length = 5)
|
sketch003 = startSketchOn(extrude001, 'START')
|
||||||
sketch003 = startSketchOn(extrude001, 'START')
|
|> circle(center = [-0.69, 0.56], radius = 0.28)
|
||||||
|> circle(
|
|
||||||
center = [-0.69, 0.56],
|
|
||||||
radius = 0.28
|
|
||||||
)
|
|
||||||
`
|
`
|
||||||
|
|
||||||
await context.addInitScript((initialCode) => {
|
await context.addInitScript((initialCode) => {
|
||||||
@ -3563,9 +3639,44 @@ radius = 8.69
|
|||||||
const lineCodeToSelection = `|> xLine(length = 2.6)`
|
const lineCodeToSelection = `|> xLine(length = 2.6)`
|
||||||
await page.getByText(lineCodeToSelection).click()
|
await page.getByText(lineCodeToSelection).click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
|
||||||
const newCodeToFind = `revolve001 = revolve(sketch003, angle = 360, axis = seg01)`
|
const newCodeToFind = `revolve001 = revolve(sketch003, angle = 360, axis = seg01)`
|
||||||
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
||||||
|
|
||||||
|
// Edit flow
|
||||||
|
const newAngle = '270'
|
||||||
|
await toolbar.openPane('feature-tree')
|
||||||
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
|
'Revolve',
|
||||||
|
0
|
||||||
|
)
|
||||||
|
await operationButton.dblclick({ button: 'left' })
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Revolve',
|
||||||
|
currentArgKey: 'angle',
|
||||||
|
currentArgValue: '360',
|
||||||
|
headerArguments: {
|
||||||
|
Angle: '360',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'angle',
|
||||||
|
stage: 'arguments',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText(newAngle)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Angle: newAngle,
|
||||||
|
},
|
||||||
|
commandName: 'Revolve',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await toolbar.closePane('feature-tree')
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
newCodeToFind.replace('angle = 360', 'angle = ' + newAngle)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -3578,7 +3689,8 @@ radius = 8.69
|
|||||||
toolbar,
|
toolbar,
|
||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `sketch001 = startSketchOn(XZ)
|
const initialCode = `@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
profile001 = circle(
|
profile001 = circle(
|
||||||
sketch001,
|
sketch001,
|
||||||
center = [0, 0],
|
center = [0, 0],
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { DEFAULT_PROJECT_KCL_FILE } from '@src/lib/constants'
|
||||||
|
import fs from 'fs'
|
||||||
|
import fsp from 'fs/promises'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
import type { Paths } from '@e2e/playwright/test-utils'
|
||||||
import {
|
import {
|
||||||
|
createProject,
|
||||||
doExport,
|
doExport,
|
||||||
executorInputPath,
|
executorInputPath,
|
||||||
|
getPlaywrightDownloadDir,
|
||||||
getUtils,
|
getUtils,
|
||||||
isOutOfViewInScrollContainer,
|
isOutOfViewInScrollContainer,
|
||||||
Paths,
|
|
||||||
createProject,
|
|
||||||
getPlaywrightDownloadDir,
|
|
||||||
orRunWhenFullSuiteEnabled,
|
orRunWhenFullSuiteEnabled,
|
||||||
runningOnWindows,
|
runningOnWindows,
|
||||||
} from './test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
import fsp from 'fs/promises'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
import fs from 'fs'
|
|
||||||
import path from 'path'
|
|
||||||
import { DEFAULT_PROJECT_KCL_FILE } from 'lib/constants'
|
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'projects reload if a new one is created, deleted, or renamed externally',
|
'projects reload if a new one is created, deleted, or renamed externally',
|
||||||
@ -87,7 +88,7 @@ test(
|
|||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
path.join(bracketDir, 'main.kcl')
|
path.join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -124,7 +125,7 @@ test(
|
|||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
path.join(bracketDir, 'main.kcl')
|
path.join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
const errorDir = path.join(dir, 'broken-code')
|
const errorDir = path.join(dir, 'broken-code')
|
||||||
@ -162,7 +163,7 @@ test(
|
|||||||
// gray at this pixel means the stream has loaded in the most
|
// gray at this pixel means the stream has loaded in the most
|
||||||
// user way we can verify it (pixel color)
|
// user way we can verify it (pixel color)
|
||||||
await expect
|
await expect
|
||||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
|
.poll(() => u.getGreatestPixDiff(pointOnModel, [110, 110, 110]), {
|
||||||
timeout: 10_000,
|
timeout: 10_000,
|
||||||
})
|
})
|
||||||
.toBeLessThan(20)
|
.toBeLessThan(20)
|
||||||
@ -213,7 +214,7 @@ test(
|
|||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
path.join(bracketDir, 'main.kcl')
|
path.join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
const emptyDir = path.join(dir, 'empty')
|
const emptyDir = path.join(dir, 'empty')
|
||||||
@ -248,7 +249,7 @@ test(
|
|||||||
// gray at this pixel means the stream has loaded in the most
|
// gray at this pixel means the stream has loaded in the most
|
||||||
// user way we can verify it (pixel color)
|
// user way we can verify it (pixel color)
|
||||||
await expect
|
await expect
|
||||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
|
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
|
||||||
timeout: 10_000,
|
timeout: 10_000,
|
||||||
})
|
})
|
||||||
.toBeLessThan(15)
|
.toBeLessThan(15)
|
||||||
@ -290,7 +291,7 @@ test(
|
|||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
path.join(bracketDir, 'main.kcl')
|
path.join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -319,7 +320,7 @@ test(
|
|||||||
// gray at this pixel means the stream has loaded in the most
|
// gray at this pixel means the stream has loaded in the most
|
||||||
// user way we can verify it (pixel color)
|
// user way we can verify it (pixel color)
|
||||||
await expect
|
await expect
|
||||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
|
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
|
||||||
timeout: 10_000,
|
timeout: 10_000,
|
||||||
})
|
})
|
||||||
.toBeLessThan(15)
|
.toBeLessThan(15)
|
||||||
@ -359,7 +360,7 @@ test(
|
|||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
path.join(bracketDir, 'main.kcl')
|
path.join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
@ -393,7 +394,7 @@ test(
|
|||||||
// gray at this pixel means the stream has loaded in the most
|
// gray at this pixel means the stream has loaded in the most
|
||||||
// user way we can verify it (pixel color)
|
// user way we can verify it (pixel color)
|
||||||
await expect
|
await expect
|
||||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
|
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
|
||||||
timeout: 10_000,
|
timeout: 10_000,
|
||||||
})
|
})
|
||||||
.toBeLessThan(15)
|
.toBeLessThan(15)
|
||||||
@ -443,7 +444,6 @@ test(
|
|||||||
await page.getByText('broken-code').click()
|
await page.getByText('broken-code').click()
|
||||||
|
|
||||||
// Gotcha: You can not use scene.waitForExecutionDone() since the KCL code is going to fail
|
// Gotcha: You can not use scene.waitForExecutionDone() since the KCL code is going to fail
|
||||||
await expect(page.getByTestId('loading')).toBeAttached()
|
|
||||||
await expect(page.getByTestId('loading')).not.toBeAttached({
|
await expect(page.getByTestId('loading')).not.toBeAttached({
|
||||||
timeout: 20_000,
|
timeout: 20_000,
|
||||||
})
|
})
|
||||||
@ -481,7 +481,7 @@ test.describe('Can export from electron app', () => {
|
|||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
path.join(bracketDir, 'main.kcl')
|
path.join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -513,7 +513,7 @@ test.describe('Can export from electron app', () => {
|
|||||||
// gray at this pixel means the stream has loaded in the most
|
// gray at this pixel means the stream has loaded in the most
|
||||||
// user way we can verify it (pixel color)
|
// user way we can verify it (pixel color)
|
||||||
await expect
|
await expect
|
||||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
|
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
|
||||||
timeout: 10_000,
|
timeout: 10_000,
|
||||||
})
|
})
|
||||||
.toBeLessThan(15)
|
.toBeLessThan(15)
|
||||||
@ -554,7 +554,7 @@ test.describe('Can export from electron app', () => {
|
|||||||
},
|
},
|
||||||
{ timeout: 15_000 }
|
{ timeout: 15_000 }
|
||||||
)
|
)
|
||||||
.toBeGreaterThan(300_000)
|
.toBeGreaterThan(50_000)
|
||||||
|
|
||||||
// clean up exported file
|
// clean up exported file
|
||||||
await fsp.rm(filepath)
|
await fsp.rm(filepath)
|
||||||
@ -1507,7 +1507,12 @@ test(
|
|||||||
|
|
||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
await page.locator('.cm-content').fill(`sketch001 = startSketchOn(XZ)
|
// The file should be prepopulated with the user's unit settings.
|
||||||
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
|
'@settings(defaultLengthUnit = in)'
|
||||||
|
)
|
||||||
|
|
||||||
|
await page.locator('.cm-content').fill(`sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([-87.4, 282.92], %)
|
|> startProfileAt([-87.4, 282.92], %)
|
||||||
|> line(end = [324.07, 27.199], tag = $seg01)
|
|> line(end = [324.07, 27.199], tag = $seg01)
|
||||||
|> line(end = [118.328, -291.754])
|
|> line(end = [118.328, -291.754])
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
/* eslint-disable jest/no-conditional-expect */
|
/* eslint-disable jest/no-conditional-expect */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
|
||||||
import { orRunWhenFullSuiteEnabled } from './test-utils'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
/* eslint-disable jest/no-conditional-expect */
|
/* eslint-disable jest/no-conditional-expect */
|
||||||
|
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
import { Page } from '@playwright/test'
|
import type { Page } from '@playwright/test'
|
||||||
import { test, expect } from './zoo-test'
|
import { bracket } from '@src/lib/exampleKcl'
|
||||||
import path from 'path'
|
import { reportRejection } from '@src/lib/trap'
|
||||||
import * as fsp from 'fs/promises'
|
import * as fsp from 'fs/promises'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from '@e2e/playwright/storageStates'
|
||||||
|
import type { TestColor } from '@e2e/playwright/test-utils'
|
||||||
import {
|
import {
|
||||||
getUtils,
|
|
||||||
executorInputPath,
|
|
||||||
TEST_COLORS,
|
TEST_COLORS,
|
||||||
TestColor,
|
executorInputPath,
|
||||||
|
getUtils,
|
||||||
orRunWhenFullSuiteEnabled,
|
orRunWhenFullSuiteEnabled,
|
||||||
} from './test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
import { bracket } from 'lib/exampleKcl'
|
|
||||||
import { reportRejection } from 'lib/trap'
|
|
||||||
|
|
||||||
test.describe('Regression tests', { tag: ['@skipWin'] }, () => {
|
test.describe('Regression tests', { tag: ['@skipWin'] }, () => {
|
||||||
// bugs we found that don't fit neatly into other categories
|
// bugs we found that don't fit neatly into other categories
|
||||||
@ -331,7 +332,7 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`@settings(defaultLengthUnit = mm)
|
`@settings(defaultLengthUnit = mm)
|
||||||
sketch002 = startSketchOn('XY')
|
sketch002 = startSketchOn(XY)
|
||||||
profile002 = startProfileAt([72.24, -52.05], sketch002)
|
profile002 = startProfileAt([72.24, -52.05], sketch002)
|
||||||
|> angledLine([0, 181.26], %, $rectangleSegmentA001)
|
|> angledLine([0, 181.26], %, $rectangleSegmentA001)
|
||||||
|> angledLine([
|
|> angledLine([
|
||||||
@ -582,7 +583,7 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
path.join(bracketDir, 'main.kcl')
|
path.join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -619,6 +620,7 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
test(`View gizmo stays visible even when zoomed out all the way`, async ({
|
test(`View gizmo stays visible even when zoomed out all the way`, async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
@ -632,7 +634,7 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
|
|
||||||
await test.step(`Load an empty file`, async () => {
|
await test.step(`Load an empty file`, async () => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem('persistCode', '')
|
localStorage.setItem('persistCode', '@settings(defaultLengthUnit = in)')
|
||||||
})
|
})
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
@ -646,22 +648,31 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
message: 'Plane color is visible',
|
message: 'Plane color is visible',
|
||||||
})
|
})
|
||||||
.toBeLessThanOrEqual(15)
|
.toBeLessThanOrEqual(20)
|
||||||
|
await expect(scene.startEditSketchBtn).toBeEnabled()
|
||||||
|
|
||||||
let maxZoomOuts = 10
|
let maxZoomOuts = 10
|
||||||
let middlePixelIsBackgroundColor =
|
let middlePixelIsBackgroundColor =
|
||||||
(await middlePixelIsColor(bgColor)) < 10
|
(await middlePixelIsColor(bgColor)) < 10
|
||||||
|
|
||||||
|
console.time('pressing control')
|
||||||
|
await page.keyboard.down('Control')
|
||||||
|
|
||||||
while (!middlePixelIsBackgroundColor && maxZoomOuts > 0) {
|
while (!middlePixelIsBackgroundColor && maxZoomOuts > 0) {
|
||||||
await page.keyboard.down('Control')
|
|
||||||
await page.mouse.move(600, 460)
|
|
||||||
await page.mouse.down({ button: 'right' })
|
|
||||||
await page.mouse.move(600, 50, { steps: 20 })
|
|
||||||
await page.mouse.up({ button: 'right' })
|
|
||||||
await page.keyboard.up('Control')
|
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
await page.mouse.move(650, 460)
|
||||||
|
console.time('moved to start point')
|
||||||
|
await page.mouse.down({ button: 'right' })
|
||||||
|
console.time('moused down')
|
||||||
|
await page.mouse.move(650, 50, { steps: 20 })
|
||||||
|
console.time('moved to end point')
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await page.mouse.up({ button: 'right' })
|
||||||
|
console.time('moused up')
|
||||||
maxZoomOuts--
|
maxZoomOuts--
|
||||||
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 10
|
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 15
|
||||||
}
|
}
|
||||||
|
await page.keyboard.up('Control')
|
||||||
|
|
||||||
expect(middlePixelIsBackgroundColor, {
|
expect(middlePixelIsBackgroundColor, {
|
||||||
message: 'We should not see the default planes',
|
message: 'We should not see the default planes',
|
||||||
@ -678,13 +689,12 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
toolbar,
|
toolbar,
|
||||||
viewport,
|
|
||||||
}) => {
|
}) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const legoDir = path.join(dir, 'lego')
|
const legoDir = path.join(dir, 'lego')
|
||||||
await fsp.mkdir(legoDir, { recursive: true })
|
await fsp.mkdir(legoDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('lego.kcl'),
|
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
|
||||||
path.join(legoDir, 'main.kcl')
|
path.join(legoDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -697,11 +707,8 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
await scene.loadingIndicator.waitFor({ state: 'detached' })
|
await scene.loadingIndicator.waitFor({ state: 'detached' })
|
||||||
})
|
})
|
||||||
await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => {
|
await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => {
|
||||||
await scene.expectPixelColor(
|
// TODO: use the viewport size to pick the center point, but the `viewport` fixture's values were wrong.
|
||||||
[143, 143, 143],
|
await scene.expectPixelColor([116, 116, 116], { x: 500, y: 250 }, 15)
|
||||||
{ x: (viewport?.width ?? 1200) / 2, y: (viewport?.height ?? 500) / 2 },
|
|
||||||
15
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -791,6 +798,74 @@ plane002 = offsetPlane(XZ, offset = -2 * x)`
|
|||||||
await page.getByTestId('custom-cmd-send-button').click()
|
await page.getByTestId('custom-cmd-send-button').click()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test('scale other than default works with sketch mode', async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
toolbar,
|
||||||
|
editor,
|
||||||
|
scene,
|
||||||
|
}) => {
|
||||||
|
await test.step('Load the washer code', async () => {
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`@settings(defaultLengthUnit = in)
|
||||||
|
|
||||||
|
innerDiameter = 0.203
|
||||||
|
outerDiameter = 0.438
|
||||||
|
thicknessMax = 0.038
|
||||||
|
thicknessMin = 0.024
|
||||||
|
washerSketch = startSketchOn(XY)
|
||||||
|
|> circle(center = [0, 0], radius = outerDiameter / 2)
|
||||||
|
|
||||||
|
washer = extrude(washerSketch, length = thicknessMax)`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
})
|
||||||
|
const [circleCenterClick] = scene.makeMouseHelpers(650, 300)
|
||||||
|
const [circleRadiusClick] = scene.makeMouseHelpers(800, 320)
|
||||||
|
const [washerFaceClick] = scene.makeMouseHelpers(657, 286)
|
||||||
|
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await test.step('Start sketching on the washer face', async () => {
|
||||||
|
await toolbar.startSketchPlaneSelection()
|
||||||
|
await washerFaceClick()
|
||||||
|
await page.waitForTimeout(600) // engine animation
|
||||||
|
await toolbar.expectToolbarMode.toBe('sketching')
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Draw a circle and verify code', async () => {
|
||||||
|
// select circle tool
|
||||||
|
await expect
|
||||||
|
.poll(async () => {
|
||||||
|
await toolbar.circleBtn.click()
|
||||||
|
return toolbar.circleBtn.getAttribute('aria-pressed')
|
||||||
|
})
|
||||||
|
.toBe('true')
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await circleCenterClick()
|
||||||
|
// this number will be different if the scale is not set correctly for inches
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
'circle(sketch001, center = [0.06, -0.06]'
|
||||||
|
)
|
||||||
|
await circleRadiusClick()
|
||||||
|
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
'circle(sketch001, center = [0.06, -0.06], radius = 0.18'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Exit sketch mode', async () => {
|
||||||
|
await toolbar.exitSketch()
|
||||||
|
await toolbar.expectToolbarMode.toBe('modeling')
|
||||||
|
|
||||||
|
await toolbar.selectUnit('Yards')
|
||||||
|
await editor.expectEditor.toContain('@settings(defaultLengthUnit = yd)')
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
async function clickExportButton(page: Page) {
|
async function clickExportButton(page: Page) {
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
import { Page } from '@playwright/test'
|
import type { Page } from '@playwright/test'
|
||||||
import { test, expect } from './zoo-test'
|
import { roundOff, uuidv4 } from '@src/lib/utils'
|
||||||
import fs from 'node:fs/promises'
|
import fs from 'node:fs/promises'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { HomePageFixture } from './fixtures/homePageFixture'
|
|
||||||
|
|
||||||
|
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||||
|
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
|
||||||
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||||
|
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
||||||
import {
|
import {
|
||||||
getMovementUtils,
|
|
||||||
getUtils,
|
|
||||||
PERSIST_MODELING_CONTEXT,
|
PERSIST_MODELING_CONTEXT,
|
||||||
TEST_COLORS,
|
TEST_COLORS,
|
||||||
|
getMovementUtils,
|
||||||
|
getUtils,
|
||||||
orRunWhenFullSuiteEnabled,
|
orRunWhenFullSuiteEnabled,
|
||||||
} from './test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
import { uuidv4, roundOff } from 'lib/utils'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
import { SceneFixture } from './fixtures/sceneFixture'
|
|
||||||
import { ToolbarFixture } from './fixtures/toolbarFixture'
|
|
||||||
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 ({
|
||||||
@ -113,7 +113,8 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([2.61, -4.01], %)
|
|> startProfileAt([2.61, -4.01], %)
|
||||||
|> xLine(length = 8.73)
|
|> xLine(length = 8.73)
|
||||||
|> tangentialArcTo([8.33, -1.31], %)`
|
|> tangentialArcTo([8.33, -1.31], %)`
|
||||||
@ -159,7 +160,10 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.mouse.click(700, 200)
|
await page.mouse.click(700, 200)
|
||||||
|
|
||||||
await expect.poll(u.normalisedEditorCode, { timeout: 1000 })
|
await expect.poll(u.normalisedEditorCode, { timeout: 1000 })
|
||||||
.toBe(`sketch002 = startSketchOn(XZ)
|
.toBe(`@settings(defaultLengthUnit = in)
|
||||||
|
|
||||||
|
|
||||||
|
sketch002 = startSketchOn(XZ)
|
||||||
sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
||||||
|> yLine(length = 12.34)
|
|> yLine(length = 12.34)
|
||||||
|
|
||||||
@ -475,7 +479,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit=in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> circle(center = [4.61, -5.01], radius = 8)`
|
|> circle(center = [4.61, -5.01], radius = 8)`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -560,12 +565,14 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
test('Can edit a sketch that has been extruded in the same pipe', async ({
|
test('Can edit a sketch that has been extruded in the same pipe', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
editor,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit=in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([4.61, -10.01], %)
|
|> startProfileAt([4.61, -10.01], %)
|
||||||
|> line(end = [12.73, -0.09])
|
|> line(end = [12.73, -0.09])
|
||||||
|> tangentialArcTo([24.95, -0.38], %)
|
|> tangentialArcTo([24.95, -0.38], %)
|
||||||
@ -650,26 +657,29 @@ 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)
|
||||||
|
|
||||||
// expect the code to have changed
|
// expect the code to have changed
|
||||||
await expect(page.locator('.cm-content'))
|
await editor.expectEditor.toContain(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)
|
`sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([7.12, -12.68], %)
|
|> startProfileAt([7.12, -12.68], %)
|
||||||
|> line(end = [12.68, -1.09])
|
|> line(end = [12.68, -1.09])
|
||||||
|> tangentialArcTo([24.89, 0.68], %)
|
|> tangentialArcTo([24.89, 0.68], %)
|
||||||
|> close()
|
|> close()
|
||||||
|> extrude(length = 5)
|
|> extrude(length = 5)`,
|
||||||
`)
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Can edit a sketch that has been revolved in the same pipe', async ({
|
test('Can edit a sketch that has been revolved in the same pipe', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
|
editor,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit=in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([4.61, -14.01], %)
|
|> startProfileAt([4.61, -14.01], %)
|
||||||
|> line(end = [12.73, -0.09])
|
|> line(end = [12.73, -0.09])
|
||||||
|> tangentialArcTo([24.95, -5.38], %)
|
|> tangentialArcTo([24.95, -5.38], %)
|
||||||
@ -754,14 +764,16 @@ 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)
|
||||||
|
|
||||||
// expect the code to have changed
|
// expect the code to have changed
|
||||||
await expect(page.locator('.cm-content'))
|
await editor.expectEditor.toContain(
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)
|
`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([24.95, -5.38], %)
|
||||||
|> line(end = [1.97, 2.06])
|
|> line(end = [1.97, 2.06])
|
||||||
|> close()
|
|> close()
|
||||||
|> revolve(axis = "X")`)
|
|> revolve(axis = "X")`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
})
|
})
|
||||||
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)
|
||||||
@ -789,7 +801,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
200
|
200
|
||||||
)
|
)
|
||||||
|
|
||||||
let codeStr = 'sketch001 = startSketchOn(XY)'
|
let codeStr =
|
||||||
|
'@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XY)'
|
||||||
|
|
||||||
await page.mouse.click(center.x, viewportSize.height * 0.55)
|
await page.mouse.click(center.x, viewportSize.height * 0.55)
|
||||||
await expect(u.codeLocator).toHaveText(codeStr)
|
await expect(u.codeLocator).toHaveText(codeStr)
|
||||||
@ -868,7 +881,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
|
|
||||||
await u.openDebugPanel()
|
await u.openDebugPanel()
|
||||||
|
|
||||||
const code = `sketch001 = startSketchOn(-XZ)
|
const code = `@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(-XZ)
|
||||||
profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
|
profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
|
||||||
scale * 34.8
|
scale * 34.8
|
||||||
)}], sketch001)
|
)}], sketch001)
|
||||||
@ -898,7 +912,7 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
|
|||||||
await page.mouse.move(700, 200, { steps: 10 })
|
await page.mouse.move(700, 200, { steps: 10 })
|
||||||
await page.mouse.click(700, 200, { delay: 200 })
|
await page.mouse.click(700, 200, { delay: 200 })
|
||||||
await expect(page.locator('.cm-content')).toHaveText(
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
`sketch001 = startSketchOn(-XZ)`
|
`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(-XZ)`
|
||||||
)
|
)
|
||||||
|
|
||||||
let prevContent = await page.locator('.cm-content').innerText()
|
let prevContent = await page.locator('.cm-content').innerText()
|
||||||
@ -1426,7 +1440,8 @@ test.describe(`Sketching with offset planes`, () => {
|
|||||||
await context.addInitScript(() => {
|
await context.addInitScript(() => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`offsetPlane001 = offsetPlane(XY, offset = 10)`
|
`@settings(defaultLengthUnit = in)
|
||||||
|
offsetPlane001 = offsetPlane(XY, offset = 10)`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1440,7 +1455,7 @@ test.describe(`Sketching with offset planes`, () => {
|
|||||||
await test.step(`Hovering should highlight code`, async () => {
|
await test.step(`Hovering should highlight code`, async () => {
|
||||||
await planeHover()
|
await planeHover()
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
activeLines: [`offsetPlane001=offsetPlane(XY,offset=10)`],
|
activeLines: [`@settings(defaultLengthUnit = in)`],
|
||||||
diagnostics: [],
|
diagnostics: [],
|
||||||
highlightedCode: 'offsetPlane(XY, offset = 10)',
|
highlightedCode: 'offsetPlane(XY, offset = 10)',
|
||||||
})
|
})
|
||||||
@ -1453,7 +1468,7 @@ test.describe(`Sketching with offset planes`, () => {
|
|||||||
await expect(toolbar.lineBtn).toBeEnabled()
|
await expect(toolbar.lineBtn).toBeEnabled()
|
||||||
await editor.expectEditor.toContain('startSketchOn(offsetPlane001)')
|
await editor.expectEditor.toContain('startSketchOn(offsetPlane001)')
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
activeLines: [`offsetPlane001=offsetPlane(XY,offset=10)`],
|
activeLines: [`@settings(defaultLengthUnit = in)`],
|
||||||
diagnostics: [],
|
diagnostics: [],
|
||||||
highlightedCode: '',
|
highlightedCode: '',
|
||||||
})
|
})
|
||||||
@ -1604,7 +1619,8 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
await context.addInitScript(() => {
|
await context.addInitScript(() => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
profile002 = startProfileAt([40.68, 87.67], sketch001)
|
profile002 = startProfileAt([40.68, 87.67], sketch001)
|
||||||
|> xLine(length = 239.17)
|
|> xLine(length = 239.17)
|
||||||
profile003 = startProfileAt([206.63, -56.73], sketch001)
|
profile003 = startProfileAt([206.63, -56.73], sketch001)
|
||||||
@ -2172,7 +2188,8 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
profile001 = startProfileAt([6.24, 4.54], sketch001)
|
profile001 = startProfileAt([6.24, 4.54], sketch001)
|
||||||
|> line(end = [-0.41, 6.99])
|
|> line(end = [-0.41, 6.99])
|
||||||
|> line(end = [8.61, 0.74])
|
|> line(end = [8.61, 0.74])
|
||||||
@ -2317,7 +2334,8 @@ profile004 = circleThreePoint(sketch001, p1 = [13.44, -6.8], p2 = [13.39, -2.07]
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
profile001 = startProfileAt([6.24, 4.54], sketch001)
|
profile001 = startProfileAt([6.24, 4.54], sketch001)
|
||||||
|> line(end = [-0.41, 6.99])
|
|> line(end = [-0.41, 6.99])
|
||||||
|> line(end = [8.61, 0.74])
|
|> line(end = [8.61, 0.74])
|
||||||
@ -2422,7 +2440,8 @@ profile003 = circle(sketch001, center = [6.92, -4.2], radius = 3.16)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
profile001 = startProfileAt([-63.43, 193.08], sketch001)
|
profile001 = startProfileAt([-63.43, 193.08], sketch001)
|
||||||
|> line(end = [168.52, 149.87])
|
|> line(end = [168.52, 149.87])
|
||||||
|> line(end = [190.29, -39.18])
|
|> line(end = [190.29, -39.18])
|
||||||
@ -2486,7 +2505,11 @@ extrude001 = extrude(profile003, length = 5)
|
|||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem('persistCode', `myVar = 5`)
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`@settings(defaultLengthUnit = in)
|
||||||
|
myVar = 5`
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
@ -2533,7 +2556,8 @@ extrude001 = extrude(profile003, length = 5)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
profile001 = startProfileAt([85.19, 338.59], sketch001)
|
profile001 = startProfileAt([85.19, 338.59], sketch001)
|
||||||
|> line(end = [213.3, -94.52])
|
|> line(end = [213.3, -94.52])
|
||||||
|> line(end = [-230.09, -55.34])
|
|> line(end = [-230.09, -55.34])
|
||||||
@ -2575,7 +2599,8 @@ profile002 = startProfileAt([85.81, 52.55], sketch002)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`thePart = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
thePart = startSketchOn(XZ)
|
||||||
|> startProfileAt([7.53, 10.51], %)
|
|> startProfileAt([7.53, 10.51], %)
|
||||||
|> line(end = [12.54, 1.83])
|
|> line(end = [12.54, 1.83])
|
||||||
|> line(end = [6.65, -6.91])
|
|> line(end = [6.65, -6.91])
|
||||||
@ -2636,7 +2661,8 @@ extrude001 = extrude(thePart, length = 75)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
profile001 = startProfileAt([6.71, -3.66], sketch001)
|
profile001 = startProfileAt([6.71, -3.66], sketch001)
|
||||||
|> line(end = [2.65, 9.02], tag = $seg02)
|
|> line(end = [2.65, 9.02], tag = $seg02)
|
||||||
|> line(end = [3.73, -9.36], tag = $seg01)
|
|> line(end = [3.73, -9.36], tag = $seg01)
|
||||||
@ -2809,7 +2835,8 @@ extrude003 = extrude(profile011, length = 2.5)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
profile001 = startProfileAt([34, 42.66], sketch001)
|
profile001 = startProfileAt([34, 42.66], sketch001)
|
||||||
|> line(end = [102.65, 151.99])
|
|> line(end = [102.65, 151.99])
|
||||||
|> line(end = [76, -138.66])
|
|> line(end = [76, -138.66])
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import type { Models } from '@kittycad/lib'
|
||||||
import { secrets } from './secrets'
|
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
|
||||||
import {
|
|
||||||
Paths,
|
|
||||||
doExport,
|
|
||||||
getUtils,
|
|
||||||
settingsToToml,
|
|
||||||
orRunWhenFullSuiteEnabled,
|
|
||||||
} from './test-utils'
|
|
||||||
import { Models } from '@kittycad/lib'
|
|
||||||
import fsp from 'fs/promises'
|
|
||||||
import { spawn } from 'child_process'
|
import { spawn } from 'child_process'
|
||||||
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
|
import fsp from 'fs/promises'
|
||||||
import JSZip from 'jszip'
|
import JSZip from 'jszip'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates'
|
|
||||||
import { SceneFixture } from './fixtures/sceneFixture'
|
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||||
import { CmdBarFixture } from './fixtures/cmdBarFixture'
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||||
|
import { secrets } from '@e2e/playwright/secrets'
|
||||||
|
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
||||||
|
import type { Paths } from '@e2e/playwright/test-utils'
|
||||||
|
import {
|
||||||
|
doExport,
|
||||||
|
getUtils,
|
||||||
|
orRunWhenFullSuiteEnabled,
|
||||||
|
settingsToToml,
|
||||||
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.beforeEach(async ({ page, context }) => {
|
test.beforeEach(async ({ page, context }) => {
|
||||||
// Make the user avatar image always 404
|
// Make the user avatar image always 404
|
||||||
@ -76,11 +77,11 @@ part001 = startSketchOn(-XZ)
|
|||||||
|> xLine(endAbsolute = totalLen, tag = $seg03)
|
|> xLine(endAbsolute = totalLen, tag = $seg03)
|
||||||
|> yLine(length = -armThick, tag = $seg01)
|
|> yLine(length = -armThick, tag = $seg01)
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle = HALF_TURN,
|
angle = turns::HALF_TURN,
|
||||||
offset = -armThick,
|
offset = -armThick,
|
||||||
intersectTag = seg04
|
intersectTag = seg04
|
||||||
}, %)
|
}, %)
|
||||||
|> angledLineToY([segAng(seg04, %) + 180, ZERO], %)
|
|> angledLineToY([segAng(seg04, %) + 180, turns::ZERO], %)
|
||||||
|> angledLineToY({
|
|> angledLineToY({
|
||||||
angle = -bottomAng,
|
angle = -bottomAng,
|
||||||
to = -totalHeightHalf - armThick,
|
to = -totalHeightHalf - armThick,
|
||||||
@ -88,12 +89,12 @@ part001 = startSketchOn(-XZ)
|
|||||||
|> xLine(length = endAbsolute = segEndX(seg03) + 0)
|
|> xLine(length = endAbsolute = segEndX(seg03) + 0)
|
||||||
|> yLine(length = -segLen(seg01, %))
|
|> yLine(length = -segLen(seg01, %))
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle = HALF_TURN,
|
angle = turns::HALF_TURN,
|
||||||
offset = -armThick,
|
offset = -armThick,
|
||||||
intersectTag = seg02
|
intersectTag = seg02
|
||||||
}, %)
|
}, %)
|
||||||
|> angledLineToY([segAng(seg02, %) + 180, -baseHeight], %)
|
|> angledLineToY([segAng(seg02, %) + 180, -baseHeight], %)
|
||||||
|> xLine(endAbsolute = ZERO)
|
|> xLine(endAbsolute = turns::ZERO)
|
||||||
|> close()
|
|> close()
|
||||||
|> extrude(length = 4)`
|
|> extrude(length = 4)`
|
||||||
)
|
)
|
||||||
@ -345,7 +346,9 @@ const extrudeDefaultPlane = async (
|
|||||||
app: {
|
app: {
|
||||||
onboarding_status: 'dismissed',
|
onboarding_status: 'dismissed',
|
||||||
show_debug_panel: true,
|
show_debug_panel: true,
|
||||||
theme: 'dark',
|
appearance: {
|
||||||
|
theme: 'dark',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
project: {
|
project: {
|
||||||
default_project_name: 'project-$nnn',
|
default_project_name: 'project-$nnn',
|
||||||
@ -452,7 +455,7 @@ test(
|
|||||||
await page.waitForTimeout(700) // TODO detect animation ending, or disable animation
|
await page.waitForTimeout(700) // TODO detect animation ending, or disable animation
|
||||||
|
|
||||||
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([182.59, -246.32], sketch001)`
|
||||||
await expect(page.locator('.cm-content')).toHaveText(code)
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
@ -470,7 +473,7 @@ test(
|
|||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
code += `
|
code += `
|
||||||
|> xLine(length = 7.25)`
|
|> xLine(length = 184.3)`
|
||||||
await expect(page.locator('.cm-content')).toHaveText(code)
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
||||||
|
|
||||||
await page
|
await page
|
||||||
@ -628,7 +631,7 @@ test(
|
|||||||
mask: [page.getByTestId('model-state-indicator')],
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
})
|
})
|
||||||
await expect(page.locator('.cm-content')).toHaveText(
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
`sketch001 = startSketchOn(XZ)profile001 = circle(sketch001, center = [14.44, -2.44], radius = 1)`
|
`sketch001 = startSketchOn(XZ)profile001 = circle(sketch001, center = [366.89, -62.01], radius = 1)`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -665,7 +668,7 @@ test.describe(
|
|||||||
|
|
||||||
const startXPx = 600
|
const startXPx = 600
|
||||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||||
code += `profile001 = startProfileAt([7.19, -9.7], sketch001)`
|
code += `profile001 = startProfileAt([182.59, -246.32], sketch001)`
|
||||||
await expect(u.codeLocator).toHaveText(code)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
@ -673,7 +676,7 @@ test.describe(
|
|||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
code += `
|
code += `
|
||||||
|> xLine(length = 7.25)`
|
|> xLine(length = 184.3)`
|
||||||
await expect(u.codeLocator).toHaveText(code)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
|
|
||||||
await page
|
await page
|
||||||
@ -688,7 +691,7 @@ test.describe(
|
|||||||
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
||||||
|
|
||||||
code += `
|
code += `
|
||||||
|> tangentialArcTo([21.7, -2.44], %)`
|
|> tangentialArcTo([551.2, -62.01], %)`
|
||||||
await expect(u.codeLocator).toHaveText(code)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
|
|
||||||
// click tangential arc tool again to unequip it
|
// click tangential arc tool again to unequip it
|
||||||
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 66 KiB |
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"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",
|
"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",
|
"prompt": "make this neon green please, use #39FF14",
|
||||||
"source_ranges": [
|
"source_ranges": [
|
||||||
{
|
{
|
||||||
@ -30,4 +30,4 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"kcl_version": "0.2.48"
|
"kcl_version": "0.2.48"
|
||||||
}
|
}
|
||||||
|
@ -29,5 +29,5 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"kcl_version": "0.2.54"
|
"kcl_version": "0.2.57"
|
||||||
}
|
}
|
@ -1,17 +1,19 @@
|
|||||||
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
import type { SaveSettingsPayload } from '@src/lib/settings/settingsTypes'
|
||||||
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
|
import { Themes } from '@src/lib/theme'
|
||||||
import { Themes } from 'lib/theme'
|
import type { DeepPartial } from '@src/lib/types'
|
||||||
import { DeepPartial } from 'lib/types'
|
import { onboardingPaths } from '@src/routes/Onboarding/paths'
|
||||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
|
||||||
|
import type { Settings } from '@rust/kcl-lib/bindings/Settings'
|
||||||
|
|
||||||
export const IS_PLAYWRIGHT_KEY = 'playwright'
|
export const IS_PLAYWRIGHT_KEY = 'playwright'
|
||||||
|
|
||||||
export const TEST_SETTINGS_KEY = '/settings.toml'
|
export const TEST_SETTINGS_KEY = '/settings.toml'
|
||||||
export const TEST_SETTINGS: DeepPartial<Settings> = {
|
export const TEST_SETTINGS: DeepPartial<Settings> = {
|
||||||
app: {
|
app: {
|
||||||
theme: Themes.Dark,
|
appearance: {
|
||||||
|
theme: Themes.Dark,
|
||||||
|
},
|
||||||
onboarding_status: 'dismissed',
|
onboarding_status: 'dismissed',
|
||||||
project_directory: '',
|
|
||||||
show_debug_panel: true,
|
show_debug_panel: true,
|
||||||
},
|
},
|
||||||
modeling: {
|
modeling: {
|
||||||
@ -22,6 +24,7 @@ export const TEST_SETTINGS: DeepPartial<Settings> = {
|
|||||||
},
|
},
|
||||||
project: {
|
project: {
|
||||||
default_project_name: 'project-$nnn',
|
default_project_name: 'project-$nnn',
|
||||||
|
directory: '',
|
||||||
},
|
},
|
||||||
text_editor: {
|
text_editor: {
|
||||||
text_wrapping: true,
|
text_wrapping: true,
|
||||||
@ -54,7 +57,7 @@ export const TEST_SETTINGS_ONBOARDING_START: DeepPartial<Settings> = {
|
|||||||
|
|
||||||
export const TEST_SETTINGS_DEFAULT_THEME: DeepPartial<Settings> = {
|
export const TEST_SETTINGS_DEFAULT_THEME: DeepPartial<Settings> = {
|
||||||
...TEST_SETTINGS,
|
...TEST_SETTINGS,
|
||||||
app: { ...TEST_SETTINGS.app, theme: Themes.System },
|
app: { ...TEST_SETTINGS.app, appearance: { theme: Themes.System } },
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TEST_SETTINGS_CORRUPTED = {
|
export const TEST_SETTINGS_CORRUPTED = {
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import type { EngineCommand } from '@src/lang/std/artifactGraph'
|
||||||
import { commonPoints, getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
|
import { uuidv4 } from '@src/lib/utils'
|
||||||
import { EngineCommand } from 'lang/std/artifactGraph'
|
|
||||||
import { uuidv4 } from 'lib/utils'
|
import {
|
||||||
|
commonPoints,
|
||||||
|
getUtils,
|
||||||
|
orRunWhenFullSuiteEnabled,
|
||||||
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Test network and connection issues', () => {
|
test.describe('Test network and connection issues', () => {
|
||||||
test(
|
test(
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
|
orRunWhenFullSuiteEnabled,
|
||||||
runningOnLinux,
|
runningOnLinux,
|
||||||
runningOnMac,
|
runningOnMac,
|
||||||
runningOnWindows,
|
runningOnWindows,
|
||||||
orRunWhenFullSuiteEnabled,
|
} from '@e2e/playwright/test-utils'
|
||||||
} from './test-utils'
|
|
||||||
|
|
||||||
describe('platform detection utilities', () => {
|
describe('platform detection utilities', () => {
|
||||||
const originalPlatform = process.platform
|
const originalPlatform = process.platform
|
||||||
|
@ -1,32 +1,29 @@
|
|||||||
import {
|
import * as TOML from '@iarna/toml'
|
||||||
expect,
|
import type { Models } from '@kittycad/lib'
|
||||||
BrowserContext,
|
import type { BrowserContext, Locator, Page, TestInfo } from '@playwright/test'
|
||||||
TestInfo,
|
import { expect } from '@playwright/test'
|
||||||
Locator,
|
import type { EngineCommand } from '@src/lang/std/artifactGraph'
|
||||||
Page,
|
import type { Configuration } from '@src/lang/wasm'
|
||||||
} from '@playwright/test'
|
import { COOKIE_NAME } from '@src/lib/constants'
|
||||||
import { test } from './zoo-test'
|
import { reportRejection } from '@src/lib/trap'
|
||||||
import { EngineCommand } from 'lang/std/artifactGraph'
|
import type { DeepPartial } from '@src/lib/types'
|
||||||
|
import { isArray } from '@src/lib/utils'
|
||||||
import fsp from 'fs/promises'
|
import fsp from 'fs/promises'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import pixelMatch from 'pixelmatch'
|
import pixelMatch from 'pixelmatch'
|
||||||
|
import type { Protocol } from 'playwright-core/types/protocol'
|
||||||
import { PNG } from 'pngjs'
|
import { PNG } from 'pngjs'
|
||||||
import { Protocol } from 'playwright-core/types/protocol'
|
|
||||||
import type { Models } from '@kittycad/lib'
|
import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
|
||||||
import { COOKIE_NAME } from 'lib/constants'
|
|
||||||
import { secrets } from './secrets'
|
import { isErrorWhitelisted } from '@e2e/playwright/lib/console-error-whitelist'
|
||||||
|
import { secrets } from '@e2e/playwright/secrets'
|
||||||
import {
|
import {
|
||||||
TEST_SETTINGS_KEY,
|
|
||||||
TEST_SETTINGS,
|
|
||||||
IS_PLAYWRIGHT_KEY,
|
IS_PLAYWRIGHT_KEY,
|
||||||
} from './storageStates'
|
TEST_SETTINGS,
|
||||||
import * as TOML from '@iarna/toml'
|
TEST_SETTINGS_KEY,
|
||||||
import { isErrorWhitelisted } from './lib/console-error-whitelist'
|
} from '@e2e/playwright/storageStates'
|
||||||
import { isArray } from 'lib/utils'
|
import { test } from '@e2e/playwright/zoo-test'
|
||||||
import { reportRejection } from 'lib/trap'
|
|
||||||
import { DeepPartial } from 'lib/types'
|
|
||||||
import { Configuration } from 'lang/wasm'
|
|
||||||
import { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
|
|
||||||
|
|
||||||
const toNormalizedCode = (text: string) => {
|
const toNormalizedCode = (text: string) => {
|
||||||
return text.replace(/\s+/g, '')
|
return text.replace(/\s+/g, '')
|
||||||
@ -683,8 +680,8 @@ const _makeTemplate = (
|
|||||||
isArray(currentOptions)
|
isArray(currentOptions)
|
||||||
? currentOptions[i]
|
? currentOptions[i]
|
||||||
: typeof currentOptions === 'number'
|
: typeof currentOptions === 'number'
|
||||||
? currentOptions
|
? currentOptions
|
||||||
: ''
|
: ''
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -903,15 +900,21 @@ export async function setup(
|
|||||||
settings: {
|
settings: {
|
||||||
...TEST_SETTINGS,
|
...TEST_SETTINGS,
|
||||||
app: {
|
app: {
|
||||||
|
appearance: {
|
||||||
|
...TEST_SETTINGS.app?.appearance,
|
||||||
|
theme: 'dark',
|
||||||
|
},
|
||||||
...TEST_SETTINGS.project,
|
...TEST_SETTINGS.project,
|
||||||
project_directory: TEST_SETTINGS.app?.project_directory,
|
|
||||||
onboarding_status: 'dismissed',
|
onboarding_status: 'dismissed',
|
||||||
theme: 'dark',
|
},
|
||||||
|
project: {
|
||||||
|
...TEST_SETTINGS.project,
|
||||||
|
directory: TEST_SETTINGS.project?.directory,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
IS_PLAYWRIGHT_KEY,
|
IS_PLAYWRIGHT_KEY,
|
||||||
PLAYWRIGHT_TEST_DIR: TEST_SETTINGS.app?.project_directory || '',
|
PLAYWRIGHT_TEST_DIR: TEST_SETTINGS.project?.directory || '',
|
||||||
PERSIST_MODELING_CONTEXT,
|
PERSIST_MODELING_CONTEXT,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -1112,21 +1115,25 @@ export async function pollEditorLinesSelectedLength(page: Page, lines: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function settingsToToml(settings: DeepPartial<Configuration>) {
|
export function settingsToToml(settings: DeepPartial<Configuration>) {
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
return TOML.stringify(settings as any)
|
return TOML.stringify(settings as any)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tomlToSettings(toml: string): DeepPartial<Configuration> {
|
export function tomlToSettings(toml: string): DeepPartial<Configuration> {
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
return TOML.parse(toml)
|
return TOML.parse(toml)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tomlToPerProjectSettings(
|
export function tomlToPerProjectSettings(
|
||||||
toml: string
|
toml: string
|
||||||
): DeepPartial<ProjectConfiguration> {
|
): DeepPartial<ProjectConfiguration> {
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
return TOML.parse(toml)
|
return TOML.parse(toml)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function perProjectsettingsToToml(
|
export function perProjectsettingsToToml(
|
||||||
settings: DeepPartial<ProjectConfiguration>
|
settings: DeepPartial<ProjectConfiguration>
|
||||||
) {
|
) {
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
return TOML.stringify(settings as any)
|
return TOML.stringify(settings as any)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import type { EngineCommand } from '@src/lang/std/artifactGraph'
|
||||||
import { EngineCommand } from 'lang/std/artifactGraph'
|
import { uuidv4 } from '@src/lib/utils'
|
||||||
import { uuidv4 } from 'lib/utils'
|
|
||||||
import { getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
|
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => {
|
test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => {
|
||||||
test('Can move camera reliably', async ({ page, context, homePage }) => {
|
test('Can move camera reliably', async ({ page, context, homePage }) => {
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { XOR } from '@src/lib/utils'
|
||||||
import * as fsp from 'fs/promises'
|
import * as fsp from 'fs/promises'
|
||||||
import {
|
|
||||||
getUtils,
|
|
||||||
TEST_COLORS,
|
|
||||||
pollEditorLinesSelectedLength,
|
|
||||||
executorInputPath,
|
|
||||||
orRunWhenFullSuiteEnabled,
|
|
||||||
} from './test-utils'
|
|
||||||
import { XOR } from 'lib/utils'
|
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
|
||||||
|
import {
|
||||||
|
TEST_COLORS,
|
||||||
|
getUtils,
|
||||||
|
orRunWhenFullSuiteEnabled,
|
||||||
|
pollEditorLinesSelectedLength,
|
||||||
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
||||||
test('Can constrain line length', async ({ page, homePage }) => {
|
test('Can constrain line length', async ({ page, homePage }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
@ -81,7 +81,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 79
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 79
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> line(end = [74.36, 130.4], tag = $seg01)
|
|> line(end = [74.36, 130.4], tag = $seg01)
|
||||||
@ -145,7 +146,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 5
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 5
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> line(end = [74.36, 130.4], tag = $seg01)
|
|> line(end = [74.36, 130.4], tag = $seg01)
|
||||||
@ -159,31 +161,6 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
|> xLine(length = segLen(seg_what))
|
|> xLine(length = segLen(seg_what))
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])`
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])`
|
||||||
)
|
)
|
||||||
|
|
||||||
const isChecked = await createNewVariableCheckbox.isChecked()
|
|
||||||
const addVariable = testName === 'Add variable'
|
|
||||||
XOR(isChecked, addVariable) && // XOR because no need to click the checkbox if the state is already correct
|
|
||||||
(await createNewVariableCheckbox.click())
|
|
||||||
|
|
||||||
await page
|
|
||||||
.getByRole('button', { name: 'Add constraining value' })
|
|
||||||
.click()
|
|
||||||
|
|
||||||
// Wait for the codemod to take effect
|
|
||||||
await expect(page.locator('.cm-content')).toContainText(`angle: -57,`)
|
|
||||||
await expect(page.locator('.cm-content')).toContainText(
|
|
||||||
`offset: ${offset},`
|
|
||||||
)
|
|
||||||
|
|
||||||
await pollEditorLinesSelectedLength(page, 2)
|
|
||||||
const activeLinesContent = await page.locator('.cm-activeLine').all()
|
|
||||||
await expect(activeLinesContent[0]).toHaveText(
|
|
||||||
`|> line(end = [74.36, 130.4], tag = $seg01)`
|
|
||||||
)
|
|
||||||
await expect(activeLinesContent[1]).toHaveText(`}, %)`)
|
|
||||||
|
|
||||||
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
|
|
||||||
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
|
|
||||||
})
|
})
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
@ -277,7 +254,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 5
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 5
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> line(end = [74.36, 130.4])
|
|> line(end = [74.36, 130.4])
|
||||||
@ -387,7 +365,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 5
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 5
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> line(end = [74.36, 130.4])
|
|> line(end = [74.36, 130.4])
|
||||||
@ -486,13 +465,13 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
testName: 'Add variable, selecting axis',
|
testName: 'Add variable, selecting axis',
|
||||||
addVariable: true,
|
addVariable: true,
|
||||||
axisSelect: true,
|
axisSelect: true,
|
||||||
value: 'QUARTER_TURN - angle001',
|
value: 'turns::QUARTER_TURN - angle001',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testName: 'No variable, selecting axis',
|
testName: 'No variable, selecting axis',
|
||||||
addVariable: false,
|
addVariable: false,
|
||||||
axisSelect: true,
|
axisSelect: true,
|
||||||
value: 'QUARTER_TURN - 7',
|
value: 'turns::QUARTER_TURN - 7',
|
||||||
},
|
},
|
||||||
] as const
|
] as const
|
||||||
for (const { testName, addVariable, value, axisSelect } of cases) {
|
for (const { testName, addVariable, value, axisSelect } of cases) {
|
||||||
@ -500,7 +479,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 5
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 5
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> line(end = [74.36, 130.4])
|
|> line(end = [74.36, 130.4])
|
||||||
@ -602,7 +582,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 5
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 5
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> line(end = [74.36, 130.4])
|
|> line(end = [74.36, 130.4])
|
||||||
@ -688,7 +669,8 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 5
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 5
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> line(end = [74.36, 130.4])
|
|> line(end = [74.36, 130.4])
|
||||||
@ -768,7 +750,8 @@ part002 = startSketchOn(XZ)
|
|||||||
await page.addInitScript(async (customCode) => {
|
await page.addInitScript(async (customCode) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 5
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 5
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> line(end = [74.36, 130.4])
|
|> line(end = [74.36, 130.4])
|
||||||
@ -869,7 +852,8 @@ part002 = startSketchOn(XZ)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 5
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 5
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> line(end = [74.36, 130.4])
|
|> line(end = [74.36, 130.4])
|
||||||
@ -935,12 +919,12 @@ part002 = startSketchOn(XZ)
|
|||||||
test.describe('Axis & segment - no modal constraints', () => {
|
test.describe('Axis & segment - no modal constraints', () => {
|
||||||
const cases = [
|
const cases = [
|
||||||
{
|
{
|
||||||
codeAfter: `|> line(endAbsolute = [154.9, ZERO])`,
|
codeAfter: `|> line(endAbsolute = [154.9, turns::ZERO])`,
|
||||||
axisClick: { x: 950, y: 250 },
|
axisClick: { x: 950, y: 250 },
|
||||||
constraintName: 'Snap To X',
|
constraintName: 'Snap To X',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
codeAfter: `|> line(endAbsolute = [ZERO, 61.34])`,
|
codeAfter: `|> line(endAbsolute = [turns::ZERO, 61.34])`,
|
||||||
axisClick: { x: 600, y: 150 },
|
axisClick: { x: 600, y: 150 },
|
||||||
constraintName: 'Snap To Y',
|
constraintName: 'Snap To Y',
|
||||||
},
|
},
|
||||||
@ -950,7 +934,8 @@ part002 = startSketchOn(XZ)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 5
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 5
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> line(end = [74.36, 130.4])
|
|> line(end = [74.36, 130.4])
|
||||||
@ -1113,13 +1098,23 @@ test.describe('Electron constraint tests', () => {
|
|||||||
test(
|
test(
|
||||||
'Able to double click label to set constraint',
|
'Able to double click label to set constraint',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ page, context, homePage, scene, editor, toolbar }) => {
|
async ({ page, context, homePage, scene, editor, toolbar, cmdBar }) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'test-sample')
|
const bracketDir = path.join(dir, 'test-sample')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.writeFile(
|
||||||
executorInputPath('angled_line.kcl'),
|
path.join(bracketDir, 'main.kcl'),
|
||||||
path.join(bracketDir, 'main.kcl')
|
`@settings(defaultLengthUnit = in)
|
||||||
|
const part001 = startSketchOn(XY)
|
||||||
|
|> startProfileAt([4.83, 12.56], %)
|
||||||
|
|> line(end = [15.1, 2.48])
|
||||||
|
|> line(end = [3.15, -9.85], tag = $seg01)
|
||||||
|
|> line(end = [-15.17, -4.1])
|
||||||
|
|> angledLine([segAng(seg01), 12.35], %)
|
||||||
|
|> line(end = [-13.02, 10.03])
|
||||||
|
|> close()
|
||||||
|
|> extrude(length = 4)`,
|
||||||
|
'utf-8'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1137,6 +1132,14 @@ test.describe('Electron constraint tests', () => {
|
|||||||
await scene.waitForExecutionDone()
|
await scene.waitForExecutionDone()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
async function clickOnFirstSegmentLabel() {
|
||||||
|
const child = page
|
||||||
|
.locator('.segment-length-label-text')
|
||||||
|
.first()
|
||||||
|
.locator('xpath=..')
|
||||||
|
await child.dblclick()
|
||||||
|
}
|
||||||
|
|
||||||
await test.step('Double click to constrain', async () => {
|
await test.step('Double click to constrain', async () => {
|
||||||
// Enter sketch edit mode via feature tree
|
// Enter sketch edit mode via feature tree
|
||||||
await toolbar.openPane('feature-tree')
|
await toolbar.openPane('feature-tree')
|
||||||
@ -1144,21 +1147,19 @@ test.describe('Electron constraint tests', () => {
|
|||||||
await op.dblclick()
|
await op.dblclick()
|
||||||
await toolbar.closePane('feature-tree')
|
await toolbar.closePane('feature-tree')
|
||||||
|
|
||||||
const child = page
|
await clickOnFirstSegmentLabel()
|
||||||
.locator('.segment-length-label-text')
|
await cmdBar.progressCmdBar()
|
||||||
.first()
|
await editor.expectEditor.toContain('length001 = 15.3')
|
||||||
.locator('xpath=..')
|
await editor.expectEditor.toContain('|> angledLine([9, length001], %)')
|
||||||
await child.dblclick()
|
})
|
||||||
const cmdBarSubmitButton = page.getByRole('button', {
|
|
||||||
name: 'arrow right Continue',
|
await test.step('Double click again and expect failure', async () => {
|
||||||
})
|
await clickOnFirstSegmentLabel()
|
||||||
await cmdBarSubmitButton.click()
|
|
||||||
await expect(page.locator('.cm-content')).toContainText(
|
await expect(
|
||||||
'length001 = 15.3'
|
page.getByText('Unable to constrain the length of this segment')
|
||||||
)
|
).toBeVisible()
|
||||||
await expect(page.locator('.cm-content')).toContainText(
|
|
||||||
'|> angledLine([9, length001], %)'
|
|
||||||
)
|
|
||||||
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { uuidv4 } from '@src/lib/utils'
|
||||||
import { getUtils } from './test-utils'
|
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { TEST_CODE_GIZMO } from '@e2e/playwright/storageStates'
|
||||||
import { TEST_CODE_GIZMO } from './storageStates'
|
import { getUtils } from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Testing Gizmo', { tag: ['@skipWin'] }, () => {
|
test.describe('Testing Gizmo', { tag: ['@skipWin'] }, () => {
|
||||||
const cases = [
|
const cases = [
|
||||||
@ -255,7 +256,7 @@ test.describe(`Testing gizmo, fixture-based`, () => {
|
|||||||
await context.addInitScript(() => {
|
await context.addInitScript(() => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`
|
`@settings(defaultLengthUnit = in)
|
||||||
const sketch002 = startSketchOn(XZ)
|
const sketch002 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-108.83, -57.48], %)
|
|> startProfileAt([-108.83, -57.48], %)
|
||||||
|> angledLine([0, 105.13], %, $rectangleSegmentA001)
|
|> angledLine([0, 105.13], %, $rectangleSegmentA001)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
|
||||||
import { getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Test toggling perspective', () => {
|
test.describe('Test toggling perspective', () => {
|
||||||
test('via command palette and toggle', async ({ page, homePage }) => {
|
test('via command palette and toggle', async ({ page, homePage }) => {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import { FILE_EXT } from '@src/lib/constants'
|
||||||
import { getUtils } from './test-utils'
|
import { bracket } from '@src/lib/exampleKcl'
|
||||||
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 { getUtils } from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Testing in-app sample loading', () => {
|
test.describe('Testing in-app sample loading', () => {
|
||||||
/**
|
/**
|
||||||
@ -46,7 +47,7 @@ test.describe('Testing in-app sample loading', () => {
|
|||||||
page.getByRole('option', {
|
page.getByRole('option', {
|
||||||
name,
|
name,
|
||||||
})
|
})
|
||||||
const warningText = page.getByText('Overwrite current file and units?')
|
const warningText = page.getByText('Overwrite current file with sample?')
|
||||||
const confirmButton = page.getByRole('button', { name: 'Submit command' })
|
const confirmButton = page.getByRole('button', { name: 'Submit command' })
|
||||||
|
|
||||||
await test.step(`Precondition: check the initial code`, async () => {
|
await test.step(`Precondition: check the initial code`, async () => {
|
||||||
@ -110,11 +111,9 @@ test.describe('Testing in-app sample loading', () => {
|
|||||||
const commandMethodOption = page.getByRole('option', {
|
const commandMethodOption = page.getByRole('option', {
|
||||||
name: 'Overwrite',
|
name: 'Overwrite',
|
||||||
})
|
})
|
||||||
const newFileWarning = page.getByText(
|
const newFileWarning = page.getByText('Create a new file from sample?')
|
||||||
'Create a new file, overwrite project units?'
|
|
||||||
)
|
|
||||||
const overwriteWarning = page.getByText(
|
const overwriteWarning = page.getByText(
|
||||||
'Overwrite current file and units?'
|
'Overwrite current file with sample?'
|
||||||
)
|
)
|
||||||
const confirmButton = page.getByRole('button', { name: 'Submit command' })
|
const confirmButton = page.getByRole('button', { name: 'Submit command' })
|
||||||
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
|
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { Page } from '@playwright/test'
|
import type { Page } from '@playwright/test'
|
||||||
import { test, expect } from './zoo-test'
|
import type { LineInputsType } from '@src/lang/std/sketchcombos'
|
||||||
|
import { uuidv4 } from '@src/lib/utils'
|
||||||
|
|
||||||
|
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
|
||||||
import {
|
import {
|
||||||
deg,
|
deg,
|
||||||
getUtils,
|
getUtils,
|
||||||
wiggleMove,
|
|
||||||
orRunWhenFullSuiteEnabled,
|
orRunWhenFullSuiteEnabled,
|
||||||
} from './test-utils'
|
wiggleMove,
|
||||||
import { LineInputsType } from 'lang/std/sketchcombos'
|
} from '@e2e/playwright/test-utils'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
import { EditorFixture } from './fixtures/editorFixture'
|
|
||||||
|
|
||||||
test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
||||||
test('Hover over a segment should show its overlay, hovering over the input overlays should show its popover, clicking the input overlay should constrain/unconstrain it:\nfor the following segments', () => {
|
test('Hover over a segment should show its overlay, hovering over the input overlays should show its popover, clicking the input overlay should constrain/unconstrain it:\nfor the following segments', () => {
|
||||||
@ -210,7 +210,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([5 + 0, 20 + 0], %)
|
|> startProfileAt([5 + 0, 20 + 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 }, %)
|
||||||
@ -380,7 +381,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yRel001 = -14
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yRel001 = -14
|
||||||
xRel001 = 0.5
|
xRel001 = 0.5
|
||||||
angle001 = 3
|
angle001 = 3
|
||||||
len001 = 32
|
len001 = 32
|
||||||
@ -459,7 +461,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
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 }, %)
|
||||||
@ -590,7 +593,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
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 }, %)
|
||||||
@ -751,7 +755,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
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 }, %)
|
||||||
@ -831,7 +836,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
profile001 = startProfileAt([56.37, 120.33], sketch001)
|
profile001 = startProfileAt([56.37, 120.33], sketch001)
|
||||||
|> line(end = [162.86, 106.48])
|
|> line(end = [162.86, 106.48])
|
||||||
|> arcTo({
|
|> arcTo({
|
||||||
@ -957,7 +963,8 @@ profile001 = startProfileAt([56.37, 120.33], sketch001)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
part001 = startSketchOn(XZ)
|
||||||
|> circle(center = [1 + 0, 0], radius = 8)
|
|> circle(center = [1 + 0, 0], radius = 8)
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
@ -1077,7 +1084,8 @@ profile001 = startProfileAt([56.37, 120.33], sketch001)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
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 }, %)
|
||||||
@ -1351,7 +1359,8 @@ profile001 = startProfileAt([56.37, 120.33], sketch001)
|
|||||||
async ({ lineToBeDeleted, extraLine }) => {
|
async ({ lineToBeDeleted, extraLine }) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([5, 6], %)
|
|> startProfileAt([5, 6], %)
|
||||||
|> ${lineToBeDeleted}
|
|> ${lineToBeDeleted}
|
||||||
|> line(end = [-10, -15])
|
|> line(end = [-10, -15])
|
||||||
@ -1516,7 +1525,8 @@ profile001 = startProfileAt([56.37, 120.33], sketch001)
|
|||||||
async ({ lineToBeDeleted }) => {
|
async ({ lineToBeDeleted }) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([5, 6], %)
|
|> startProfileAt([5, 6], %)
|
||||||
|> ${lineToBeDeleted}
|
|> ${lineToBeDeleted}
|
||||||
|> line(end = [-10, -15])
|
|> line(end = [-10, -15])
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import type { Coords2d } from '@src/lang/std/sketch'
|
||||||
|
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
|
||||||
|
import { uuidv4 } from '@src/lib/utils'
|
||||||
|
|
||||||
import { commonPoints, getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
|
import {
|
||||||
import { Coords2d } from 'lang/std/sketch'
|
commonPoints,
|
||||||
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
|
getUtils,
|
||||||
import { uuidv4 } from 'lib/utils'
|
orRunWhenFullSuiteEnabled,
|
||||||
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
|
test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
|
||||||
test.setTimeout(90_000)
|
test.setTimeout(90_000)
|
||||||
@ -68,20 +72,20 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
|
|||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||||
await expect(page.locator('.cm-content')).toHaveText(
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)`
|
`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)`
|
||||||
)
|
)
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)
|
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)
|
||||||
|> xLine(length = ${commonPoints.num1})`)
|
|> xLine(length = ${commonPoints.num1})`)
|
||||||
|
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
|
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
|
||||||
commonPoints.startAt
|
commonPoints.startAt
|
||||||
}, sketch001)
|
}, sketch001)
|
||||||
|> xLine(length = ${commonPoints.num1})
|
|> xLine(length = ${commonPoints.num1})
|
||||||
@ -89,7 +93,7 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await page.mouse.click(startXPx, 500 - PUR * 20)
|
await page.mouse.click(startXPx, 500 - PUR * 20)
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
|
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
|
||||||
commonPoints.startAt
|
commonPoints.startAt
|
||||||
}, sketch001)
|
}, sketch001)
|
||||||
|> xLine(length = ${commonPoints.num1})
|
|> xLine(length = ${commonPoints.num1})
|
||||||
@ -260,7 +264,8 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-79.26, 95.04], %)
|
|> startProfileAt([-79.26, 95.04], %)
|
||||||
|> line(end = [112.54, 127.64], tag = $seg02)
|
|> line(end = [112.54, 127.64], tag = $seg02)
|
||||||
|> line(end = [170.36, -121.61], tag = $seg01)
|
|> line(end = [170.36, -121.61], tag = $seg01)
|
||||||
@ -528,7 +533,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
|
|||||||
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
|
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([20, 0], %)
|
|> startProfileAt([20, 0], %)
|
||||||
|> line(end = [7.13, 4 + 0])
|
|> line(end = [7.13, 4 + 0])
|
||||||
|> angledLine({ angle = 3 + 0, length = 3.14 + 0 }, %)
|
|> angledLine({ angle = 3 + 0, length = 3.14 + 0 }, %)
|
||||||
@ -747,7 +753,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
|
|||||||
await page.waitForTimeout(200)
|
await page.waitForTimeout(200)
|
||||||
|
|
||||||
await u.removeCurrentCode()
|
await u.removeCurrentCode()
|
||||||
await u.codeLocator.fill(`sketch001 = startSketchOn(XZ)
|
await u.codeLocator.fill(`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
||||||
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||||
|> angledLine([
|
|> angledLine([
|
||||||
@ -965,7 +972,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
|
|||||||
async ({ cases }) => {
|
async ({ cases }) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`yo = 79
|
`@settings(defaultLengthUnit = in)
|
||||||
|
yo = 79
|
||||||
part001 = startSketchOn(XZ)
|
part001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-7.54, -26.74], %)
|
|> startProfileAt([-7.54, -26.74], %)
|
||||||
|> ${cases[0].expectedCode}
|
|> ${cases[0].expectedCode}
|
||||||
@ -1020,7 +1028,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([-79.26, 95.04], %)
|
|> startProfileAt([-79.26, 95.04], %)
|
||||||
|> line(end = [112.54, 127.64])
|
|> line(end = [112.54, 127.64])
|
||||||
|> line(end = [170.36, -121.61], tag = $seg01)
|
|> line(end = [170.36, -121.61], tag = $seg01)
|
||||||
@ -1253,7 +1262,7 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
|
|||||||
await page.mouse.click(700, 200)
|
await page.mouse.click(700, 200)
|
||||||
|
|
||||||
await expect(page.locator('.cm-content')).toHaveText(
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
`sketch001 = startSketchOn(XZ)`
|
`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)`
|
||||||
)
|
)
|
||||||
|
|
||||||
await page.waitForTimeout(600)
|
await page.waitForTimeout(600)
|
||||||
|
@ -1,24 +1,29 @@
|
|||||||
import { test, expect } from './zoo-test'
|
import {
|
||||||
|
PROJECT_SETTINGS_FILE_NAME,
|
||||||
|
SETTINGS_FILE_NAME,
|
||||||
|
} from '@src/lib/constants'
|
||||||
|
import type { SettingsLevel } from '@src/lib/settings/settingsTypes'
|
||||||
|
import type { DeepPartial } from '@src/lib/types'
|
||||||
import * as fsp from 'fs/promises'
|
import * as fsp from 'fs/promises'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
|
|
||||||
|
import type { Settings } from '@rust/kcl-lib/bindings/Settings'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getUtils,
|
|
||||||
executorInputPath,
|
|
||||||
createProject,
|
|
||||||
tomlToSettings,
|
|
||||||
TEST_COLORS,
|
|
||||||
orRunWhenFullSuiteEnabled,
|
|
||||||
} from './test-utils'
|
|
||||||
import { SettingsLevel } from 'lib/settings/settingsTypes'
|
|
||||||
import { SETTINGS_FILE_NAME, PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
|
|
||||||
import {
|
|
||||||
TEST_SETTINGS_KEY,
|
|
||||||
TEST_SETTINGS_CORRUPTED,
|
|
||||||
TEST_SETTINGS,
|
TEST_SETTINGS,
|
||||||
|
TEST_SETTINGS_CORRUPTED,
|
||||||
TEST_SETTINGS_DEFAULT_THEME,
|
TEST_SETTINGS_DEFAULT_THEME,
|
||||||
} from './storageStates'
|
TEST_SETTINGS_KEY,
|
||||||
import { DeepPartial } from 'lib/types'
|
} from '@e2e/playwright/storageStates'
|
||||||
import { Settings } from '@rust/kcl-lib/bindings/Settings'
|
import {
|
||||||
|
TEST_COLORS,
|
||||||
|
createProject,
|
||||||
|
executorInputPath,
|
||||||
|
getUtils,
|
||||||
|
orRunWhenFullSuiteEnabled,
|
||||||
|
tomlToSettings,
|
||||||
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Testing settings', () => {
|
test.describe('Testing settings', () => {
|
||||||
test('Stored settings are validated and fall back to defaults', async ({
|
test('Stored settings are validated and fall back to defaults', async ({
|
||||||
@ -45,12 +50,12 @@ test.describe('Testing settings', () => {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(storedSettings.settings?.app?.theme).toBe('dark')
|
expect(storedSettings.settings?.app?.appearance?.theme).toBe('dark')
|
||||||
|
|
||||||
// Check that the invalid settings were changed to good defaults
|
// Check that the invalid settings were changed to good defaults
|
||||||
expect(storedSettings.settings?.modeling?.base_unit).toBe('in')
|
expect(storedSettings.settings?.modeling?.base_unit).toBe('in')
|
||||||
expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo')
|
expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo')
|
||||||
expect(storedSettings.settings?.app?.project_directory).toBe('')
|
expect(storedSettings.settings?.project?.directory).toBe('')
|
||||||
expect(storedSettings.settings?.project?.default_project_name).toBe(
|
expect(storedSettings.settings?.project?.default_project_name).toBe(
|
||||||
'project-$nnn'
|
'project-$nnn'
|
||||||
)
|
)
|
||||||
@ -271,7 +276,7 @@ test.describe('Testing settings', () => {
|
|||||||
const bracketDir = join(dir, projectName)
|
const bracketDir = join(dir, projectName)
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
await fsp.copyFile(
|
await fsp.copyFile(
|
||||||
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
|
executorInputPath('cylinder-inches.kcl'),
|
||||||
join(bracketDir, 'main.kcl')
|
join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -381,7 +386,9 @@ test.describe('Testing settings', () => {
|
|||||||
}
|
}
|
||||||
await tronApp.cleanProjectDir({
|
await tronApp.cleanProjectDir({
|
||||||
app: {
|
app: {
|
||||||
theme_color: '259',
|
appearance: {
|
||||||
|
color: 259,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -413,9 +420,12 @@ test.describe('Testing settings', () => {
|
|||||||
|
|
||||||
await tronApp.cleanProjectDir({
|
await tronApp.cleanProjectDir({
|
||||||
app: {
|
app: {
|
||||||
// Doesn't matter what you set it to. It will
|
appearance: {
|
||||||
// default to 264.5
|
// Doesn't matter what you set it to. It will
|
||||||
theme_color: '0',
|
// default to 264.5
|
||||||
|
|
||||||
|
color: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -699,19 +709,19 @@ test.describe('Testing settings', () => {
|
|||||||
name: 'Current units are: ',
|
name: 'Current units are: ',
|
||||||
})
|
})
|
||||||
await gizmo.click()
|
await gizmo.click()
|
||||||
const button = page.getByRole('button', {
|
const button = page.locator('ul').getByRole('button', {
|
||||||
name: copy,
|
name: copy,
|
||||||
exact: true,
|
exact: true,
|
||||||
})
|
})
|
||||||
await button.click()
|
await button.click()
|
||||||
const toastMessage = page.getByText(
|
const toastMessage = page.getByText(
|
||||||
`Set default unit to "${unitOfMeasure}" for this project`
|
`Updated per-file units to ${unitOfMeasure}`
|
||||||
)
|
)
|
||||||
await expect(toastMessage).toBeVisible()
|
await expect(toastMessage).toBeVisible()
|
||||||
}
|
}
|
||||||
|
|
||||||
await changeUnitOfMeasureInGizmo('in', 'Inches')
|
|
||||||
await changeUnitOfMeasureInGizmo('ft', 'Feet')
|
await changeUnitOfMeasureInGizmo('ft', 'Feet')
|
||||||
|
await changeUnitOfMeasureInGizmo('in', 'Inches')
|
||||||
await changeUnitOfMeasureInGizmo('yd', 'Yards')
|
await changeUnitOfMeasureInGizmo('yd', 'Yards')
|
||||||
await changeUnitOfMeasureInGizmo('mm', 'Millimeters')
|
await changeUnitOfMeasureInGizmo('mm', 'Millimeters')
|
||||||
await changeUnitOfMeasureInGizmo('cm', 'Centimeters')
|
await changeUnitOfMeasureInGizmo('cm', 'Centimeters')
|
||||||
@ -951,9 +961,9 @@ test.describe('Testing settings', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Initial units from settings`, async () => {
|
await test.step(`Initial units from settings are ignored`, async () => {
|
||||||
await homePage.openProject('project-000')
|
await homePage.openProject('project-000')
|
||||||
await expect(unitsIndicator).toHaveText('Current units are: in')
|
await expect(unitsIndicator).toHaveText('Current units are: mm')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Manually write inline settings`, async () => {
|
await test.step(`Manually write inline settings`, async () => {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { Page } from '@playwright/test'
|
import type { Page } from '@playwright/test'
|
||||||
import { test, expect } from './zoo-test'
|
|
||||||
import {
|
|
||||||
getUtils,
|
|
||||||
createProject,
|
|
||||||
orRunWhenFullSuiteEnabled,
|
|
||||||
} from './test-utils'
|
|
||||||
import { join } from 'path'
|
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
import { join } from 'path'
|
||||||
|
|
||||||
|
import {
|
||||||
|
createProject,
|
||||||
|
getUtils,
|
||||||
|
orRunWhenFullSuiteEnabled,
|
||||||
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => {
|
test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => {
|
||||||
test('basic lego happy case', async ({ page, homePage }) => {
|
test('basic lego happy case', async ({ page, homePage }) => {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { test, expect } from './zoo-test'
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
doExport,
|
doExport,
|
||||||
getUtils,
|
getUtils,
|
||||||
makeTemplate,
|
makeTemplate,
|
||||||
orRunWhenFullSuiteEnabled,
|
orRunWhenFullSuiteEnabled,
|
||||||
} from './test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
|
||||||
test('Units menu', async ({ page, homePage }) => {
|
test('Units menu', async ({ page, homePage }) => {
|
||||||
test.fixme(orRunWhenFullSuiteEnabled())
|
test.fixme(orRunWhenFullSuiteEnabled())
|
||||||
@ -67,11 +66,11 @@ part001 = startSketchOn(-XZ)
|
|||||||
|> xLine(endAbsolute = totalLen, tag = $seg03)
|
|> xLine(endAbsolute = totalLen, tag = $seg03)
|
||||||
|> yLine(length = -armThick, tag = $seg01)
|
|> yLine(length = -armThick, tag = $seg01)
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle = HALF_TURN,
|
angle = turns::HALF_TURN,
|
||||||
offset = -armThick,
|
offset = -armThick,
|
||||||
intersectTag = seg04
|
intersectTag = seg04
|
||||||
}, %)
|
}, %)
|
||||||
|> angledLineToY([segAng(seg04) + 180, ZERO], %)
|
|> angledLineToY([segAng(seg04) + 180, turns::ZERO], %)
|
||||||
|> angledLineToY({
|
|> angledLineToY({
|
||||||
angle = -bottomAng,
|
angle = -bottomAng,
|
||||||
to = -totalHeightHalf - armThick,
|
to = -totalHeightHalf - armThick,
|
||||||
@ -79,12 +78,12 @@ part001 = startSketchOn(-XZ)
|
|||||||
|> xLine(endAbsolute = segEndX(seg03) + 0)
|
|> xLine(endAbsolute = segEndX(seg03) + 0)
|
||||||
|> yLine(length = -segLen(seg01))
|
|> yLine(length = -segLen(seg01))
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle = HALF_TURN,
|
angle = turns::HALF_TURN,
|
||||||
offset = -armThick,
|
offset = -armThick,
|
||||||
intersectTag = seg02
|
intersectTag = seg02
|
||||||
}, %)
|
}, %)
|
||||||
|> angledLineToY([segAng(seg02) + 180, -baseHeight], %)
|
|> angledLineToY([segAng(seg02) + 180, -baseHeight], %)
|
||||||
|> xLine(endAbsolute = ZERO)
|
|> xLine(endAbsolute = turns::ZERO)
|
||||||
|> close()
|
|> close()
|
||||||
|> extrude(length = 4)`
|
|> extrude(length = 4)`
|
||||||
)
|
)
|
||||||
@ -483,7 +482,8 @@ test('Sketch on face', async ({ page, homePage, scene, cmdBar, toolbar }) => {
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`sketch001 = startSketchOn(XZ)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([3.29, 7.86], %)
|
|> startProfileAt([3.29, 7.86], %)
|
||||||
|> line(end = [2.48, 2.44])
|
|> line(end = [2.48, 2.44])
|
||||||
|> line(end = [2.66, 1.17])
|
|> line(end = [2.66, 1.17])
|
||||||
|