Compare commits
	
		
			145 Commits
		
	
	
		
			v0.17.3
			...
			kurt-speed
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 182865014e | |||
| 2452eede0b | |||
| 98442b9ec2 | |||
| fb1c8036f6 | |||
| 2918612d4b | |||
| abbd065c2c | |||
| 23e29b024f | |||
| 807adac371 | |||
| 03eb8dca32 | |||
| e3358f8251 | |||
| 49ea3991b2 | |||
| f32f0e2717 | |||
| 0363e4f4e0 | |||
| 5e60dbd5e8 | |||
| 379f154a5c | |||
| 60c4969322 | |||
| cc6dee8ad4 | |||
| 2fc7c0d5fd | |||
| bf2dcd808f | |||
| ee21e486d4 | |||
| b5a3eb9e9c | |||
| c85645c9f2 | |||
| cfa4dd2e33 | |||
| c620f7269c | |||
| 2d8d29b345 | |||
| 00da062586 | |||
| aafbaf6c50 | |||
| 2894c84a4e | |||
| c01084feb0 | |||
| c461db5f54 | |||
| 03fcb73aca | |||
| 8065e7e51a | |||
| 2d0ac249df | |||
| 3d73b82c23 | |||
| 0b235dc1cd | |||
| 0857415793 | |||
| 1da4fd03ef | |||
| 39d84c12ab | |||
| 537d86c8ff | |||
| f08d955d40 | |||
| 7ea6722d2d | |||
| 39bd72fc83 | |||
| 88aec7e2c5 | |||
| b936eafc26 | |||
| 6c11f0e456 | |||
| 06a7fcf6a7 | |||
| 6450622146 | |||
| 9dfe0c3d80 | |||
| ba33b0da19 | |||
| 21756fe513 | |||
| 69d34c5318 | |||
| f909ea7af5 | |||
| 38d9b5d4b4 | |||
| ac140c054f | |||
| 215db38b44 | |||
| 0880199844 | |||
| 18ce254566 | |||
| bc90840e7c | |||
| 3f8c4e7b5a | |||
| 168fed038d | |||
| 9544251b1a | |||
| a490b4db8c | |||
| 410089549d | |||
| 05e27f354a | |||
| 6793555e86 | |||
| 6823c5eedd | |||
| b13c1339aa | |||
| 624b1fc07d | |||
| ed69213680 | |||
| 593b4e6f21 | |||
| 7eeaf96d18 | |||
| 6fa7698f42 | |||
| 4abb8fc267 | |||
| ff482e5f9b | |||
| dd51eecaed | |||
| 266450afbf | |||
| e01b35d1e9 | |||
| f0b9de2c1c | |||
| 35c3103186 | |||
| 08534a024c | |||
| 25fa3b48e1 | |||
| db5abf0149 | |||
| 3634c96cf1 | |||
| e9890aa22b | |||
| 36532c521e | |||
| c75ecada03 | |||
| 21d64d7c29 | |||
| 2224c89909 | |||
| 9b0f9f321b | |||
| f29573f3dc | |||
| 9a9c2223de | |||
| 6d12aa48f8 | |||
| 3fdf7bd45e | |||
| fdadd059d6 | |||
| b646504cfb | |||
| ff8a994cb8 | |||
| 4f9a0be343 | |||
| e8240ee896 | |||
| 70bc0accad | |||
| 9dedc56b7e | |||
| 72144052c0 | |||
| 82bad2cab1 | |||
| 63be31971f | |||
| ba6b3d9a8d | |||
| 0b5802a0d2 | |||
| e2d24edfee | |||
| cc06825ec9 | |||
| 51f7addf54 | |||
| 226e4d2932 | |||
| e7397ec564 | |||
| af69856633 | |||
| bce058ab52 | |||
| 75545ddff1 | |||
| 203fa7e454 | |||
| 76de64780c | |||
| 2d804dee2b | |||
| c094d0ced1 | |||
| a90fe3c066 | |||
| f3ea7fd0e2 | |||
| 704ff0df62 | |||
| eba17e92b7 | |||
| d9d700624e | |||
| 1e547aeef0 | |||
| 22899c9e69 | |||
| 25702f454c | |||
| 11faf86983 | |||
| 67d73382b1 | |||
| 15b9f43f2c | |||
| d28555a070 | |||
| 7bf116629f | |||
| fe45b5b54d | |||
| bcbd3f5bfd | |||
| 959433e357 | |||
| d18e35b7ea | |||
| 596c9a0ee6 | |||
| 9106a81c77 | |||
| 8b5ebe67b2 | |||
| a7f539eca6 | |||
| f4c87c994c | |||
| 3d4ae05145 | |||
| f5ee346408 | |||
| 544a7565e3 | |||
| 979046f7e6 | |||
| 07ae5106b9 | |||
| e9ae484332 | 
| @ -1,3 +1,3 @@ | ||||
| [codespell] | ||||
| ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,absolutey,atleast | ||||
| skip: **/target,node_modules,build,**/Cargo.lock,./docs/kcl/*.md | ||||
| skip: **/target,node_modules,build,**/Cargo.lock,./docs/kcl/*.md,./src-tauri/gen/schemas | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| VITE_KC_API_WS_MODELING_URL=wss://api.dev.zoo.dev/ws/modeling/commands | ||||
| VITE_KC_API_BASE_URL=https://api.dev.zoo.dev | ||||
| VITE_KC_SITE_BASE_URL=https://dev.zoo.dev | ||||
| VITE_KC_WASM_OVERRIDE_URL="" | ||||
| VITE_KC_SKIP_AUTH=false | ||||
| VITE_KC_CONNECTION_TIMEOUT_MS=5000 | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| VITE_KC_API_WS_MODELING_URL=wss://api.zoo.dev/ws/modeling/commands | ||||
| VITE_KC_API_BASE_URL=https://api.zoo.dev | ||||
| VITE_KC_SITE_BASE_URL=https://zoo.dev | ||||
| VITE_KC_WASM_OVERRIDE_URL="" | ||||
| VITE_KC_SKIP_AUTH=false | ||||
| VITE_KC_CONNECTION_TIMEOUT_MS=15000 | ||||
|  | ||||
							
								
								
									
										12
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -9,15 +9,27 @@ updates: | ||||
|       directory: '/' # Location of package manifests | ||||
|       schedule: | ||||
|           interval: 'daily' | ||||
|       reviewers: | ||||
|           - franknoirot  | ||||
|           - irev-dev | ||||
|     - package-ecosystem: 'github-actions' # See documentation for possible values | ||||
|       directory: '/' # Location of package manifests | ||||
|       schedule: | ||||
|           interval: 'daily' | ||||
|       reviewers: | ||||
|           - adamchalmers | ||||
|           - jessfraz | ||||
|     - package-ecosystem: 'cargo' # See documentation for possible values | ||||
|       directory: '/src/wasm-lib/' # Location of package manifests | ||||
|       schedule: | ||||
|           interval: 'daily' | ||||
|       reviewers: | ||||
|           - adamchalmers | ||||
|           - jessfraz | ||||
|     - package-ecosystem: 'cargo' # See documentation for possible values | ||||
|       directory: '/src-tauri/' # Location of package manifests | ||||
|       schedule: | ||||
|           interval: 'daily' | ||||
|       reviewers: | ||||
|           - adamchalmers | ||||
|           - jessfraz | ||||
|  | ||||
							
								
								
									
										41
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -104,7 +104,11 @@ jobs: | ||||
|         run: | | ||||
|           VERSION=$(date +'%-y.%-m.%-d') yarn bump-jsons | ||||
|           echo "$(jq --arg url 'https://dl.zoo.dev/releases/modeling-app/nightly/last_update.json' \ | ||||
|             '.tauri.updater.endpoints[]=$url' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json | ||||
|             '.plugins.updater.endpoints[]=$url' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json | ||||
|           echo "$(jq --arg id 'dev.zoo.modeling-app-nightly' \ | ||||
|             '.identifier=$id' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json | ||||
|           echo "$(jq --arg name 'Zoo Modeling App (Nightly)' \ | ||||
|             '.productName=$name' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json | ||||
|  | ||||
|       - uses: actions/upload-artifact@v3 | ||||
|         if: github.event_name == 'schedule' | ||||
| @ -125,6 +129,9 @@ jobs: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         os: [macos-14, ubuntu-latest, windows-latest] | ||||
|     env: | ||||
|       TAURI_ARGS_MACOS: ${{ matrix.os == 'macos-14' && '--target universal-apple-darwin' || '' }} | ||||
|       TAURI_ARGS_UBUNTU: ${{ matrix.os == 'ubuntu-latest' && '--bundles' || '' }} | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
| @ -144,10 +151,12 @@ jobs: | ||||
|           sudo apt-get update && | ||||
|           sudo apt-get install -y | ||||
|           libgtk-3-dev | ||||
|           libgtksourceview-3.0-dev | ||||
|           webkit2gtk-4.0 | ||||
|           libappindicator3-dev | ||||
|           libayatana-appindicator3-dev | ||||
|           webkit2gtk-driver | ||||
|           libsoup-3.0-dev | ||||
|           libjavascriptcoregtk-4.1-dev | ||||
|           libwebkit2gtk-4.1-dev | ||||
|           at-spi2-core | ||||
|           xvfb | ||||
|  | ||||
|       - name: Sync node version and setup cache | ||||
| @ -161,7 +170,9 @@ jobs: | ||||
|       - name: Setup Rust | ||||
|         uses: dtolnay/rust-toolchain@stable | ||||
|  | ||||
|       # TODO: re-enable for Windows builds, see https://github.com/tauri-apps/tauri/issues/9045 | ||||
|       - name: Setup Rust cache | ||||
|         if: matrix.os != 'windows-latest' | ||||
|         uses: swatinem/rust-cache@v2 | ||||
|         with: | ||||
|           workspaces: './src-tauri -> target' | ||||
| @ -224,14 +235,14 @@ jobs: | ||||
|         with: | ||||
|           includeRelease: false | ||||
|           includeDebug: true | ||||
|           args: ${{ matrix.os == 'macos-14' && '--target universal-apple-darwin' || '' }} | ||||
|           args: "${{ env.TAURI_ARGS_MACOS }} ${{ env.TAURI_ARGS_UBUNTU }}" | ||||
|  | ||||
|       - name: Build the app (release) and sign | ||||
|         uses: tauri-apps/tauri-action@v0 | ||||
|         if: ${{ env.BUILD_RELEASE == 'true' }} | ||||
|         env: | ||||
|           TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} | ||||
|           TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} | ||||
|           TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | ||||
|           TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | ||||
|           APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} | ||||
|           APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | ||||
|           APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} | ||||
| @ -240,7 +251,7 @@ jobs: | ||||
|           APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | ||||
|           TAURI_CONF_ARGS: "--config ${{ matrix.os == 'windows-latest' && 'src-tauri\\tauri.release.conf.json' || 'src-tauri/tauri.release.conf.json' }}" | ||||
|         with: | ||||
|           args: "${{ matrix.os == 'macos-14' && '--target universal-apple-darwin' || '' }} ${{ env.TAURI_CONF_ARGS }}" | ||||
|           args: "${{ env.TAURI_CONF_ARGS }} ${{ env.TAURI_ARGS_MACOS }} ${{ env.TAURI_ARGS_UBUNTU }}" | ||||
|  | ||||
|       - uses: actions/upload-artifact@v3 | ||||
|         if: matrix.os != 'ubuntu-latest' | ||||
| @ -250,10 +261,11 @@ jobs: | ||||
|         with: | ||||
|           path: "${{ env.PREFIX }}/${{ env.MODE }}/bundle/*/*" | ||||
|  | ||||
|       # TODO: re-enable linux e2e tests when possible | ||||
|       - name: Run e2e tests (linux only) | ||||
|         if: matrix.os == 'ubuntu-latest' | ||||
|         if: false | ||||
|         run: | | ||||
|           cargo install tauri-driver@0.1.3 | ||||
|           cargo install tauri-driver | ||||
|           source .env.${{ env.BUILD_RELEASE == 'true' && 'production' || 'development' }} | ||||
|           export VITE_KC_API_BASE_URL | ||||
|           xvfb-run yarn test:e2e:tauri | ||||
| @ -273,6 +285,7 @@ jobs: | ||||
|       NOTES: ${{ github.event_name == 'release' && github.event.release.body || format('Nightly build, commit {0}', github.sha) }} | ||||
|       BUCKET_DIR: ${{ github.event_name == 'release' && 'dl.kittycad.io/releases/modeling-app' || 'dl.kittycad.io/releases/modeling-app/nightly' }} | ||||
|       WEBSITE_DIR: ${{ github.event_name == 'release' && 'dl.zoo.dev/releases/modeling-app' || 'dl.zoo.dev/releases/modeling-app/nightly' }} | ||||
|       URL_CODED_NAME: ${{ github.event_name == 'schedule' && 'Zoo%20Modeling%20App%20%28Nightly%29' || 'Zoo%20Modeling%20App' }} | ||||
|     steps: | ||||
|       - uses: actions/download-artifact@v3 | ||||
|  | ||||
| @ -287,9 +300,9 @@ jobs: | ||||
|             --arg pub_date "${PUB_DATE}" \ | ||||
|             --arg notes "${NOTES}" \ | ||||
|             --arg darwin_sig "$DARWIN_SIG" \ | ||||
|             --arg darwin_url "$RELEASE_DIR/macos/Zoo%20Modeling%20App.app.tar.gz" \ | ||||
|             --arg darwin_url "$RELEASE_DIR/macos/${{ env.URL_CODED_NAME }}.app.tar.gz" \ | ||||
|             --arg windows_sig "$WINDOWS_SIG" \ | ||||
|             --arg windows_url "$RELEASE_DIR/msi/Zoo%20Modeling%20App_${VERSION_NO_V}_x64_en-US.msi.zip" \ | ||||
|             --arg windows_url "$RELEASE_DIR/msi/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_x64_en-US.msi.zip" \ | ||||
|             '{ | ||||
|               "version": $version, | ||||
|               "pub_date": $pub_date, | ||||
| @ -318,8 +331,8 @@ jobs: | ||||
|             --arg version "${VERSION}" \ | ||||
|             --arg pub_date "${PUB_DATE}" \ | ||||
|             --arg notes "${NOTES}" \ | ||||
|             --arg darwin_url "$RELEASE_DIR/dmg/Zoo%20Modeling%20App_${VERSION_NO_V}_universal.dmg" \ | ||||
|             --arg windows_url "$RELEASE_DIR/msi/Zoo%20Modeling%20App_${VERSION_NO_V}_x64_en-US.msi" \ | ||||
|             --arg darwin_url "$RELEASE_DIR/dmg/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_universal.dmg" \ | ||||
|             --arg windows_url "$RELEASE_DIR/msi/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_x64_en-US.msi" \ | ||||
|             '{ | ||||
|               "version": $version, | ||||
|               "pub_date": $pub_date, | ||||
|  | ||||
							
								
								
									
										5
									
								
								.github/workflows/generate-website-docs.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -15,7 +15,7 @@ concurrency: | ||||
|   cancel-in-progress: true | ||||
| jobs: | ||||
|   generate-website-docs: | ||||
|     name: generate-website-docs  | ||||
|     name: generate-website-docs | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
| @ -56,6 +56,9 @@ jobs: | ||||
|           gh pr create --title "Update KCL docs" \ | ||||
|               --body "Updating the generated kcl docs cc @jessfraz @franknoirot merge this" \ | ||||
|               --head "$NEW_BRANCH" \ | ||||
|               --reviewer jessfraz \ | ||||
|               --reviewer irev-dev \ | ||||
|               --reviewer franknoirot \ | ||||
|               --base main || true | ||||
|         env: | ||||
|           GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} | ||||
|  | ||||
							
								
								
									
										35
									
								
								.github/workflows/playwright.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -14,9 +14,31 @@ permissions: | ||||
|   pull-requests: write | ||||
|  | ||||
| jobs: | ||||
|   check-wasm-lib-changes: | ||||
|     runs-on: ubuntu-latest | ||||
|     outputs: | ||||
|       url: ${{ steps.set-output.outputs.url }} | ||||
|     steps: | ||||
|       - uses: actions/checkout@v2 | ||||
|         with: | ||||
|           fetch-depth: 0 # Fetches all history for all branches and tags | ||||
|  | ||||
|       - name: Check for changes in src/wasm-lib | ||||
|         id: set-output | ||||
|         run: | | ||||
|           if git diff --quiet origin/main...HEAD -- src/wasm-lib; then | ||||
|             echo "url=https://app.zoo.dev" >> $GITHUB_OUTPUT | ||||
|             echo "No changes detected in src/wasm-lib" | ||||
|           else | ||||
|             echo "Changes detected in src/wasm-lib" | ||||
|             echo "url=" >> $GITHUB_OUTPUT | ||||
|           fi | ||||
|  | ||||
|  | ||||
|   playwright-ubuntu: | ||||
|     timeout-minutes: 60 | ||||
|     runs-on: ubuntu-latest-8-cores | ||||
|     needs: check-wasm-lib-changes | ||||
|     steps: | ||||
|     - uses: actions/checkout@v4 | ||||
|     - uses: actions/setup-node@v4 | ||||
| @ -28,13 +50,19 @@ jobs: | ||||
|       run: yarn | ||||
|     - name: Install Playwright Browsers | ||||
|       run: yarn playwright install --with-deps | ||||
|     - name: Print WASM Lib Changes URL | ||||
|       run: | | ||||
|         echo "WASM Lib Changes URL: ${{ needs.check-wasm-lib-changes.outputs.url }}" | ||||
|     - name: Setup Rust | ||||
|       if: ${{ needs.check-wasm-lib-changes.outputs.url }} == '' | ||||
|       uses: dtolnay/rust-toolchain@stable | ||||
|     - name: Cache wasm | ||||
|       if: ${{ needs.check-wasm-lib-changes.outputs.url }} == '' | ||||
|       uses: Swatinem/rust-cache@v2 | ||||
|       with: | ||||
|         workspaces: './src/wasm-lib' | ||||
|     - name: build wasm | ||||
|       if: ${{ needs.check-wasm-lib-changes.outputs.url }} == '' | ||||
|       run: yarn build:wasm | ||||
|     - name: build web | ||||
|       run: yarn build:local | ||||
| @ -44,6 +72,7 @@ jobs: | ||||
|         CI: true | ||||
|         token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} | ||||
|         snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }} | ||||
|         WASM_OVERRIDE: ${{ steps.check-wasm-lib-changes.outputs.url }} | ||||
|     - uses: actions/upload-artifact@v3 | ||||
|       if: always() | ||||
|       with: | ||||
| @ -79,6 +108,7 @@ jobs: | ||||
|       env: | ||||
|         CI: true | ||||
|         token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} | ||||
|         WASM_OVERRIDE: ${{ steps.check-wasm-lib-changes.outputs.url }} | ||||
|     - uses: actions/upload-artifact@v3 | ||||
|       if: always() | ||||
|       with: | ||||
| @ -89,6 +119,7 @@ jobs: | ||||
|   playwright-macos: | ||||
|     timeout-minutes: 60 | ||||
|     runs-on: macos-14 | ||||
|     needs: check-wasm-lib-changes | ||||
|     steps: | ||||
|     - uses: actions/checkout@v4 | ||||
|     - uses: actions/setup-node@v4 | ||||
| @ -100,12 +131,15 @@ jobs: | ||||
|     - name: Install Playwright Browsers | ||||
|       run: yarn playwright install --with-deps | ||||
|     - name: Setup Rust | ||||
|       if: needs.check-wasm-lib-changes.outputs.url == '' | ||||
|       uses: dtolnay/rust-toolchain@stable | ||||
|     - name: Cache wasm | ||||
|       if: needs.check-wasm-lib-changes.outputs.url == '' | ||||
|       uses: Swatinem/rust-cache@v2 | ||||
|       with: | ||||
|         workspaces: './src/wasm-lib' | ||||
|     - name: build wasm | ||||
|       if: needs.check-wasm-lib-changes.outputs.url == '' | ||||
|       run: yarn build:wasm | ||||
|     - name: build web | ||||
|       run: yarn build:local | ||||
| @ -116,6 +150,7 @@ jobs: | ||||
|       env: | ||||
|         CI: true | ||||
|         token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} | ||||
|         WASM_OVERRIDE: ${{ steps.check-wasm-lib-changes.outputs.url }} | ||||
|     - uses: actions/upload-artifact@v3 | ||||
|       if: always() | ||||
|       with: | ||||
|  | ||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -51,5 +51,6 @@ e2e/playwright/export-snapshots/* | ||||
|  | ||||
| ## generated files | ||||
| src/**/*.typegen.ts | ||||
| src-tauri/gen | ||||
|  | ||||
| src/wasm-lib/grackle/stdlib_cube_partial.json | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								app-icon.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 113 KiB | 
| @ -1,3 +1,3 @@ | ||||
| module.exports = { | ||||
|   presets: ["@babel/preset-env"], | ||||
|   presets: ['@babel/preset-env'], | ||||
| } | ||||
|  | ||||
							
								
								
									
										7404
									
								
								docs/kcl/std.json
									
									
									
									
									
								
							
							
						
						| @ -7,16 +7,36 @@ import { spawn } from 'child_process' | ||||
| import { APP_NAME } from 'lib/constants' | ||||
| import JSZip from 'jszip' | ||||
| import path from 'path' | ||||
| import { basicSettings, basicStorageState } from './storageStates' | ||||
| import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates' | ||||
| import * as TOML from '@iarna/toml' | ||||
|  | ||||
| test.beforeEach(async ({ page }) => { | ||||
|   // reducedMotion kills animations, which speeds up tests and reduces flakiness | ||||
|   await page.emulateMedia({ reducedMotion: 'reduce' }) | ||||
| }) | ||||
|  | ||||
| test.use({ | ||||
|   storageState: structuredClone(basicStorageState), | ||||
|   // set the default settings | ||||
|   await page.addInitScript( | ||||
|     async ({ token, settingsKey, settings }) => { | ||||
|       localStorage.setItem('TOKEN_PERSIST_KEY', token) | ||||
|       localStorage.setItem('persistCode', ``) | ||||
|       localStorage.setItem(settingsKey, settings) | ||||
|     }, | ||||
|     { | ||||
|       token: secrets.token, | ||||
|       settingsKey: TEST_SETTINGS_KEY, | ||||
|       settings: TOML.stringify({ settings: TEST_SETTINGS }), | ||||
|     } | ||||
|   ) | ||||
|  | ||||
|   // Make the user avatar image always 404 | ||||
|   // so we see the fallback menu icon for all snapshot tests | ||||
|   await page.route('https://lh3.googleusercontent.com/**', async (route) => { | ||||
|     await route.fulfill({ | ||||
|       status: 404, | ||||
|       contentType: 'text/plain', | ||||
|       body: 'Not Found!', | ||||
|     }) | ||||
|   }) | ||||
| }) | ||||
|  | ||||
| test.setTimeout(60_000) | ||||
| @ -316,10 +336,7 @@ const part001 = startSketchOn('-XZ') | ||||
|   } | ||||
| }) | ||||
|  | ||||
| test('extrude on each default plane should be stable', async ({ | ||||
|   page, | ||||
|   context, | ||||
| }) => { | ||||
| const extrudeDefaultPlane = async (context: any, page: any, plane: string) => { | ||||
|   await context.addInitScript(async () => { | ||||
|     localStorage.setItem( | ||||
|       'SETTINGS_PERSIST_KEY', | ||||
| @ -336,8 +353,8 @@ test('extrude on each default plane should be stable', async ({ | ||||
|       }) | ||||
|     ) | ||||
|   }) | ||||
|   const u = getUtils(page) | ||||
|   const makeCode = (plane = 'XY') => `const part001 = startSketchOn('${plane}') | ||||
|  | ||||
|   const code = `const part001 = startSketchOn('${plane}') | ||||
|   |> startProfileAt([7.00, 4.40], %) | ||||
|   |> line([6.60, -0.20], %) | ||||
|   |> line([2.80, 5.00], %) | ||||
| @ -346,9 +363,11 @@ test('extrude on each default plane should be stable', async ({ | ||||
|   |> close(%) | ||||
|   |> extrude(10.00, %) | ||||
| ` | ||||
|   await context.addInitScript(async (code) => { | ||||
|   await page.addInitScript(async (code: string) => { | ||||
|     localStorage.setItem('persistCode', code) | ||||
|   }, makeCode('XY')) | ||||
|   }) | ||||
|  | ||||
|   const u = getUtils(page) | ||||
|   await page.setViewportSize({ width: 1200, height: 500 }) | ||||
|   await page.goto('/') | ||||
|   await u.waitForAuthSkipAppStart() | ||||
| @ -358,32 +377,48 @@ test('extrude on each default plane should be stable', async ({ | ||||
|   await u.expectCmdLog('[data-message-type="execution-done"]') | ||||
|   await u.clearAndCloseDebugPanel() | ||||
|   await page.waitForTimeout(200) | ||||
|   // clear code | ||||
|   await u.removeCurrentCode() | ||||
|   await u.openAndClearDebugPanel() | ||||
|   await u.doAndWaitForImageDiff( | ||||
|     () => page.locator('.cm-content').fill(code), | ||||
|     200 | ||||
|   ) | ||||
|   // wait for execution done | ||||
|   await u.expectCmdLog('[data-message-type="execution-done"]') | ||||
|   await u.clearAndCloseDebugPanel() | ||||
|  | ||||
|   const runSnapshotsForOtherPlanes = async (plane = 'XY') => { | ||||
|     // clear code | ||||
|     await u.removeCurrentCode() | ||||
|     // add makeCode('XZ') | ||||
|     await u.openAndClearDebugPanel() | ||||
|     await page.locator('.cm-content').fill(makeCode(plane)) | ||||
|     // wait for execution done | ||||
|     await u.expectCmdLog('[data-message-type="execution-done"]') | ||||
|     await u.clearAndCloseDebugPanel() | ||||
|   await u.closeKclCodePanel() | ||||
|   await expect(page).toHaveScreenshot({ | ||||
|     maxDiffPixels: 100, | ||||
|   }) | ||||
|   await u.openKclCodePanel() | ||||
| } | ||||
|  | ||||
|     await page.getByText('Code').click() | ||||
|     await page.waitForTimeout(150) | ||||
|     await expect(page).toHaveScreenshot({ | ||||
|       maxDiffPixels: 100, | ||||
|     }) | ||||
|     await page.getByText('Code').click() | ||||
|   } | ||||
|   await runSnapshotsForOtherPlanes('XY') | ||||
|   await runSnapshotsForOtherPlanes('-XY') | ||||
| test.describe('extrude on default planes should be stable', () => { | ||||
|   test('XY', async ({ page, context }) => { | ||||
|     await extrudeDefaultPlane(context, page, 'XY') | ||||
|   }) | ||||
|  | ||||
|   await runSnapshotsForOtherPlanes('XZ') | ||||
|   await runSnapshotsForOtherPlanes('-XZ') | ||||
|   test('XZ', async ({ page, context }) => { | ||||
|     await extrudeDefaultPlane(context, page, 'XZ') | ||||
|   }) | ||||
|  | ||||
|   await runSnapshotsForOtherPlanes('YZ') | ||||
|   await runSnapshotsForOtherPlanes('-YZ') | ||||
|   test('YZ', async ({ page, context }) => { | ||||
|     await extrudeDefaultPlane(context, page, 'YZ') | ||||
|   }) | ||||
|  | ||||
|   test('-XY', async ({ page, context }) => { | ||||
|     await extrudeDefaultPlane(context, page, '-XY') | ||||
|   }) | ||||
|  | ||||
|   test('-XZ', async ({ page, context }) => { | ||||
|     await extrudeDefaultPlane(context, page, '-XZ') | ||||
|   }) | ||||
|  | ||||
|   test('-YZ', async ({ page, context }) => { | ||||
|     await extrudeDefaultPlane(context, page, '-YZ') | ||||
|   }) | ||||
| }) | ||||
|  | ||||
| test('Draft segments should look right', async ({ page, context }) => { | ||||
| @ -445,9 +480,7 @@ test('Draft segments should look right', async ({ page, context }) => { | ||||
|   }) | ||||
| }) | ||||
|  | ||||
| test('Client side scene scale should match engine scale - Inch', async ({ | ||||
|   page, | ||||
| }) => { | ||||
| test('Draft rectangles should look right', async ({ page, context }) => { | ||||
|   const u = getUtils(page) | ||||
|   await page.setViewportSize({ width: 1200, height: 500 }) | ||||
|   const PUR = 400 / 37.5 //pixeltoUnitRatio | ||||
| @ -475,75 +508,126 @@ test('Client side scene scale should match engine scale - Inch', async ({ | ||||
|   ) | ||||
|  | ||||
|   await page.waitForTimeout(300) // TODO detect animation ending, or disable animation | ||||
|  | ||||
|   const startXPx = 600 | ||||
|   await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10) | ||||
|   await expect(page.locator('.cm-content')) | ||||
|     .toHaveText(`const part001 = startSketchOn('-XZ') | ||||
|   |> startProfileAt([9.06, -12.22], %)`) | ||||
|   await page.waitForTimeout(100) | ||||
|  | ||||
|   await u.closeDebugPanel() | ||||
|  | ||||
|   await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10) | ||||
|   await page.waitForTimeout(100) | ||||
|   const startXPx = 600 | ||||
|  | ||||
|   await expect(page.locator('.cm-content')) | ||||
|     .toHaveText(`const part001 = startSketchOn('-XZ') | ||||
|   |> startProfileAt([9.06, -12.22], %) | ||||
|   |> line([9.14, 0], %)`) | ||||
|   // Equip the rectangle tool | ||||
|   await page.getByRole('button', { name: 'Line' }).click() | ||||
|   await page.getByRole('button', { name: 'Rectangle' }).click() | ||||
|  | ||||
|   await page.getByRole('button', { name: 'Tangential Arc' }).click() | ||||
|   await page.waitForTimeout(100) | ||||
|   // Draw the rectangle | ||||
|   await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 30) | ||||
|   await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 10, { steps: 5 }) | ||||
|  | ||||
|   await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20) | ||||
|  | ||||
|   await expect(page.locator('.cm-content')) | ||||
|     .toHaveText(`const part001 = startSketchOn('-XZ') | ||||
|   |> startProfileAt([9.06, -12.22], %) | ||||
|   |> line([9.14, 0], %) | ||||
|   |> tangentialArcTo([27.34, -3.08], %)`) | ||||
|  | ||||
|   // click tangential arc tool again to unequip it | ||||
|   await page.getByRole('button', { name: 'Tangential Arc' }).click() | ||||
|   await page.waitForTimeout(100) | ||||
|  | ||||
|   // screen shot should show the sketch | ||||
|   await expect(page).toHaveScreenshot({ | ||||
|     maxDiffPixels: 100, | ||||
|   }) | ||||
|  | ||||
|   // exit sketch | ||||
|   await u.openAndClearDebugPanel() | ||||
|   await page.getByRole('button', { name: 'Exit Sketch' }).click() | ||||
|  | ||||
|   // wait for execution done | ||||
|   await u.expectCmdLog('[data-message-type="execution-done"]') | ||||
|   await u.clearAndCloseDebugPanel() | ||||
|   await page.waitForTimeout(200) | ||||
|  | ||||
|   // second screen shot should look almost identical, i.e. scale should be the same. | ||||
|   // Ensure the draft rectangle looks the same as it usually does | ||||
|   await expect(page).toHaveScreenshot({ | ||||
|     maxDiffPixels: 100, | ||||
|   }) | ||||
| }) | ||||
|  | ||||
| test.describe('Client side scene scale should match engine scale - Millimeters', () => { | ||||
|   const storageState = structuredClone(basicStorageState) | ||||
|   storageState.origins[0].localStorage[2].value = TOML.stringify({ | ||||
|     settings: { | ||||
|       ...basicSettings, | ||||
|       modeling: { | ||||
|         ...basicSettings.modeling, | ||||
|         defaultUnit: 'mm', | ||||
|       }, | ||||
|     }, | ||||
|   }) | ||||
|   test.use({ | ||||
|     storageState, | ||||
| test.describe('Client side scene scale should match engine scale', () => { | ||||
|   test('Inch scale', async ({ page }) => { | ||||
|     const u = getUtils(page) | ||||
|     await page.setViewportSize({ width: 1200, height: 500 }) | ||||
|     const PUR = 400 / 37.5 //pixeltoUnitRatio | ||||
|     await page.goto('/') | ||||
|     await u.waitForAuthSkipAppStart() | ||||
|     await u.openDebugPanel() | ||||
|  | ||||
|     await expect( | ||||
|       page.getByRole('button', { name: 'Start Sketch' }) | ||||
|     ).not.toBeDisabled() | ||||
|     await expect( | ||||
|       page.getByRole('button', { name: 'Start Sketch' }) | ||||
|     ).toBeVisible() | ||||
|  | ||||
|     // click on "Start Sketch" button | ||||
|     await u.clearCommandLogs() | ||||
|     await u.doAndWaitForImageDiff( | ||||
|       () => page.getByRole('button', { name: 'Start Sketch' }).click(), | ||||
|       200 | ||||
|     ) | ||||
|  | ||||
|     // select a plane | ||||
|     await page.mouse.click(700, 200) | ||||
|  | ||||
|     await expect(page.locator('.cm-content')).toHaveText( | ||||
|       `const part001 = startSketchOn('-XZ')` | ||||
|     ) | ||||
|  | ||||
|     await page.waitForTimeout(300) // TODO detect animation ending, or disable animation | ||||
|  | ||||
|     const startXPx = 600 | ||||
|     await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10) | ||||
|     await expect(page.locator('.cm-content')) | ||||
|       .toHaveText(`const part001 = startSketchOn('-XZ') | ||||
|     |> startProfileAt([9.06, -12.22], %)`) | ||||
|     await page.waitForTimeout(100) | ||||
|  | ||||
|     await u.closeDebugPanel() | ||||
|  | ||||
|     await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10) | ||||
|     await page.waitForTimeout(100) | ||||
|  | ||||
|     await expect(page.locator('.cm-content')) | ||||
|       .toHaveText(`const part001 = startSketchOn('-XZ') | ||||
|     |> startProfileAt([9.06, -12.22], %) | ||||
|     |> line([9.14, 0], %)`) | ||||
|  | ||||
|     await page.getByRole('button', { name: 'Tangential Arc' }).click() | ||||
|     await page.waitForTimeout(100) | ||||
|  | ||||
|     await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20) | ||||
|  | ||||
|     await expect(page.locator('.cm-content')) | ||||
|       .toHaveText(`const part001 = startSketchOn('-XZ') | ||||
|     |> startProfileAt([9.06, -12.22], %) | ||||
|     |> line([9.14, 0], %) | ||||
|     |> tangentialArcTo([27.34, -3.08], %)`) | ||||
|  | ||||
|     // click tangential arc tool again to unequip it | ||||
|     await page.getByRole('button', { name: 'Tangential Arc' }).click() | ||||
|     await page.waitForTimeout(100) | ||||
|  | ||||
|     // screen shot should show the sketch | ||||
|     await expect(page).toHaveScreenshot({ | ||||
|       maxDiffPixels: 100, | ||||
|     }) | ||||
|  | ||||
|     // exit sketch | ||||
|     await u.openAndClearDebugPanel() | ||||
|     await page.getByRole('button', { name: 'Exit Sketch' }).click() | ||||
|  | ||||
|     // wait for execution done | ||||
|     await u.expectCmdLog('[data-message-type="execution-done"]') | ||||
|     await u.clearAndCloseDebugPanel() | ||||
|     await page.waitForTimeout(200) | ||||
|  | ||||
|     // second screen shot should look almost identical, i.e. scale should be the same. | ||||
|     await expect(page).toHaveScreenshot({ | ||||
|       maxDiffPixels: 100, | ||||
|     }) | ||||
|   }) | ||||
|  | ||||
|   test('Millimeters', async ({ page }) => { | ||||
|   test('Millimeter scale', async ({ page }) => { | ||||
|     await page.addInitScript( | ||||
|       async ({ settingsKey, settings }) => { | ||||
|         localStorage.setItem(settingsKey, settings) | ||||
|       }, | ||||
|       { | ||||
|         settingsKey: TEST_SETTINGS_KEY, | ||||
|         settings: TOML.stringify({ | ||||
|           settings: { | ||||
|             ...TEST_SETTINGS, | ||||
|             modeling: { | ||||
|               ...TEST_SETTINGS.modeling, | ||||
|               defaultUnit: 'mm', | ||||
|             }, | ||||
|           }, | ||||
|         }), | ||||
|       } | ||||
|     ) | ||||
|     const u = getUtils(page) | ||||
|     await page.setViewportSize({ width: 1200, height: 500 }) | ||||
|     const PUR = 400 / 37.5 //pixeltoUnitRatio | ||||
| @ -638,7 +722,7 @@ test('Sketch on face with none z-up', async ({ page, context }) => { | ||||
|   |> close(%) | ||||
|   |> extrude(5 + 7, %) | ||||
| const part002 = startSketchOn(part001, 'seg01') | ||||
|   |> startProfileAt([-2.89, 1.82], %) | ||||
|   |> startProfileAt([8, 8], %) | ||||
|   |> line([4.68, 3.05], %) | ||||
|   |> line([0, -7.79], %, 'seg02') | ||||
|   |> close(%) | ||||
| @ -650,6 +734,19 @@ const part002 = startSketchOn(part001, 'seg01') | ||||
|   await page.setViewportSize({ width: 1200, height: 500 }) | ||||
|   await page.goto('/') | ||||
|   await u.waitForAuthSkipAppStart() | ||||
|  | ||||
|   await u.openDebugPanel() | ||||
|   // wait for execution done | ||||
|   await expect( | ||||
|     page.locator('[data-message-type="execution-done"]') | ||||
|   ).toHaveCount(2) | ||||
|   await u.closeDebugPanel() | ||||
|  | ||||
|   // Wait for the second extrusion to appear | ||||
|   // TODO: Find a way to truly know that the objects have finished | ||||
|   // rendering, because an execution-done message is not sufficient. | ||||
|   await page.waitForTimeout(1000) | ||||
|  | ||||
|   await expect( | ||||
|     page.getByRole('button', { name: 'Start Sketch' }) | ||||
|   ).not.toBeDisabled() | ||||
|  | ||||
| Before Width: | Height: | Size: 43 KiB | 
| Before Width: | Height: | Size: 47 KiB | 
| Before Width: | Height: | Size: 47 KiB | 
| Before Width: | Height: | Size: 48 KiB | 
| After Width: | Height: | Size: 39 KiB | 
| After Width: | Height: | Size: 51 KiB | 
| After Width: | Height: | Size: 45 KiB | 
| After Width: | Height: | Size: 52 KiB | 
| Before Width: | Height: | Size: 44 KiB | 
| Before Width: | Height: | Size: 48 KiB | 
| Before Width: | Height: | Size: 48 KiB | 
| Before Width: | Height: | Size: 49 KiB | 
| After Width: | Height: | Size: 27 KiB | 
| Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 30 KiB | 
| Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 33 KiB | 
| After Width: | Height: | Size: 66 KiB | 
| Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 71 KiB | 
| After Width: | Height: | Size: 47 KiB | 
| After Width: | Height: | Size: 51 KiB | 
| After Width: | Height: | Size: 46 KiB | 
| After Width: | Height: | Size: 48 KiB | 
| After Width: | Height: | Size: 50 KiB | 
| After Width: | Height: | Size: 46 KiB | 
| Before Width: | Height: | Size: 48 KiB | 
| Before Width: | Height: | Size: 47 KiB | 
| Before Width: | Height: | Size: 48 KiB | 
| Before Width: | Height: | Size: 50 KiB | 
| Before Width: | Height: | Size: 48 KiB | 
| Before Width: | Height: | Size: 48 KiB | 
| @ -1,13 +1,13 @@ | ||||
| import { SaveSettingsPayload } from 'lib/settings/settingsTypes' | ||||
| import { secrets } from './secrets' | ||||
| import * as TOML from '@iarna/toml' | ||||
| import { Themes } from 'lib/theme' | ||||
|  | ||||
| export const basicSettings = { | ||||
| export const TEST_SETTINGS_KEY = '/user.toml' | ||||
| export const TEST_SETTINGS = { | ||||
|   app: { | ||||
|     theme: Themes.Dark, | ||||
|     onboardingStatus: 'dismissed', | ||||
|     projectDirectory: '', | ||||
|     enableSSAO: false, | ||||
|   }, | ||||
|   modeling: { | ||||
|     defaultUnit: 'in', | ||||
| @ -22,19 +22,26 @@ export const basicSettings = { | ||||
|   }, | ||||
| } satisfies Partial<SaveSettingsPayload> | ||||
|  | ||||
| export const basicStorageState = { | ||||
|   cookies: [], | ||||
|   origins: [ | ||||
|     { | ||||
|       origin: 'http://localhost:3000', | ||||
|       localStorage: [ | ||||
|         { name: 'TOKEN_PERSIST_KEY', value: secrets.token }, | ||||
|         { name: 'persistCode', value: '' }, | ||||
|         { | ||||
|           name: '/user.toml', | ||||
|           value: TOML.stringify({ settings: basicSettings }), | ||||
|         }, | ||||
|       ], | ||||
|     }, | ||||
|   ], | ||||
| } | ||||
| export const TEST_SETTINGS_ONBOARDING = { | ||||
|   ...TEST_SETTINGS, | ||||
|   app: { ...TEST_SETTINGS.app, onboardingStatus: '/export ' }, | ||||
| } satisfies Partial<SaveSettingsPayload> | ||||
|  | ||||
| export const TEST_SETTINGS_CORRUPTED = { | ||||
|   app: { | ||||
|     theme: Themes.Dark, | ||||
|     onboardingStatus: 'dismissed', | ||||
|     projectDirectory: 123 as any, | ||||
|   }, | ||||
|   modeling: { | ||||
|     defaultUnit: 'invalid' as any, | ||||
|     mouseControls: `() => alert('hack the planet')` as any, | ||||
|     showDebugPanel: true, | ||||
|   }, | ||||
|   projects: { | ||||
|     defaultProjectName: false as any, | ||||
|   }, | ||||
|   textEditor: { | ||||
|     textWrapping: true, | ||||
|   }, | ||||
| } satisfies Partial<SaveSettingsPayload> | ||||
|  | ||||
| @ -44,26 +44,44 @@ async function waitForDefaultPlanesToBeVisible(page: Page) { | ||||
|   ) | ||||
| } | ||||
|  | ||||
| async function openDebugPanel(page: Page) { | ||||
|   const isOpen = | ||||
|     (await page | ||||
|       .locator('[data-testid="debug-panel"]') | ||||
|       ?.getAttribute('open')) === '' | ||||
| async function openKclCodePanel(page: Page) { | ||||
|   const paneLocator = page.getByRole('tab', { name: 'KCL Code', exact: false }) | ||||
|   const isOpen = (await paneLocator?.getAttribute('aria-selected')) === 'true' | ||||
|  | ||||
|   if (!isOpen) { | ||||
|     await page.getByText('Debug').click() | ||||
|     await page.getByTestId('debug-panel').and(page.locator('[open]')).waitFor() | ||||
|     await paneLocator.click() | ||||
|     await paneLocator.and(page.locator('[aria-selected="true"]')).waitFor() | ||||
|   } | ||||
| } | ||||
|  | ||||
| async function closeKclCodePanel(page: Page) { | ||||
|   const paneLocator = page.getByRole('tab', { name: 'KCL Code', exact: false }) | ||||
|   const isOpen = (await paneLocator?.getAttribute('aria-selected')) === 'true' | ||||
|   if (isOpen) { | ||||
|     await paneLocator.click() | ||||
|     await paneLocator | ||||
|       .and(page.locator(':not([aria-selected="true"])')) | ||||
|       .waitFor() | ||||
|   } | ||||
| } | ||||
|  | ||||
| async function openDebugPanel(page: Page) { | ||||
|   const debugLocator = page.getByRole('tab', { name: 'Debug', exact: false }) | ||||
|   const isOpen = (await debugLocator?.getAttribute('aria-selected')) === 'true' | ||||
|  | ||||
|   if (!isOpen) { | ||||
|     await debugLocator.click() | ||||
|     await debugLocator.and(page.locator('[aria-selected="true"]')).waitFor() | ||||
|   } | ||||
| } | ||||
|  | ||||
| async function closeDebugPanel(page: Page) { | ||||
|   const isOpen = | ||||
|     (await page.getByTestId('debug-panel')?.getAttribute('open')) === '' | ||||
|   const debugLocator = page.getByRole('tab', { name: 'Debug', exact: false }) | ||||
|   const isOpen = (await debugLocator?.getAttribute('aria-selected')) === 'true' | ||||
|   if (isOpen) { | ||||
|     await page.getByText('Debug').click() | ||||
|     await page | ||||
|       .getByTestId('debug-panel') | ||||
|       .and(page.locator(':not([open])')) | ||||
|     await debugLocator.click() | ||||
|     await debugLocator | ||||
|       .and(page.locator(':not([aria-selected="true"])')) | ||||
|       .waitFor() | ||||
|   } | ||||
| } | ||||
| @ -81,20 +99,19 @@ export function getUtils(page: Page) { | ||||
|     removeCurrentCode: () => removeCurrentCode(page), | ||||
|     sendCustomCmd: (cmd: EngineCommand) => sendCustomCmd(page, cmd), | ||||
|     updateCamPosition: async (xyz: [number, number, number]) => { | ||||
|       const fillInput = async () => { | ||||
|         await page.fill('[data-testid="cam-x-position"]', String(xyz[0])) | ||||
|         await page.fill('[data-testid="cam-y-position"]', String(xyz[1])) | ||||
|         await page.fill('[data-testid="cam-z-position"]', String(xyz[2])) | ||||
|       const fillInput = async (axis: 'x' | 'y' | 'z', value: number) => { | ||||
|         await page.fill(`[data-testid="cam-${axis}-position"]`, String(value)) | ||||
|         await page.waitForTimeout(100) | ||||
|       } | ||||
|       await fillInput() | ||||
|       await page.waitForTimeout(100) | ||||
|       await fillInput() | ||||
|       await page.waitForTimeout(100) | ||||
|       await fillInput() | ||||
|       await page.waitForTimeout(100) | ||||
|  | ||||
|       await fillInput('x', xyz[0]) | ||||
|       await fillInput('y', xyz[1]) | ||||
|       await fillInput('z', xyz[2]) | ||||
|     }, | ||||
|     clearCommandLogs: () => clearCommandLogs(page), | ||||
|     expectCmdLog: (locatorStr: string) => expectCmdLog(page, locatorStr), | ||||
|     openKclCodePanel: () => openKclCodePanel(page), | ||||
|     closeKclCodePanel: () => closeKclCodePanel(page), | ||||
|     openDebugPanel: () => openDebugPanel(page), | ||||
|     closeDebugPanel: () => closeDebugPanel(page), | ||||
|     openAndClearDebugPanel: async () => { | ||||
|  | ||||
| @ -57,7 +57,7 @@ echo "New version number without 'v': $new_version_number" | ||||
| git checkout -b "cut-release-$new_version" | ||||
|  | ||||
| echo "$(jq --arg v "$new_version_number" '.version=$v' package.json --indent 2)" > package.json | ||||
| echo "$(jq --arg v "$new_version_number" '.package.version=$v' src-tauri/tauri.conf.json --indent 2)" > src-tauri/tauri.conf.json | ||||
| echo "$(jq --arg v "$new_version_number" '.version=$v' src-tauri/tauri.conf.json --indent 2)" > src-tauri/tauri.conf.json | ||||
|  | ||||
| git add package.json src-tauri/tauri.conf.json | ||||
| git commit -m "Cut release $new_version" | ||||
|  | ||||
							
								
								
									
										77
									
								
								package.json
									
									
									
									
									
								
							
							
						
						| @ -1,38 +1,45 @@ | ||||
| { | ||||
|   "name": "untitled-app", | ||||
|   "version": "0.17.3", | ||||
|   "version": "0.18.1", | ||||
|   "private": true, | ||||
|   "dependencies": { | ||||
|     "@codemirror/autocomplete": "^6.15.0", | ||||
|     "@fortawesome/fontawesome-svg-core": "^6.4.2", | ||||
|     "@fortawesome/free-brands-svg-icons": "^6.4.2", | ||||
|     "@codemirror/autocomplete": "^6.16.0", | ||||
|     "@fortawesome/fontawesome-svg-core": "^6.5.2", | ||||
|     "@fortawesome/free-brands-svg-icons": "^6.5.2", | ||||
|     "@fortawesome/free-solid-svg-icons": "^6.4.2", | ||||
|     "@fortawesome/react-fontawesome": "^0.2.0", | ||||
|     "@headlessui/react": "^1.7.18", | ||||
|     "@headlessui/react": "^1.7.19", | ||||
|     "@headlessui/tailwindcss": "^0.2.0", | ||||
|     "@iarna/toml": "^2.2.5", | ||||
|     "@kittycad/lib": "^0.0.56", | ||||
|     "@kittycad/lib": "^0.0.58", | ||||
|     "@lezer/javascript": "^1.4.9", | ||||
|     "@open-rpc/client-js": "^1.8.1", | ||||
|     "@react-hook/resize-observer": "^1.2.6", | ||||
|     "@replit/codemirror-interact": "^6.3.0", | ||||
|     "@tauri-apps/api": "^1.5.3", | ||||
|     "@replit/codemirror-interact": "^6.3.1", | ||||
|     "@tauri-apps/api": "2.0.0-beta.8", | ||||
|     "@tauri-apps/plugin-dialog": "^2.0.0-beta.2", | ||||
|     "@tauri-apps/plugin-fs": "^2.0.0-beta.2", | ||||
|     "@tauri-apps/plugin-http": "^2.0.0-beta.2", | ||||
|     "@tauri-apps/plugin-os": "^2.0.0-beta.2", | ||||
|     "@tauri-apps/plugin-process": "^2.0.0-beta.2", | ||||
|     "@tauri-apps/plugin-shell": "^2.0.0-beta.2", | ||||
|     "@tauri-apps/plugin-updater": "^2.0.0-beta.2", | ||||
|     "@testing-library/jest-dom": "^5.14.1", | ||||
|     "@testing-library/react": "^14.0.0", | ||||
|     "@testing-library/react": "^15.0.2", | ||||
|     "@testing-library/user-event": "^14.5.2", | ||||
|     "@ts-stack/markdown": "^1.5.0", | ||||
|     "@tweenjs/tween.js": "^23.1.1", | ||||
|     "@types/node": "^18.19.26", | ||||
|     "@types/react": "^18.2.73", | ||||
|     "@types/react-dom": "^18.2.22", | ||||
|     "@types/node": "^18.19.31", | ||||
|     "@types/react": "^18.2.77", | ||||
|     "@types/react-dom": "^18.2.25", | ||||
|     "@uiw/react-codemirror": "^4.21.25", | ||||
|     "@xstate/inspect": "^0.8.0", | ||||
|     "@xstate/react": "^3.2.2", | ||||
|     "crypto-js": "^4.2.0", | ||||
|     "debounce-promise": "^3.1.2", | ||||
|     "decamelize": "^6.0.0", | ||||
|     "formik": "^2.4.3", | ||||
|     "formik": "^2.4.5", | ||||
|     "fuse.js": "^7.0.0", | ||||
|     "html2canvas-pro": "^1.4.3", | ||||
|     "http-server": "^14.1.1", | ||||
|     "json-rpc-2.0": "^1.6.0", | ||||
|     "jszip": "^3.10.1", | ||||
| @ -47,19 +54,18 @@ | ||||
|     "react-modal-promise": "^1.0.2", | ||||
|     "react-router-dom": "^6.22.3", | ||||
|     "sketch-helpers": "^0.0.4", | ||||
|     "swr": "^2.2.2", | ||||
|     "tauri-plugin-fs-extra-api": "https://github.com/tauri-apps/tauri-plugin-fs-extra#v1", | ||||
|     "three": "^0.160.0", | ||||
|     "toml": "^3.0.0", | ||||
|     "swr": "^2.2.5", | ||||
|     "three": "^0.163.0", | ||||
|     "ts-node": "^10.9.2", | ||||
|     "typescript": "^5.4.3", | ||||
|     "typescript": "^5.4.5", | ||||
|     "ua-parser-js": "^1.0.37", | ||||
|     "uuid": "^9.0.1", | ||||
|     "vitest": "^1.4.0", | ||||
|     "vitest": "^1.5.0", | ||||
|     "vscode-jsonrpc": "^8.1.0", | ||||
|     "vscode-languageserver-protocol": "^3.17.5", | ||||
|     "wasm-pack": "^0.12.1", | ||||
|     "web-vitals": "^3.5.2", | ||||
|     "ws": "^8.13.0", | ||||
|     "ws": "^8.16.0", | ||||
|     "xstate": "^4.38.2", | ||||
|     "zustand": "^4.5.2" | ||||
|   }, | ||||
| @ -78,15 +84,15 @@ | ||||
|     "test:e2e:tauri": "E2E_TAURI_ENABLED=true TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\"}' wdio run wdio.conf.ts", | ||||
|     "simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &", | ||||
|     "simpleserver": "yarn pretest && http-server ./public --cors -p 3000", | ||||
|     "fmt": "prettier --write ./src && prettier --write ./e2e", | ||||
|     "fmt-check": "prettier --check ./src && prettier --check ./e2e", | ||||
|     "fmt": "prettier --write ./src *.ts *.json *.js ./e2e", | ||||
|     "fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e", | ||||
|     "build:wasm-dev": "(cd src/wasm-lib && wasm-pack build --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt", | ||||
|     "build:wasm": "(cd src/wasm-lib && wasm-pack build --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && cp src/wasm-lib/pkg/wasm_lib_bg.wasm public && yarn fmt", | ||||
|     "build:wasm-clean": "yarn wasm-prep && yarn build:wasm", | ||||
|     "remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\" || echo \"sed for both mac and linux\"", | ||||
|     "wasm-prep": "rm -rf src/wasm-lib/pkg && mkdir src/wasm-lib/pkg && rm -rf src/wasm-lib/kcl/bindings", | ||||
|     "lint": "eslint --fix src", | ||||
|     "bump-jsons": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json && echo \"$(jq --arg v \"$VERSION\" '.package.version=$v' src-tauri/tauri.conf.json --indent 2)\" > src-tauri/tauri.conf.json", | ||||
|     "bump-jsons": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json && echo \"$(jq --arg v \"$VERSION\" '.version=$v' src-tauri/tauri.conf.json --indent 2)\" > src-tauri/tauri.conf.json", | ||||
|     "postinstall": "yarn xstate:typegen", | ||||
|     "xstate:typegen": "yarn xstate typegen \"src/**/*.ts?(x)\"" | ||||
|   }, | ||||
| @ -111,24 +117,27 @@ | ||||
|   "devDependencies": { | ||||
|     "@babel/plugin-proposal-private-property-in-object": "^7.21.11", | ||||
|     "@babel/preset-env": "^7.24.3", | ||||
|     "@playwright/test": "^1.39.0", | ||||
|     "@tauri-apps/cli": "^1.5.11", | ||||
|     "@iarna/toml": "^2.2.5", | ||||
|     "@playwright/test": "^1.43.1", | ||||
|     "@tauri-apps/cli": "^2.0.0-beta.13", | ||||
|     "@types/crypto-js": "^4.2.2", | ||||
|     "@types/debounce-promise": "^3.1.9", | ||||
|     "@types/pixelmatch": "^5.2.6", | ||||
|     "@types/pngjs": "^6.0.4", | ||||
|     "@types/react-modal": "^3.16.3", | ||||
|     "@types/three": "^0.160.0", | ||||
|     "@types/three": "^0.163.0", | ||||
|     "@types/ua-parser-js": "^0.7.39", | ||||
|     "@types/uuid": "^9.0.8", | ||||
|     "@types/wait-on": "^5.3.4", | ||||
|     "@types/wicg-file-system-access": "^2023.10.5", | ||||
|     "@types/ws": "^8.5.5", | ||||
|     "@types/ws": "^8.5.10", | ||||
|     "@vitejs/plugin-react": "^4.2.1", | ||||
|     "@vitest/web-worker": "^1.5.0", | ||||
|     "@wdio/cli": "^8.24.3", | ||||
|     "@wdio/globals": "^8.24.3", | ||||
|     "@wdio/local-runner": "^8.35.1", | ||||
|     "@wdio/mocha-framework": "^8.35.0", | ||||
|     "@wdio/spec-reporter": "^8.32.4", | ||||
|     "@wdio/globals": "^8.36.0", | ||||
|     "@wdio/local-runner": "^8.36.0", | ||||
|     "@wdio/mocha-framework": "^8.36.0", | ||||
|     "@wdio/spec-reporter": "^8.36.0", | ||||
|     "@xstate/cli": "^0.5.17", | ||||
|     "autoprefixer": "^10.4.19", | ||||
|     "eslint": "^8.57.0", | ||||
| @ -143,12 +152,12 @@ | ||||
|     "prettier": "^2.8.0", | ||||
|     "setimmediate": "^1.0.5", | ||||
|     "tailwindcss": "^3.4.1", | ||||
|     "vite": "^5.2.6", | ||||
|     "vite": "^5.2.9", | ||||
|     "vite-plugin-eslint": "^1.8.1", | ||||
|     "vite-plugin-package-version": "^1.1.0", | ||||
|     "vite-tsconfig-paths": "^4.3.2", | ||||
|     "vitest-webgl-canvas-mock": "^1.1.0", | ||||
|     "wait-on": "^7.2.0", | ||||
|     "yarn": "^1.22.19" | ||||
|     "yarn": "^1.22.22" | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| import { defineConfig, devices } from '@playwright/test' | ||||
| import { basicStorageState } from './e2e/playwright/storageStates' | ||||
|  | ||||
| /** | ||||
|  * Read environment variables from file. | ||||
| @ -19,7 +18,7 @@ export default defineConfig({ | ||||
|   /* Retry on CI only */ | ||||
|   retries: process.env.CI ? 3 : 0, | ||||
|   /* Opt out of parallel tests on CI. */ | ||||
|   workers: process.env.CI ? 1 : 1, | ||||
|   workers: process.env.CI ? 2 : 1, | ||||
|   /* Reporter to use. See https://playwright.dev/docs/test-reporters */ | ||||
|   reporter: 'html', | ||||
|   /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ | ||||
| @ -29,9 +28,6 @@ export default defineConfig({ | ||||
|  | ||||
|     /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ | ||||
|     trace: 'on-first-retry', | ||||
|  | ||||
|     /* Use a common shared localStorage */ | ||||
|     storageState: basicStorageState, | ||||
|   }, | ||||
|  | ||||
|   /* Configure projects for major browsers */ | ||||
| @ -53,8 +49,6 @@ export default defineConfig({ | ||||
|     //   use: { ...devices['Desktop Chrome'] }, | ||||
|     // }, | ||||
|  | ||||
|  | ||||
|  | ||||
|     /* Test against mobile viewports. */ | ||||
|     // { | ||||
|     //   name: 'Mobile Chrome', | ||||
| @ -78,8 +72,8 @@ export default defineConfig({ | ||||
|  | ||||
|   /* Run your local dev server before starting the tests */ | ||||
|   webServer: { | ||||
|     command: 'yarn serve', | ||||
|     command: 'VITE_KC_WASM_OVERRIDE_URL=$WASM_OVERRIDE yarn serve', | ||||
|     // url: 'http://127.0.0.1:3000', | ||||
|     reuseExistingServer: !process.env.CI, | ||||
|   }, | ||||
| }) | ||||
| }) | ||||
|  | ||||
| Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB | 
| Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 6.8 KiB | 
| Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 12 KiB | 
							
								
								
									
										2603
									
								
								src-tauri/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						| @ -7,21 +7,27 @@ license = "" | ||||
| repository = "https://github.com/KittyCAD/modeling-app" | ||||
| default-run = "app" | ||||
| edition = "2021" | ||||
| rust-version = "1.60" | ||||
| rust-version = "1.70" | ||||
|  | ||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||
|  | ||||
| [build-dependencies] | ||||
| tauri-build = { version = "1.5.1", features = [] } | ||||
| tauri-build = { version = "2.0.0-beta.13", features = [] } | ||||
|  | ||||
| [dependencies] | ||||
| anyhow = "1" | ||||
| kittycad = "0.2.63" | ||||
| kittycad = "0.3.0" | ||||
| oauth2 = "4.4.2" | ||||
| serde = { version = "1.0", features = ["derive"] } | ||||
| serde_json = "1.0" | ||||
| tauri = { version = "1.6.1", features = [ "os-all", "dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "devtools"] } | ||||
| tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } | ||||
| tauri = { version = "2.0.0-beta.15", features = [ "devtools", "unstable"] } | ||||
| tauri-plugin-dialog = { version = "2.0.0-beta.6" } | ||||
| tauri-plugin-fs = { version = "2.0.0-beta.6" } | ||||
| tauri-plugin-http = { version = "2.0.0-beta.6" } | ||||
| tauri-plugin-os = { version = "2.0.0-beta.2" } | ||||
| tauri-plugin-process = { version = "2.0.0-beta.2" } | ||||
| tauri-plugin-shell = { version = "2.0.0-beta.2" } | ||||
| tauri-plugin-updater = { version = "2.0.0-beta.4" } | ||||
| tokio = { version = "1.37.0", features = ["time"] } | ||||
| toml = "0.8.2" | ||||
|  | ||||
|  | ||||
							
								
								
									
										89
									
								
								src-tauri/capabilities/desktop.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,89 @@ | ||||
| { | ||||
|   "$schema": "../gen/schemas/desktop-schema.json", | ||||
|   "identifier": "main-capability", | ||||
|   "description": "Capability for the main window", | ||||
|   "context": "local", | ||||
|   "windows": [ | ||||
|     "main" | ||||
|   ], | ||||
|   "permissions": [ | ||||
|     "path:default", | ||||
|     "event:default", | ||||
|     "window:default", | ||||
|     "app:default", | ||||
|     "resources:default", | ||||
|     "menu:default", | ||||
|     "tray:default", | ||||
|     "fs:allow-create", | ||||
|     "fs:allow-read-file", | ||||
|     "fs:allow-read-text-file", | ||||
|     "fs:allow-write-file", | ||||
|     "fs:allow-write-text-file", | ||||
|     "fs:allow-read-dir", | ||||
|     "fs:allow-copy-file", | ||||
|     "fs:allow-mkdir", | ||||
|     "fs:allow-remove", | ||||
|     "fs:allow-remove", | ||||
|     "fs:allow-rename", | ||||
|     "fs:allow-exists", | ||||
|     "fs:allow-stat", | ||||
|     { | ||||
|       "identifier": "fs:scope", | ||||
|       "allow": [ | ||||
|         { | ||||
|           "path": "$HOME/**/*" | ||||
|         }, | ||||
|         { | ||||
|           "path": "$HOME/.config" | ||||
|         }, | ||||
|         { | ||||
|           "path": "$HOME/.config/**/*" | ||||
|         }, | ||||
|         { | ||||
|           "path": "$APPCONFIG" | ||||
|         }, | ||||
|         { | ||||
|           "path": "$APPCONFIG/**/*" | ||||
|         }, | ||||
|         { | ||||
|           "path": "$DOCUMENT" | ||||
|         }, | ||||
|         { | ||||
|           "path": "$DOCUMENT/**/*" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     "shell:allow-open", | ||||
|     "dialog:allow-open", | ||||
|     "dialog:allow-save", | ||||
|     "dialog:allow-message", | ||||
|     "dialog:allow-ask", | ||||
|     "dialog:allow-confirm", | ||||
|     { | ||||
|       "identifier": "http:default", | ||||
|       "allow": [ | ||||
|         "https://dev.kittycad.io/*", | ||||
|         "https://dev.zoo.dev/*", | ||||
|         "https://kittycad.io/*", | ||||
|         "https://zoo.dev/*", | ||||
|         "https://api.dev.kittycad.io/*", | ||||
|         "https://api.dev.zoo.dev/*" | ||||
|       ] | ||||
|     }, | ||||
|     "os:allow-platform", | ||||
|     "os:allow-version", | ||||
|     "os:allow-os-type", | ||||
|     "os:allow-family", | ||||
|     "os:allow-arch", | ||||
|     "os:allow-exe-extension", | ||||
|     "os:allow-locale", | ||||
|     "os:allow-hostname", | ||||
|     "process:allow-restart", | ||||
|     "updater:default" | ||||
|   ], | ||||
|   "platforms": [ | ||||
|     "linux", | ||||
|     "macOS", | ||||
|     "windows" | ||||
|   ] | ||||
| } | ||||
| Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 8.1 KiB | 
| Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 21 KiB | 
| Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.5 KiB | 
