diff --git a/.github/workflows/build-apps.yml b/.github/workflows/build-apps.yml index b17b27d88..218108716 100644 --- a/.github/workflows/build-apps.yml +++ b/.github/workflows/build-apps.yml @@ -33,26 +33,63 @@ jobs: - run: yarn install + - id: filter + name: Check for Rust changes + uses: dorny/paths-filter@v3 + with: + filters: | + rust: + - 'rust/**' + + - name: Download Wasm Cache + id: download-wasm + if: ${{ github.event_name == 'pull_request' && steps.filter.outputs.rust == 'false' }} + uses: dawidd6/action-download-artifact@v7 + continue-on-error: true + with: + github_token: ${{secrets.GITHUB_TOKEN}} + name: wasm-bundle + workflow: build-and-store-wasm.yml + branch: main + path: rust/kcl-wasm-lib/pkg + + - name: Build WASM condition + id: wasm + run: | + set -euox pipefail + # Build wasm if this is a push to main or tag, there are Rust changes, or + # downloading from the wasm cache failed. + if [[ ${{github.event_name}} == 'push' || ${{steps.filter.outputs.rust}} == 'true' || ${{steps.download-wasm.outcome}} == 'failure' ]]; then + echo "should-build-wasm=true" >> $GITHUB_OUTPUT + else + echo "should-build-wasm=false" >> $GITHUB_OUTPUT + fi + - name: Use correct Rust toolchain + if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }} shell: bash run: | [ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./ + - name: Install rust + if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }} uses: actions-rust-lang/setup-rust-toolchain@v1 with: cache: false # Configured below. - # TODO: see if we can fetch from main instead if no diff at rust - uses: taiki-e/install-action@955a6ff1416eae278c9f833008a9beb4b7f9afe3 + if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }} with: tool: wasm-pack - name: Rust Cache + if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }} uses: Swatinem/rust-cache@v2 with: workspaces: rust - name: Run build:wasm + if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }} run: "yarn build:wasm" - name: Set nightly version, product name, release notes, and icons diff --git a/e2e/playwright/basic-sketch.spec.ts b/e2e/playwright/basic-sketch.spec.ts index 0ff50e1f0..578e7e7ef 100644 --- a/e2e/playwright/basic-sketch.spec.ts +++ b/e2e/playwright/basic-sketch.spec.ts @@ -1,4 +1,5 @@ -import { test, expect, Page } from './zoo-test' +import { Page } from '@playwright/test' +import { test, expect } from './zoo-test' import { getUtils, TEST_COLORS, diff --git a/e2e/playwright/can-create-sketches-on-all-planes-and-their-back-sides.spec.ts b/e2e/playwright/can-create-sketches-on-all-planes-and-their-back-sides.spec.ts index 3a3aaedb8..218cd0e59 100644 --- a/e2e/playwright/can-create-sketches-on-all-planes-and-their-back-sides.spec.ts +++ b/e2e/playwright/can-create-sketches-on-all-planes-and-their-back-sides.spec.ts @@ -1,4 +1,5 @@ -import { test, expect, Page } from './zoo-test' +import { Page } from '@playwright/test' +import { test, expect } from './zoo-test' import { HomePageFixture } from './fixtures/homePageFixture' import { getUtils } from './test-utils' import { EngineCommand } from 'lang/std/artifactGraph' diff --git a/e2e/playwright/desktop-export.spec.ts b/e2e/playwright/desktop-export.spec.ts index ae92071ac..76bf36009 100644 --- a/e2e/playwright/desktop-export.spec.ts +++ b/e2e/playwright/desktop-export.spec.ts @@ -10,7 +10,11 @@ import fsp from 'fs/promises' test( 'export works on the first try', { tag: ['@electron', '@skipLocalEngine'] }, - async ({ page, context, scene }, testInfo) => { + async ({ page, context, scene, tronApp }, testInfo) => { + if (!tronApp) { + fail() + } + await context.folderSetupFn(async (dir) => { const bracketDir = path.join(dir, 'bracket') await Promise.all([fsp.mkdir(bracketDir, { recursive: true })]) @@ -86,7 +90,7 @@ test( await expect(exportingToastMessage).not.toBeVisible() const firstFileFullPath = path.resolve( - getPlaywrightDownloadDir(page), + getPlaywrightDownloadDir(tronApp.projectDirName), exportFileName ) await test.step('Check the export size', async () => { @@ -165,7 +169,7 @@ test( ])) const secondFileFullPath = path.resolve( - getPlaywrightDownloadDir(page), + getPlaywrightDownloadDir(tronApp.projectDirName), exportFileName ) await test.step('Check the export size', async () => { diff --git a/e2e/playwright/file-tree.spec.ts b/e2e/playwright/file-tree.spec.ts index fef404739..4b28a25c8 100644 --- a/e2e/playwright/file-tree.spec.ts +++ b/e2e/playwright/file-tree.spec.ts @@ -158,11 +158,14 @@ test.describe('when using the file tree to', () => { await createNewFile('lee') await test.step('Postcondition: there are 5 new lee-*.kcl files', async () => { - await expect( - page - .locator('[data-testid="file-pane-scroll-container"] button') - .filter({ hasText: /lee[-]?[0-5]?/ }) - ).toHaveCount(5) + await expect + .poll(() => + page + .locator('[data-testid="file-pane-scroll-container"] button') + .filter({ hasText: /lee[-]?[0-5]?/ }) + .count() + ) + .toEqual(5) }) } ) diff --git a/e2e/playwright/fixtures/cmdBarFixture.ts b/e2e/playwright/fixtures/cmdBarFixture.ts index 865aea548..18800ef9e 100644 --- a/e2e/playwright/fixtures/cmdBarFixture.ts +++ b/e2e/playwright/fixtures/cmdBarFixture.ts @@ -27,28 +27,19 @@ type CmdBarSerialised = export class CmdBarFixture { public page: Page - - get cmdBarOpenBtn() { - return this.page.getByTestId('command-bar-open-button') - } - - get cmdBarElement() { - return this.page.getByTestId('command-bar') - } + public cmdBarOpenBtn!: Locator + public cmdBarElement!: Locator constructor(page: Page) { this.page = page + this.cmdBarOpenBtn = this.page.getByTestId('command-bar-open-button') + this.cmdBarElement = this.page.getByTestId('command-bar') } get currentArgumentInput() { return this.page.getByTestId('cmd-bar-arg-value') } - // Put all selectors here because this method is re-run on fixture creation. - reConstruct = (page: Page) => { - this.page = page - } - private _serialiseCmdBar = async (): Promise => { if (!(await this.page.getByTestId('command-bar-wrapper').isVisible())) { return { stage: 'commandBarClosed' } diff --git a/e2e/playwright/fixtures/editorFixture.ts b/e2e/playwright/fixtures/editorFixture.ts index b8c5e2d82..c4723e4fd 100644 --- a/e2e/playwright/fixtures/editorFixture.ts +++ b/e2e/playwright/fixtures/editorFixture.ts @@ -24,11 +24,6 @@ export class EditorFixture { constructor(page: Page) { this.page = page - this.reConstruct(page) - } - reConstruct = (page: Page) => { - this.page = page - this.codeContent = page.locator('.cm-content[data-language="kcl"]') this.diagnosticsTooltip = page.locator('.cm-tooltip-lint') this.diagnosticsGutterIcon = page.locator('.cm-lint-marker-error') diff --git a/e2e/playwright/fixtures/fixtureSetup.ts b/e2e/playwright/fixtures/fixtureSetup.ts index 90ed51dbe..7e5897fde 100644 --- a/e2e/playwright/fixtures/fixtureSetup.ts +++ b/e2e/playwright/fixtures/fixtureSetup.ts @@ -1,13 +1,31 @@ +/* eslint-disable react-hooks/rules-of-hooks */ + import type { BrowserContext, ElectronApplication, + Fixtures as PlaywrightFixtures, TestInfo, Page, } from '@playwright/test' -import { getUtils, setup, setupElectron } from '../test-utils' +import { + _electron as electron, + PlaywrightTestArgs, + PlaywrightWorkerArgs, +} from '@playwright/test' + +import * as TOML from '@iarna/toml' +import { + TEST_SETTINGS_KEY, + TEST_SETTINGS_CORRUPTED, + TEST_SETTINGS, + TEST_SETTINGS_DEFAULT_THEME, +} from '../storageStates' +import { SETTINGS_FILE_NAME, PROJECT_SETTINGS_FILE_NAME } from 'lib/constants' +import { getUtils, setup } from '../test-utils' import fsp from 'fs/promises' -import { join } from 'path' +import fs from 'node:fs' +import path from 'path' import { CmdBarFixture } from './cmdBarFixture' import { EditorFixture } from './editorFixture' import { ToolbarFixture } from './toolbarFixture' @@ -23,7 +41,7 @@ export class AuthenticatedApp { public readonly testInfo: TestInfo public readonly viewPortSize = { width: 1200, height: 500 } public electronApp: undefined | ElectronApplication - public dir: string = '' + public projectDirName: string = '' constructor(context: BrowserContext, page: Page, testInfo: TestInfo) { this.context = context @@ -46,7 +64,7 @@ export class AuthenticatedApp { } getInputFile = (fileName: string) => { return fsp.readFile( - join('rust', 'kcl-lib', 'e2e', 'executor', 'inputs', fileName), + path.join('rust', 'kcl-lib', 'e2e', 'executor', 'inputs', fileName), 'utf-8' ) } @@ -59,101 +77,300 @@ export interface Fixtures { scene: SceneFixture homePage: HomePageFixture } -export class AuthenticatedTronApp { - public originalPage: Page - public page: Page - public browserContext: BrowserContext - public context: BrowserContext - public readonly testInfo: TestInfo - public electronApp: ElectronApplication | undefined - public readonly viewPortSize = { width: 1200, height: 500 } - public dir: string = '' - constructor( - browserContext: BrowserContext, - originalPage: Page, - testInfo: TestInfo - ) { - this.page = originalPage - this.originalPage = originalPage - this.browserContext = browserContext - // Will be overwritten in the initializer - this.context = browserContext - this.testInfo = testInfo - } - async initialise( - arg: { - fixtures: Partial - folderSetupFn?: (projectDirName: string) => Promise - cleanProjectDir?: boolean - appSettings?: DeepPartial - } = { fixtures: {} } - ) { - const { electronApp, page, context, dir } = await setupElectron({ - testInfo: this.testInfo, - folderSetupFn: arg.folderSetupFn, - cleanProjectDir: arg.cleanProjectDir, - appSettings: arg.appSettings, - viewport: this.viewPortSize, +export class ElectronZoo { + public available: boolean = true + public electron!: ElectronApplication + public firstUrl = '' + public viewPortSize = { width: 1200, height: 500 } + public projectDirName = '' + + public page!: Page + public context!: BrowserContext + + constructor() {} + + async makeAvailableAgain() { + // Help remote end by signaling we're done with the connection. + await this.page.evaluate(async () => { + return new Promise((resolve) => { + if (!window.engineCommandManager.engineConnection?.state?.type) { + return resolve(undefined) + } + + window.engineCommandManager.tearDown() + // Keep polling (per js event tick) until state is Disconnected. + const checkDisconnected = () => { + // It's possible we never even created an engineConnection + // e.g. never left Projects view. + if ( + window.engineCommandManager?.engineConnection?.state.type === + 'disconnected' + ) { + return resolve(undefined) + } + setTimeout(checkDisconnected, 0) + } + checkDisconnected() + }) }) - this.page = page - // These assignments "fix" some brokenness in the Playwright Workbench when - // running against electron applications. - // The timeline is still broken but failure screenshots work again. - this.context = context - // TODO: try to get this to work again for screenshots, but it messed with test ends when enabled - // Object.assign(this.browserContext, this.context) + await this.context.tracing.stopChunk({ path: 'trace.zip' }) - this.electronApp = electronApp - this.dir = dir + // Only after cleanup we're ready. + this.available = true + } - // Easier to access throughout utils - this.page.dir = dir + async createInstanceIfMissing(testInfo: TestInfo) { + // Create or otherwise clear the folder. + this.projectDirName = testInfo.outputPath('electron-test-projects-dir') - // Setup localStorage, addCookies, reload - await setup(this.context, this.page, this.testInfo) + // We need to expose this in order for some tests that require folder + // creation and some code below. + const that = this - for (const key of unsafeTypedKeys(arg.fixtures)) { - const fixture = arg.fixtures[key] - if ( - !fixture || - fixture instanceof AuthenticatedApp || - fixture instanceof AuthenticatedTronApp - ) - continue - fixture.reConstruct(page) + const options = { + args: ['.', '--no-sandbox'], + env: { + ...process.env, + TEST_SETTINGS_FILE_KEY: this.projectDirName, + IS_PLAYWRIGHT: 'true', + }, + ...(process.env.ELECTRON_OVERRIDE_DIST_PATH + ? { + executablePath: + process.env.ELECTRON_OVERRIDE_DIST_PATH + 'electron', + } + : {}), + ...(process.env.PLAYWRIGHT_RECORD_VIDEO + ? { + recordVideo: { + dir: testInfo.snapshotPath(), + size: this.viewPortSize, + }, + } + : {}), } + + // Do this once and then reuse window on subsequent calls. + if (!this.electron) { + this.electron = await electron.launch(options) + this.context = this.electron.context() + this.page = await this.electron.firstWindow() + await this.context.tracing.start({ screenshots: true, snapshots: true }) + } + + await this.context.tracing.startChunk() + + await setup(this.context, this.page, testInfo) + + await this.cleanProjectDir() + + // Create a consistent way to resize the page across electron and web. + // (lee) I had to do everything in the book to make electron change its + // damn window size. I succeeded in making it consistently and reliably + // do it after a whole afternoon. + this.page.setBodyDimensions = async function (dims: { + width: number + height: number + }) { + await this.setViewportSize(dims) + + await that.electron?.evaluateHandle(async ({ app }, dims) => { + // @ts-ignore sorry jon but see comment in main.ts why this is ignored + await app.resizeWindow(dims.width, dims.height) + }, dims) + + return this.evaluate(async (dims: { width: number; height: number }) => { + await window.electron.resizeWindow(dims.width, dims.height) + window.document.body.style.width = dims.width + 'px' + window.document.body.style.height = dims.height + 'px' + window.document.documentElement.style.width = dims.width + 'px' + window.document.documentElement.style.height = dims.height + 'px' + }, dims) + } + + await this.page.setBodyDimensions(this.viewPortSize) + + this.context.folderSetupFn = async function (fn) { + return fn(that.projectDirName) + .then(() => that.page.reload()) + .then(() => ({ + dir: that.projectDirName, + })) + } + + // We need to patch this because addInitScript will bind too late in our + // electron tests, never running. We need to call reload() after each call + // to guarantee it runs. + const oldContextAddInitScript = this.context.addInitScript + this.context.addInitScript = async function (a, b) { + // @ts-ignore pretty sure way out of tsc's type checking capabilities. + // This code works perfectly fine. + await oldContextAddInitScript.apply(this, [a, b]) + await that.page.reload() + } + + // No idea why we mix and match page and context's addInitScript but we do + const oldPageAddInitScript = this.page.addInitScript + this.page.addInitScript = async function (a: any, b: any) { + // @ts-ignore pretty sure way out of tsc's type checking capabilities. + // This code works perfectly fine. + await oldPageAddInitScript.apply(this, [a, b]) + await that.page.reload() + } + + if (!this.firstUrl) { + await this.page.getByText('Your Projects').count() + this.firstUrl = this.page.url() + } + + // Due to the app controlling its own window context we need to inject new + // options and context here. + // NOTE TO LEE: Seems to destroy page context when calling an electron loadURL. + // await tronApp.electronApp.evaluate(({ app }) => { + // return app.reuseWindowForTest(); + // }); + + await this.electron?.evaluate(({ app }, projectDirName) => { + // @ts-ignore can't declaration merge see main.ts + app.testProperty['TEST_SETTINGS_FILE_KEY'] = projectDirName + }, this.projectDirName) + + // Always start at the root view + await this.page.goto(this.firstUrl) + + // Force a hard reload, destroying the stream and other state + await this.page.reload() } - close = async () => { - await this.electronApp?.close?.() + async cleanProjectDir(appSettings?: DeepPartial) { + try { + if (fs.existsSync(this.projectDirName)) { + await fsp.rm(this.projectDirName, { recursive: true }) + } + } catch (e) { + console.error(e) + } + + try { + await fsp.mkdir(this.projectDirName) + } catch (e) { + // Not a problem if it already exists. + } + + const tempSettingsFilePath = path.join( + this.projectDirName, + SETTINGS_FILE_NAME + ) + + let settingsOverridesToml = '' + + if (appSettings) { + settingsOverridesToml = TOML.stringify({ + // @ts-expect-error + settings: { + ...TEST_SETTINGS, + ...appSettings, + app: { + ...TEST_SETTINGS.app, + project_directory: this.projectDirName, + ...appSettings.app, + }, + }, + }) + } else { + settingsOverridesToml = TOML.stringify({ + // @ts-expect-error + settings: { + ...TEST_SETTINGS, + app: { + ...TEST_SETTINGS.app, + project_directory: this.projectDirName, + }, + }, + }) + } + await fsp.writeFile(tempSettingsFilePath, settingsOverridesToml) } - debugPause = () => - new Promise(() => { - console.log('UN-RESOLVING PROMISE') - }) } -export const fixtures = { - cmdBar: async ({ page }: { page: Page }, use: any) => { - // eslint-disable-next-line react-hooks/rules-of-hooks +// If yee encounter this, please try to type it. +type FnUse = any + +const fixturesForElectron = { + page: async ( + { tronApp }: { tronApp: ElectronZoo }, + use: FnUse, + testInfo: TestInfo + ) => { + await tronApp.createInstanceIfMissing(testInfo) + await use(tronApp.page) + await tronApp?.makeAvailableAgain() + }, + context: async ( + { tronApp }: { tronApp: ElectronZoo }, + use: FnUse, + testInfo: TestInfo + ) => { + await tronApp.createInstanceIfMissing(testInfo) + await use(tronApp.context) + }, +} + +const fixturesForWeb = { + page: async ( + { page, context }: { page: Page; context: BrowserContext }, + use: FnUse, + testInfo: TestInfo + ) => { + page.setBodyDimensions = page.setViewportSize + + // We do the same thing in ElectronZoo. addInitScript simply doesn't fire + // at the correct time, so we reload the page and it fires appropriately. + const oldPageAddInitScript = page.addInitScript + page.addInitScript = async function (...args) { + // @ts-expect-error + await oldPageAddInitScript.apply(this, args) + await page.reload() + } + + const oldContextAddInitScript = context.addInitScript + context.addInitScript = async function (...args) { + // @ts-expect-error + await oldContextAddInitScript.apply(this, args) + await page.reload() + } + + const webApp = new AuthenticatedApp(context, page, testInfo) + await webApp.initialise() + + await use(page) + }, +} + +const fixturesBasedOnProcessEnvPlatform = { + cmdBar: async ({ page }: { page: Page }, use: FnUse) => { await use(new CmdBarFixture(page)) }, - editor: async ({ page }: { page: Page }, use: any) => { - // eslint-disable-next-line react-hooks/rules-of-hooks + editor: async ({ page }: { page: Page }, use: FnUse) => { await use(new EditorFixture(page)) }, - toolbar: async ({ page }: { page: Page }, use: any) => { - // eslint-disable-next-line react-hooks/rules-of-hooks + toolbar: async ({ page }: { page: Page }, use: FnUse) => { await use(new ToolbarFixture(page)) }, - scene: async ({ page }: { page: Page }, use: any) => { - // eslint-disable-next-line react-hooks/rules-of-hooks + scene: async ({ page }: { page: Page }, use: FnUse) => { await use(new SceneFixture(page)) }, - homePage: async ({ page }: { page: Page }, use: any) => { - // eslint-disable-next-line react-hooks/rules-of-hooks + homePage: async ({ page }: { page: Page }, use: FnUse) => { await use(new HomePageFixture(page)) }, } + +if (process.env.PLATFORM === 'web') { + Object.assign(fixturesBasedOnProcessEnvPlatform, fixturesForWeb) +} else { + Object.assign(fixturesBasedOnProcessEnvPlatform, fixturesForElectron) +} + +export { fixturesBasedOnProcessEnvPlatform } diff --git a/e2e/playwright/fixtures/homePageFixture.ts b/e2e/playwright/fixtures/homePageFixture.ts index 7606eed44..e6caf43a8 100644 --- a/e2e/playwright/fixtures/homePageFixture.ts +++ b/e2e/playwright/fixtures/homePageFixture.ts @@ -27,10 +27,6 @@ export class HomePageFixture { constructor(page: Page) { this.page = page - this.reConstruct(page) - } - reConstruct = (page: Page) => { - this.page = page this.projectSection = this.page.getByTestId('home-section') @@ -96,8 +92,12 @@ export class HomePageFixture { } } - createAndGoToProject = async (projectTitle = 'project-$nnn') => { + projectsLoaded = async () => { await expect(this.projectSection).not.toHaveText('Loading your Projects...') + } + + createAndGoToProject = async (projectTitle = 'project-$nnn') => { + await this.projectsLoaded() await this.projectButtonNew.click() await this.projectTextName.click() await this.projectTextName.fill(projectTitle) diff --git a/e2e/playwright/fixtures/sceneFixture.ts b/e2e/playwright/fixtures/sceneFixture.ts index 73ec11345..d7189a672 100644 --- a/e2e/playwright/fixtures/sceneFixture.ts +++ b/e2e/playwright/fixtures/sceneFixture.ts @@ -53,7 +53,12 @@ export class SceneFixture { constructor(page: Page) { this.page = page - this.reConstruct(page) + this.streamWrapper = page.getByTestId('stream') + this.networkToggleConnected = page.getByTestId('network-toggle-ok') + this.loadingIndicator = this.streamWrapper.getByTestId('loading') + this.startEditSketchBtn = page + .getByRole('button', { name: 'Start Sketch' }) + .or(page.getByRole('button', { name: 'Edit Sketch' })) } private _serialiseScene = async (): Promise => { const camera = await this.getCameraInfo() @@ -72,17 +77,6 @@ export class SceneFixture { .toEqual(expected) } - reConstruct = (page: Page) => { - this.page = page - - this.streamWrapper = page.getByTestId('stream') - this.networkToggleConnected = page.getByTestId('network-toggle-ok') - this.loadingIndicator = this.streamWrapper.getByTestId('loading') - this.startEditSketchBtn = page - .getByRole('button', { name: 'Start Sketch' }) - .or(page.getByRole('button', { name: 'Edit Sketch' })) - } - makeMouseHelpers = ( x: number, y: number, @@ -253,7 +247,7 @@ export class SceneFixture { await u.openDebugPanel() await u.expectCmdLog('[data-message-type="execution-done"]') - await u.clearAndCloseDebugPanel() + await u.closeDebugPanel() await this.waitForExecutionDone() await expect(this.startEditSketchBtn).not.toBeDisabled() diff --git a/e2e/playwright/fixtures/toolbarFixture.ts b/e2e/playwright/fixtures/toolbarFixture.ts index 6ab60f5d3..892a5775e 100644 --- a/e2e/playwright/fixtures/toolbarFixture.ts +++ b/e2e/playwright/fixtures/toolbarFixture.ts @@ -37,13 +37,12 @@ export class ToolbarFixture { featureTreeId = 'feature-tree' as const /** The pane element for the Feature Tree */ featureTreePane!: Locator + gizmo!: Locator + gizmoDisabled!: Locator constructor(page: Page) { this.page = page - this.reConstruct(page) - } - reConstruct = (page: Page) => { - this.page = page + this.extrudeButton = page.getByTestId('extrude') this.loftButton = page.getByTestId('loft') this.sweepButton = page.getByTestId('sweep') @@ -67,6 +66,13 @@ export class ToolbarFixture { this.filePane = page.locator('#files-pane') this.featureTreePane = page.locator('#feature-tree-pane') this.fileCreateToast = page.getByText('Successfully created') + + // Note to test writers: having two locators like this is preferable to one + // which changes another el property because it means our test "signal" is + // completely decoupled from the elements themselves. It means the same + // element or two different elements can represent these states. + this.gizmo = page.getByTestId('gizmo') + this.gizmoDisabled = page.getByTestId('gizmo-disabled') } get editSketchBtn() { @@ -86,6 +92,18 @@ export class ToolbarFixture { startSketchPlaneSelection = async () => doAndWaitForImageDiff(this.page, () => this.startSketchBtn.click(), 500) + waitUntilSketchingReady = async () => { + await expect(this.gizmoDisabled).toBeVisible() + } + + startSketchThenCallbackThenWaitUntilReady = async ( + cb: () => Promise + ) => { + await this.startSketchBtn.click() + await cb() + await this.waitUntilSketchingReady() + } + exitSketch = async () => { await this.exitSketchBtn.click() await expect( diff --git a/e2e/playwright/onboarding-tests.spec.ts b/e2e/playwright/onboarding-tests.spec.ts index 6343f6f8e..8be152a44 100644 --- a/e2e/playwright/onboarding-tests.spec.ts +++ b/e2e/playwright/onboarding-tests.spec.ts @@ -21,58 +21,54 @@ import { expectPixelColor } from './fixtures/sceneFixture' // we must set it to empty for the tests where we want to see the onboarding immediately. test.describe('Onboarding tests', () => { - test( - 'Onboarding code is shown in the editor', - { - appSettings: { - app: { - onboarding_status: '', - }, - }, - cleanProjectDir: true, - }, - async ({ page, homePage }) => { - const u = await getUtils(page) - await page.setBodyDimensions({ width: 1200, height: 500 }) - await homePage.goToModelingScene() - - // Test that the onboarding pane loaded - await expect( - page.getByText('Welcome to Modeling App! This') - ).toBeVisible() - - // Test that the onboarding pane loaded - await expect( - page.getByText('Welcome to Modeling App! This') - ).toBeVisible() - - // *and* that the code is shown in the editor - await expect(page.locator('.cm-content')).toContainText( - '// Shelf Bracket' - ) - - // Make sure the model loaded - const XYPlanePoint = { x: 774, y: 116 } as const - const modelColor: [number, number, number] = [45, 45, 45] - await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y) - expect(await u.getGreatestPixDiff(XYPlanePoint, modelColor)).toBeLessThan( - 8 - ) + test('Onboarding code is shown in the editor', async ({ + page, + homePage, + tronApp, + }) => { + if (!tronApp) { + fail() } - ) + await tronApp.cleanProjectDir({ + app: { + onboarding_status: '', + }, + }) + + const u = await getUtils(page) + await page.setBodyDimensions({ width: 1200, height: 500 }) + await homePage.goToModelingScene() + + // Test that the onboarding pane loaded + await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible() + + // Test that the onboarding pane loaded + await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible() + + // *and* that the code is shown in the editor + await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket') + + // Make sure the model loaded + const XYPlanePoint = { x: 774, y: 116 } as const + const modelColor: [number, number, number] = [45, 45, 45] + await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y) + expect(await u.getGreatestPixDiff(XYPlanePoint, modelColor)).toBeLessThan(8) + }) test( 'Desktop: fresh onboarding executes and loads', { tag: '@electron', - appSettings: { + }, + async ({ page, tronApp }) => { + if (!tronApp) { + fail() + } + await tronApp.cleanProjectDir({ app: { onboarding_status: '', }, - }, - cleanProjectDir: true, - }, - async ({ page }) => { + }) const u = await getUtils(page) const viewportSize = { width: 1200, height: 500 } @@ -107,223 +103,235 @@ test.describe('Onboarding tests', () => { } ) - test( - 'Code resets after confirmation', - { - cleanProjectDir: true, - }, - async ({ context, page, homePage }) => { - const initialCode = `sketch001 = startSketchOn('XZ')` + test('Code resets after confirmation', async ({ + context, + page, + homePage, + tronApp, + scene, + cmdBar, + }) => { + if (!tronApp) { + fail() + } + await tronApp.cleanProjectDir() - // Load the page up with some code so we see the confirmation warning - // when we go to replay onboarding - await context.addInitScript((code) => { - localStorage.setItem('persistCode', code) - }, initialCode) + const initialCode = `sketch001 = startSketchOn('XZ')` - await page.setBodyDimensions({ width: 1200, height: 500 }) - await homePage.goToModelingScene() + // Load the page up with some code so we see the confirmation warning + // when we go to replay onboarding + await page.addInitScript((code) => { + localStorage.setItem('persistCode', code) + }, initialCode) - // Replay the onboarding - await page.getByRole('link', { name: 'Settings' }).last().click() - const replayButton = page.getByRole('button', { - name: 'Replay onboarding', - }) - await expect(replayButton).toBeVisible() - await replayButton.click() + await page.setBodyDimensions({ width: 1200, height: 500 }) + await homePage.goToModelingScene() + await scene.connectionEstablished() - // Ensure we see the warning, and that the code has not yet updated - await expect(page.getByText('Would you like to create')).toBeVisible() - await expect(page.locator('.cm-content')).toHaveText(initialCode) + // Replay the onboarding + await page.getByRole('link', { name: 'Settings' }).last().click() + const replayButton = page.getByRole('button', { + name: 'Replay onboarding', + }) + await expect(replayButton).toBeVisible() + await replayButton.click() - const nextButton = page.getByTestId('onboarding-next') + // Ensure we see the warning, and that the code has not yet updated + await expect(page.getByText('Would you like to create')).toBeVisible() + await expect(page.locator('.cm-content')).toHaveText(initialCode) + + const nextButton = page.getByTestId('onboarding-next') + await nextButton.hover() + await nextButton.click() + + // Ensure we see the introduction and that the code has been reset + await expect(page.getByText('Welcome to Modeling App!')).toBeVisible() + await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket') + + // There used to be old code here that checked if we stored the reset + // code into localStorage but that isn't the case on desktop. It gets + // saved to the file system, which we have other tests for. + }) + + test('Click through each onboarding step and back', async ({ + context, + page, + homePage, + tronApp, + }) => { + if (!tronApp) { + fail() + } + await tronApp.cleanProjectDir({ + app: { + onboarding_status: '', + }, + }) + // Override beforeEach test setup + await context.addInitScript( + async ({ settingsKey, settings }) => { + // Give no initial code, so that the onboarding start is shown immediately + localStorage.setItem('persistCode', '') + localStorage.setItem(settingsKey, settings) + }, + { + settingsKey: TEST_SETTINGS_KEY, + settings: settingsToToml({ + settings: TEST_SETTINGS_ONBOARDING_START, + }), + } + ) + + await page.setBodyDimensions({ width: 1200, height: 1080 }) + await homePage.goToModelingScene() + + // Test that the onboarding pane loaded + await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible() + + const nextButton = page.getByTestId('onboarding-next') + const prevButton = page.getByTestId('onboarding-prev') + + while ((await nextButton.innerText()) !== 'Finish') { await nextButton.hover() await nextButton.click() - - // Ensure we see the introduction and that the code has been reset - await expect(page.getByText('Welcome to Modeling App!')).toBeVisible() - await expect(page.locator('.cm-content')).toContainText( - '// Shelf Bracket' - ) - - // There used to be old code here that checked if we stored the reset - // code into localStorage but that isn't the case on desktop. It gets - // saved to the file system, which we have other tests for. } - ) - test( - 'Click through each onboarding step and back', - { - appSettings: { - app: { - onboarding_status: '', - }, - }, - }, - async ({ context, page, homePage }) => { - // Override beforeEach test setup - await context.addInitScript( - async ({ settingsKey, settings }) => { - // Give no initial code, so that the onboarding start is shown immediately - localStorage.setItem('persistCode', '') - localStorage.setItem(settingsKey, settings) - }, - { - settingsKey: TEST_SETTINGS_KEY, - settings: settingsToToml({ - settings: TEST_SETTINGS_ONBOARDING_START, - }), - } - ) - - await page.setBodyDimensions({ width: 1200, height: 1080 }) - await homePage.goToModelingScene() - - // Test that the onboarding pane loaded - await expect( - page.getByText('Welcome to Modeling App! This') - ).toBeVisible() - - const nextButton = page.getByTestId('onboarding-next') - const prevButton = page.getByTestId('onboarding-prev') - - while ((await nextButton.innerText()) !== 'Finish') { - await nextButton.hover() - await nextButton.click() - } - - while ((await prevButton.innerText()) !== 'Dismiss') { - await prevButton.hover() - await prevButton.click() - } - - // Dismiss the onboarding + while ((await prevButton.innerText()) !== 'Dismiss') { await prevButton.hover() await prevButton.click() - - // Test that the onboarding pane is gone - await expect(page.getByTestId('onboarding-content')).not.toBeVisible() - await expect.poll(() => page.url()).not.toContain('/onboarding') } - ) - test( - 'Onboarding redirects and code updating', - { - appSettings: { - app: { - onboarding_status: '/export', - }, + // Dismiss the onboarding + await prevButton.hover() + await prevButton.click() + + // Test that the onboarding pane is gone + await expect(page.getByTestId('onboarding-content')).not.toBeVisible() + await expect.poll(() => page.url()).not.toContain('/onboarding') + }) + + test('Onboarding redirects and code updating', async ({ + context, + page, + homePage, + tronApp, + }) => { + if (!tronApp) { + fail() + } + await tronApp.cleanProjectDir({ + app: { + onboarding_status: '/export', }, - cleanProjectDir: true, - }, - async ({ context, page, homePage }) => { - const originalCode = 'sigmaAllow = 15000' + }) - // Override beforeEach test setup - await context.addInitScript( - async ({ settingsKey, settings }) => { - // Give some initial code, so we can test that it's cleared - localStorage.setItem('persistCode', originalCode) - localStorage.setItem(settingsKey, settings) - }, - { - settingsKey: TEST_SETTINGS_KEY, - settings: settingsToToml({ - settings: TEST_SETTINGS_ONBOARDING_EXPORT, - }), - } - ) + const originalCode = 'sigmaAllow = 15000' - await page.setBodyDimensions({ width: 1200, height: 500 }) - await homePage.goToModelingScene() - - // Test that the redirect happened - await expect.poll(() => page.url()).toContain('/onboarding/export') - - // Test that you come back to this page when you refresh - await page.reload() - await expect.poll(() => page.url()).toContain('/onboarding/export') - - // Test that the code changes when you advance to the next step - await page.getByTestId('onboarding-next').hover() - await page.getByTestId('onboarding-next').click() - - // Test that the onboarding pane loaded - const title = page.locator('[data-testid="onboarding-content"]') - await expect(title).toBeAttached() - - await expect(page.locator('.cm-content')).not.toHaveText(originalCode) - - // Test that the code is not empty when you click on the next step - await page.locator('[data-testid="onboarding-next"]').hover() - await page.locator('[data-testid="onboarding-next"]').click() - await expect(page.locator('.cm-content')).toHaveText(/.+/) - } - ) - - test( - 'Onboarding code gets reset to demo on Interactive Numbers step', - { - appSettings: { - app: { - onboarding_status: '/parametric-modeling', - }, + // Override beforeEach test setup + await context.addInitScript( + async ({ settingsKey, settings }) => { + // Give some initial code, so we can test that it's cleared + localStorage.setItem('persistCode', originalCode) + localStorage.setItem(settingsKey, settings) }, - cleanProjectDir: true, - }, + { + settingsKey: TEST_SETTINGS_KEY, + settings: settingsToToml({ + settings: TEST_SETTINGS_ONBOARDING_EXPORT, + }), + } + ) - async ({ page, homePage }) => { - const u = await getUtils(page) - const badCode = `// This is bad code we shouldn't see` + await page.setBodyDimensions({ width: 1200, height: 500 }) + await homePage.goToModelingScene() - await page.setBodyDimensions({ width: 1200, height: 1080 }) - await homePage.goToModelingScene() + // Test that the redirect happened + await expect.poll(() => page.url()).toContain('/onboarding/export') - await expect - .poll(() => page.url()) - .toContain(onboardingPaths.PARAMETRIC_MODELING) + // Test that you come back to this page when you refresh + await page.reload() + await expect.poll(() => page.url()).toContain('/onboarding/export') - const bracketNoNewLines = bracket.replace(/\n/g, '') + // Test that the code changes when you advance to the next step + await page.getByTestId('onboarding-next').hover() + await page.getByTestId('onboarding-next').click() - // Check the code got reset on load - await expect(page.locator('#code-pane')).toBeVisible() - await expect(u.codeLocator).toHaveText(bracketNoNewLines, { - timeout: 10_000, - }) + // Test that the onboarding pane loaded + const title = page.locator('[data-testid="onboarding-content"]') + await expect(title).toBeAttached() - // Mess with the code again - await u.codeLocator.selectText() - await u.codeLocator.fill(badCode) - await expect(u.codeLocator).toHaveText(badCode) + await expect(page.locator('.cm-content')).not.toHaveText(originalCode) - // Click to the next step - await page.locator('[data-testid="onboarding-next"]').hover() - await page.locator('[data-testid="onboarding-next"]').click() - await page.waitForURL('**' + onboardingPaths.INTERACTIVE_NUMBERS, { - waitUntil: 'domcontentloaded', - }) + // Test that the code is not empty when you click on the next step + await page.locator('[data-testid="onboarding-next"]').hover() + await page.locator('[data-testid="onboarding-next"]').click() + await expect(page.locator('.cm-content')).toHaveText(/.+/) + }) - // Check that the code has been reset - await expect(u.codeLocator).toHaveText(bracketNoNewLines) + test('Onboarding code gets reset to demo on Interactive Numbers step', async ({ + page, + homePage, + tronApp, + }) => { + if (!tronApp) { + fail() } - ) + await tronApp.cleanProjectDir({ + app: { + onboarding_status: '/parametric-modeling', + }, + }) + + const u = await getUtils(page) + const badCode = `// This is bad code we shouldn't see` + + await page.setBodyDimensions({ width: 1200, height: 1080 }) + await homePage.goToModelingScene() + + await expect + .poll(() => page.url()) + .toContain(onboardingPaths.PARAMETRIC_MODELING) + + const bracketNoNewLines = bracket.replace(/\n/g, '') + + // Check the code got reset on load + await expect(page.locator('#code-pane')).toBeVisible() + await expect(u.codeLocator).toHaveText(bracketNoNewLines, { + timeout: 10_000, + }) + + // Mess with the code again + await u.codeLocator.selectText() + await u.codeLocator.fill(badCode) + await expect(u.codeLocator).toHaveText(badCode) + + // Click to the next step + await page.locator('[data-testid="onboarding-next"]').hover() + await page.locator('[data-testid="onboarding-next"]').click() + await page.waitForURL('**' + onboardingPaths.INTERACTIVE_NUMBERS, { + waitUntil: 'domcontentloaded', + }) + + // Check that the code has been reset + await expect(u.codeLocator).toHaveText(bracketNoNewLines) + }) // (lee) The two avatar tests are weird because even on main, we don't have // anything to do with the avatar inside the onboarding test. Due to the // low impact of an avatar not showing I'm changing this to fixme. test.fixme( 'Avatar text updates depending on image load success', - { - appSettings: { + async ({ context, page, homePage, tronApp }) => { + if (!tronApp) { + fail() + } + + await tronApp.cleanProjectDir({ app: { onboarding_status: '', }, - }, - cleanProjectDir: true, - }, - async ({ context, page, homePage }) => { + }) + // Override beforeEach test setup await context.addInitScript( async ({ settingsKey, settings }) => { @@ -388,15 +396,16 @@ test.describe('Onboarding tests', () => { test.fixme( "Avatar text doesn't mention avatar when no avatar", - { - appSettings: { + async ({ context, page, homePage, tronApp }) => { + if (!tronApp) { + fail() + } + + await tronApp.cleanProjectDir({ app: { onboarding_status: '', }, - }, - cleanProjectDir: true, - }, - async ({ context, page, homePage }) => { + }) // Override beforeEach test setup await context.addInitScript( async ({ settingsKey, settings }) => { @@ -444,15 +453,17 @@ test.describe('Onboarding tests', () => { test.fixme( 'Restarting onboarding on desktop takes one attempt', - { - appSettings: { + async ({ context, page, tronApp }) => { + if (!tronApp) { + fail() + } + + await tronApp.cleanProjectDir({ app: { onboarding_status: 'dismissed', }, - }, - cleanProjectDir: true, - }, - async ({ context, page }) => { + }) + await context.folderSetupFn(async (dir) => { const routerTemplateDir = join(dir, 'router-template-slate') await fsp.mkdir(routerTemplateDir, { recursive: true }) diff --git a/e2e/playwright/point-click.spec.ts b/e2e/playwright/point-click.spec.ts index 139898784..7bb57ce4a 100644 --- a/e2e/playwright/point-click.spec.ts +++ b/e2e/playwright/point-click.spec.ts @@ -1,4 +1,5 @@ -import { test, expect, Page } from './zoo-test' +import { Page } from '@playwright/test' +import { test, expect } from './zoo-test' import { EditorFixture } from './fixtures/editorFixture' import { SceneFixture } from './fixtures/sceneFixture' import { ToolbarFixture } from './fixtures/toolbarFixture' diff --git a/e2e/playwright/projects.spec.ts b/e2e/playwright/projects.spec.ts index 07397a8b9..e32b582b4 100644 --- a/e2e/playwright/projects.spec.ts +++ b/e2e/playwright/projects.spec.ts @@ -163,7 +163,7 @@ test( .poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), { timeout: 10_000, }) - .toBeLessThan(15) + .toBeLessThan(20) }) await test.step('Clicking the logo takes us back to the projects page / home', async () => { @@ -464,7 +464,11 @@ test.describe('Can export from electron app', () => { test( `Can export using ${method}`, { tag: ['@electron', '@skipLocalEngine'] }, - async ({ context, page }, testInfo) => { + async ({ context, page, tronApp }, testInfo) => { + if (!tronApp) { + fail() + } + await context.folderSetupFn(async (dir) => { const bracketDir = path.join(dir, 'bracket') await fsp.mkdir(bracketDir, { recursive: true }) @@ -516,6 +520,7 @@ test.describe('Can export from electron app', () => { storage: 'embedded', presentation: 'pretty', }, + tronApp.projectDirName, page, method ) @@ -523,7 +528,7 @@ test.describe('Can export from electron app', () => { }) const filepath = path.resolve( - getPlaywrightDownloadDir(page), + getPlaywrightDownloadDir(tronApp.projectDirName), 'main.gltf' ) @@ -781,6 +786,7 @@ test( page.on('console', console.log) await expect(page.getByText('router-template-slate')).toBeVisible() + await expect(page.getByText('Loading your Projects...')).not.toBeVisible() await expect(page.getByText('Your Projects')).toBeVisible() await page.keyboard.press('Delete') @@ -858,7 +864,7 @@ test.describe(`Project management commands`, () => { test( `Delete from project page`, { tag: '@electron' }, - async ({ context, page }, testInfo) => { + async ({ context, page, scene, cmdBar }, testInfo) => { const projectName = `my_project_to_delete` await context.folderSetupFn(async (dir) => { await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) @@ -887,6 +893,8 @@ test.describe(`Project management commands`, () => { await projectHomeLink.click() await u.waitForPageLoad() + await scene.connectionEstablished() + await scene.settled(cmdBar) }) await test.step(`Run delete command via command palette`, async () => { @@ -909,7 +917,7 @@ test.describe(`Project management commands`, () => { test( `Rename from home page`, { tag: '@electron' }, - async ({ context, page }, testInfo) => { + async ({ context, page, homePage }, testInfo) => { const projectName = `my_project_to_rename` await context.folderSetupFn(async (dir) => { await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) @@ -936,6 +944,7 @@ test.describe(`Project management commands`, () => { await test.step(`Setup`, async () => { await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) + await homePage.projectsLoaded() await expect(projectHomeLink).toBeVisible() }) @@ -1682,7 +1691,11 @@ test( test( 'You can change the root projects directory and nothing is lost', { tag: '@electron' }, - async ({ context, page, electronApp }, testInfo) => { + async ({ context, page, tronApp, homePage }, testInfo) => { + if (!tronApp) { + fail() + } + await context.folderSetupFn(async (dir) => { await Promise.all([ fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }), @@ -1712,6 +1725,8 @@ test( await fsp.rm(newProjectDirName, { recursive: true }) } + await homePage.projectsLoaded() + await test.step('We can change the root project directory', async () => { // expect to see the project directory settings link await expect( @@ -1725,7 +1740,7 @@ test( .locator('section#projectDirectory input') .inputValue() - const handleFile = electronApp?.evaluate( + const handleFile = tronApp.electron.evaluate( async ({ dialog }, filePaths) => { dialog.showOpenDialog = () => Promise.resolve({ canceled: false, filePaths }) @@ -1741,6 +1756,8 @@ test( await page.getByTestId('settings-close-button').click() + await homePage.projectsLoaded() + await expect(page.getByText('No Projects found')).toBeVisible() await createProject({ name: 'project-000', page, returnHome: true }) await expect( @@ -1755,7 +1772,7 @@ test( await page.getByTestId('project-directory-settings-link').click() - const handleFile = electronApp?.evaluate( + const handleFile = tronApp.electron.evaluate( async ({ dialog }, filePaths) => { dialog.showOpenDialog = () => Promise.resolve({ canceled: false, filePaths }) @@ -1767,6 +1784,7 @@ test( await page.getByTestId('project-directory-button').click() await handleFile + await homePage.projectsLoaded() await expect(page.locator('section#projectDirectory input')).toHaveValue( originalProjectDirName ) @@ -2000,8 +2018,8 @@ test( test( 'Settings persist across restarts', - { tag: '@electron', cleanProjectDir: true }, - async ({ page }, testInfo) => { + { tag: '@electron' }, + async ({ page, scene, cmdBar }, testInfo) => { await test.step('We can change a user setting like theme', async () => { await page.setBodyDimensions({ width: 1200, height: 500 }) @@ -2014,6 +2032,10 @@ test( await expect(page.getByTestId('app-theme')).toHaveValue('dark') await page.getByTestId('app-theme').selectOption('light') + await expect(page.getByTestId('app-theme')).toHaveValue('light') + + // Give time to system for writing to a persistent store + await page.waitForTimeout(1000) }) await test.step('Starting the app again and we can see the same theme', async () => { diff --git a/e2e/playwright/regression-tests.spec.ts b/e2e/playwright/regression-tests.spec.ts index 6de674d26..af3747f81 100644 --- a/e2e/playwright/regression-tests.spec.ts +++ b/e2e/playwright/regression-tests.spec.ts @@ -1,4 +1,5 @@ -import { test, expect, Page } from './zoo-test' +import { Page } from '@playwright/test' +import { test, expect } from './zoo-test' import path from 'path' import * as fsp from 'fs/promises' import { getUtils, executorInputPath } from './test-utils' diff --git a/e2e/playwright/sketch-tests.spec.ts b/e2e/playwright/sketch-tests.spec.ts index f9660dbb3..5ac703464 100644 --- a/e2e/playwright/sketch-tests.spec.ts +++ b/e2e/playwright/sketch-tests.spec.ts @@ -1,4 +1,5 @@ -import { test, expect, Page } from './zoo-test' +import { Page } from '@playwright/test' +import { test, expect } from './zoo-test' import fs from 'node:fs/promises' import path from 'node:path' import { HomePageFixture } from './fixtures/homePageFixture' @@ -2153,6 +2154,8 @@ extrude001 = extrude(profile003, length = 5) await page.setBodyDimensions({ width: 1000, height: 500 }) await homePage.goToModelingScene() + + await page.waitForTimeout(5000) await expect( page.getByRole('button', { name: 'Start Sketch' }) ).not.toBeDisabled() @@ -2165,7 +2168,7 @@ extrude001 = extrude(profile003, length = 5) await page.waitForTimeout(600) await editor.expectEditor.toContain(`sketch001 = startSketchOn('XZ')`) - await toolbar.exitSketchBtn.click() + await toolbar.exitSketch() await editor.expectEditor.not.toContain(`sketch001 = startSketchOn('XZ')`) @@ -2181,6 +2184,8 @@ extrude001 = extrude(profile003, length = 5) )` ) + await scene.settled(cmdBar) + await scene.expectPixelColor([255, 255, 255], { x: 633, y: 211 }, 15) }) }) diff --git a/e2e/playwright/snapshot-tests.spec.ts b/e2e/playwright/snapshot-tests.spec.ts index 33e9bf40c..528a86b0f 100644 --- a/e2e/playwright/snapshot-tests.spec.ts +++ b/e2e/playwright/snapshot-tests.spec.ts @@ -31,8 +31,7 @@ test.beforeEach(async ({ page, context }) => { // Help engine-manager: tear shit down. test.afterEach(async ({ page }) => { await page.evaluate(() => { - // @ts-expect-error - window.tearDown() + window.engineCommandManager.tearDown() }) }) @@ -45,7 +44,11 @@ test.setTimeout(60_000) test.skip( 'exports of each format should work', { tag: ['@snapshot', '@skipWin', '@skipMacos'] }, - async ({ page, context, scene, cmdBar }) => { + async ({ page, context, scene, cmdBar, tronApp }) => { + if (!tronApp) { + fail() + } + // FYI this test doesn't work with only engine running locally // And you will need to have the KittyCAD CLI installed const u = await getUtils(page) @@ -134,6 +137,7 @@ part001 = startSketchOn('-XZ') storage: 'ascii', units: 'in', }, + tronApp.projectDirName, page ) ) @@ -146,6 +150,7 @@ part001 = startSketchOn('-XZ') selection: { type: 'default_scene' }, units: 'in', }, + tronApp.projectDirName, page ) ) @@ -158,6 +163,7 @@ part001 = startSketchOn('-XZ') selection: { type: 'default_scene' }, units: 'in', }, + tronApp.projectDirName, page ) ) @@ -170,6 +176,7 @@ part001 = startSketchOn('-XZ') units: 'in', selection: { type: 'default_scene' }, }, + tronApp.projectDirName, page ) ) @@ -182,6 +189,7 @@ part001 = startSketchOn('-XZ') units: 'in', selection: { type: 'default_scene' }, }, + tronApp.projectDirName, page ) ) @@ -193,6 +201,7 @@ part001 = startSketchOn('-XZ') coords: sysType, units: 'in', }, + tronApp.projectDirName, page ) ) @@ -203,6 +212,7 @@ part001 = startSketchOn('-XZ') storage: 'embedded', presentation: 'pretty', }, + tronApp.projectDirName, page ) ) @@ -213,6 +223,7 @@ part001 = startSketchOn('-XZ') storage: 'binary', presentation: 'pretty', }, + tronApp.projectDirName, page ) ) @@ -223,6 +234,7 @@ part001 = startSketchOn('-XZ') storage: 'standard', presentation: 'pretty', }, + tronApp.projectDirName, page ) ) diff --git a/e2e/playwright/test-network-and-connection-issues.spec.ts b/e2e/playwright/test-network-and-connection-issues.spec.ts index 14aa36278..9d861cf16 100644 --- a/e2e/playwright/test-network-and-connection-issues.spec.ts +++ b/e2e/playwright/test-network-and-connection-issues.spec.ts @@ -84,7 +84,7 @@ test.describe('Test network and connection issues', () => { 'Engine disconnect & reconnect in sketch mode', { tag: '@skipLocalEngine' }, async ({ page, homePage }) => { - // TODO: Don't skip Mac for these. After `window.tearDown` is working in Safari, these should work on webkit + // TODO: Don't skip Mac for these. After `window.engineCommandManager.tearDown` is working in Safari, these should work on webkit const networkToggle = page.getByTestId('network-toggle') const u = await getUtils(page) diff --git a/e2e/playwright/test-utils.ts b/e2e/playwright/test-utils.ts index a08c6331c..6d10ecff0 100644 --- a/e2e/playwright/test-utils.ts +++ b/e2e/playwright/test-utils.ts @@ -5,8 +5,9 @@ import { _electron as electron, ElectronApplication, Locator, + Page, } from '@playwright/test' -import { test, Page } from './zoo-test' +import { test } from './zoo-test' import { EngineCommand } from 'lang/std/artifactGraph' import fsp from 'fs/promises' import fsSync from 'fs' @@ -337,7 +338,7 @@ export const getMovementUtils = (opts: any) => { async function waitForAuthAndLsp(page: Page) { const waitForLspPromise = page.waitForEvent('console', { - predicate: async (message) => { + predicate: async (message: any) => { // it would be better to wait for a message that the kcl lsp has started by looking for the message message.text().includes('[lsp] [window/logMessage]') // but that doesn't seem to make it to the console for macos/safari :( if (message.text().includes('start kcl lsp')) { @@ -420,7 +421,7 @@ export async function getUtils(page: Page, test_?: typeof test) { const overlay = page.locator(locator) const bbox = await overlay .boundingBox({ timeout: 5_000 }) - .then((box) => ({ ...box, x: box?.x || 0, y: box?.y || 0 })) + .then((box: any) => ({ ...box, x: box?.x || 0, y: box?.y || 0 })) const angle = Number(await overlay.getAttribute('data-overlay-angle')) const angleXOffset = Math.cos(((angle - 180) * Math.PI) / 180) * px const angleYOffset = Math.sin(((angle - 180) * Math.PI) / 180) * px @@ -437,7 +438,7 @@ export async function getUtils(page: Page, test_?: typeof test) { page .locator(locator) .boundingBox({ timeout: 5_000 }) - .then((box) => ({ ...box, x: box?.x || 0, y: box?.y || 0 })), + .then((box: any) => ({ ...box, x: box?.x || 0, y: box?.y || 0 })), codeLocator: page.locator('.cm-content'), crushKclCodeIntoOneLineAndThenMaybeSome: async () => { const code = await page.locator('.cm-content').innerText() @@ -504,7 +505,7 @@ export async function getUtils(page: Page, test_?: typeof test) { ) => { if (cdpSession === null) { // Use a fail safe if we can't simulate disconnect (on Safari) - return page.evaluate('window.tearDown()') + return page.evaluate('window.engineCommandManager.tearDown()') } return cdpSession?.send( @@ -631,7 +632,7 @@ export async function getUtils(page: Page, test_?: typeof test) { panesOpen: async (paneIds: PaneId[]) => { return test?.step(`Setting ${paneIds} panes to be open`, async () => { await page.addInitScript( - ({ PERSIST_MODELING_CONTEXT, paneIds }) => { + ({ PERSIST_MODELING_CONTEXT, paneIds }: any) => { localStorage.setItem( PERSIST_MODELING_CONTEXT, JSON.stringify({ openPanes: paneIds }) @@ -722,14 +723,14 @@ export const makeTemplate: ( const PLAYWRIGHT_DOWNLOAD_DIR = 'downloads-during-playwright' -export const getPlaywrightDownloadDir = (page: Page) => { - return path.resolve(page.dir, PLAYWRIGHT_DOWNLOAD_DIR) +export const getPlaywrightDownloadDir = (rootDir: string) => { + return path.resolve(rootDir, PLAYWRIGHT_DOWNLOAD_DIR) } -const moveDownloadedFileTo = async (page: Page, toLocation: string) => { +const moveDownloadedFileTo = async (rootDir: string, toLocation: string) => { await fsp.mkdir(path.dirname(toLocation), { recursive: true }) - const downloadDir = getPlaywrightDownloadDir(page) + const downloadDir = getPlaywrightDownloadDir(rootDir) // Expect there to be at least one file await expect @@ -756,6 +757,7 @@ export interface Paths { export const doExport = async ( output: Models['OutputFormat_type'], + rootDir: string, page: Page, exportFrom: 'dropdown' | 'sidebarButton' | 'commandBar' = 'dropdown' ): Promise => { @@ -836,7 +838,7 @@ export const doExport = async ( // (declared in src/lib/exportSave) // To remain consistent with our old web tests, we want to move some downloads // (images) to another directory. - await moveDownloadedFileTo(page, downloadLocation) + await moveDownloadedFileTo(rootDir, downloadLocation) } return { @@ -859,12 +861,6 @@ export async function tearDown(page: Page, testInfo: TestInfo) { downloadThroughput: -1, uploadThroughput: -1, }) - - // It seems it's best to give the browser about 3s to close things - // It's not super reliable but we have no real other choice for now - await page.waitForTimeout(3000) - - await testInfo.tronApp?.close() } // settingsOverrides may need to be augmented to take more generic items, @@ -936,107 +932,11 @@ let electronApp: ElectronApplication | undefined = undefined let context: BrowserContext | undefined = undefined let page: Page | undefined = undefined -export async function setupElectron({ - testInfo, - cleanProjectDir = true, - appSettings, - viewport, -}: { - testInfo: TestInfo - folderSetupFn?: (projectDirName: string) => Promise - cleanProjectDir?: boolean - appSettings?: DeepPartial - viewport: { - width: number - height: number - } -}): Promise<{ - electronApp: ElectronApplication - context: BrowserContext - page: Page - dir: string -}> { - // create or otherwise clear the folder - const projectDirName = testInfo.outputPath('electron-test-projects-dir') - try { - if (fsSync.existsSync(projectDirName) && cleanProjectDir) { - await fsp.rm(projectDirName, { recursive: true }) - } - } catch (e) { - console.error(e) - } - - if (cleanProjectDir) { - await fsp.mkdir(projectDirName) - } - - const options = { - args: ['.', '--no-sandbox'], - env: { - ...process.env, - TEST_SETTINGS_FILE_KEY: projectDirName, - IS_PLAYWRIGHT: 'true', - }, - ...(process.env.ELECTRON_OVERRIDE_DIST_PATH - ? { executablePath: process.env.ELECTRON_OVERRIDE_DIST_PATH + 'electron' } - : {}), - ...(process.env.PLAYWRIGHT_RECORD_VIDEO - ? { - recordVideo: { - dir: testInfo.snapshotPath(), - size: viewport, - }, - } - : {}), - } - - // Do this once and then reuse window on subsequent calls. - if (!electronApp) { - electronApp = await electron.launch(options) - } - - if (!context || !page) { - context = electronApp.context() - page = await electronApp.firstWindow() - context.on('console', console.log) - page.on('console', console.log) - } - - if (cleanProjectDir) { - const tempSettingsFilePath = path.join(projectDirName, SETTINGS_FILE_NAME) - const settingsOverrides = settingsToToml( - appSettings - ? { - settings: { - ...TEST_SETTINGS, - ...appSettings, - app: { - ...TEST_SETTINGS.app, - project_directory: projectDirName, - ...appSettings.app, - }, - }, - } - : { - settings: { - ...TEST_SETTINGS, - app: { - ...TEST_SETTINGS.app, - project_directory: projectDirName, - }, - }, - } - ) - await fsp.writeFile(tempSettingsFilePath, settingsOverrides) - } - - return { electronApp, page, context, dir: projectDirName } -} - function failOnConsoleErrors(page: Page, testInfo?: TestInfo) { // enabled for chrome for now if (page.context().browser()?.browserType().name() === 'chromium') { - page.on('pageerror', (exception) => { + // No idea wtf exception is + page.on('pageerror', (exception: any) => { if (isErrorWhitelisted(exception)) { return } diff --git a/e2e/playwright/testing-segment-overlays.spec.ts b/e2e/playwright/testing-segment-overlays.spec.ts index 52219d3fa..65456d06b 100644 --- a/e2e/playwright/testing-segment-overlays.spec.ts +++ b/e2e/playwright/testing-segment-overlays.spec.ts @@ -1,4 +1,5 @@ -import { test, expect, Page } from './zoo-test' +import { Page } from '@playwright/test' +import { test, expect } from './zoo-test' import { deg, getUtils, wiggleMove } from './test-utils' import { LineInputsType } from 'lang/std/sketchcombos' diff --git a/e2e/playwright/testing-settings.spec.ts b/e2e/playwright/testing-settings.spec.ts index 70babbff6..aed910fcd 100644 --- a/e2e/playwright/testing-settings.spec.ts +++ b/e2e/playwright/testing-settings.spec.ts @@ -20,35 +20,40 @@ import { DeepPartial } from 'lib/types' import { Settings } from '@rust/kcl-lib/bindings/Settings' test.describe('Testing settings', () => { - test( - 'Stored settings are validated and fall back to defaults', + test('Stored settings are validated and fall back to defaults', async ({ + page, + homePage, + tronApp, + }) => { + if (!tronApp) { + fail() + } // Override beforeEach test setup // with corrupted settings - { - appSettings: TEST_SETTINGS_CORRUPTED as DeepPartial, - }, - async ({ page, homePage }) => { - await page.setBodyDimensions({ width: 1200, height: 500 }) + await tronApp.cleanProjectDir( + TEST_SETTINGS_CORRUPTED as DeepPartial + ) - // Check the settings were reset - const storedSettings = tomlToSettings( - await page.evaluate( - ({ settingsKey }) => localStorage.getItem(settingsKey) || '', - { settingsKey: TEST_SETTINGS_KEY } - ) + await page.setBodyDimensions({ width: 1200, height: 500 }) + + // Check the settings were reset + const storedSettings = tomlToSettings( + await page.evaluate( + ({ settingsKey }) => localStorage.getItem(settingsKey) || '', + { settingsKey: TEST_SETTINGS_KEY } ) + ) - expect(storedSettings.settings?.app?.theme).toBe('dark') + expect(storedSettings.settings?.app?.theme).toBe('dark') - // Check that the invalid settings were changed to good defaults - expect(storedSettings.settings?.modeling?.base_unit).toBe('in') - expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo') - expect(storedSettings.settings?.app?.project_directory).toBe('') - expect(storedSettings.settings?.project?.default_project_name).toBe( - 'project-$nnn' - ) - } - ) + // Check that the invalid settings were changed to good defaults + expect(storedSettings.settings?.modeling?.base_unit).toBe('in') + expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo') + expect(storedSettings.settings?.app?.project_directory).toBe('') + expect(storedSettings.settings?.project?.default_project_name).toBe( + 'project-$nnn' + ) + }) // The behavior is actually broken. Parent always takes precedence test.fixme( @@ -357,8 +362,6 @@ test.describe('Testing settings', () => { `Load desktop app with no settings file`, { tag: '@electron', - // This is what makes no settings file get created - cleanProjectDir: false, }, async ({ page }, testInfo) => { await page.setBodyDimensions({ width: 1200, height: 500 }) @@ -379,13 +382,17 @@ test.describe('Testing settings', () => { `Load desktop app with a settings file, but no project directory setting`, { tag: '@electron', - appSettings: { + }, + async ({ context, page, tronApp }, testInfo) => { + if (!tronApp) { + fail() + } + await tronApp.cleanProjectDir({ app: { theme_color: '259', }, - }, - }, - async ({ context, page }, testInfo) => { + }) + await page.setBodyDimensions({ width: 1200, height: 500 }) // Selectors and constants @@ -405,15 +412,20 @@ test.describe('Testing settings', () => { 'user settings reload on external change, on project and modeling view', { tag: '@electron', - appSettings: { + }, + async ({ context, page, tronApp }, testInfo) => { + if (!tronApp) { + fail() + } + + await tronApp.cleanProjectDir({ app: { // Doesn't matter what you set it to. It will // default to 264.5 theme_color: '0', }, - }, - }, - async ({ context, page }, testInfo) => { + }) + const { dir: projectDirName } = await context.folderSetupFn( async () => {} ) @@ -783,128 +795,136 @@ test.describe('Testing settings', () => { }) }) - test( - `Changing system theme preferences (via media query) should update UI and stream`, - { - // Override the settings so that the theme is set to `system` - appSettings: TEST_SETTINGS_DEFAULT_THEME, - }, - async ({ page, homePage }) => { - const u = await getUtils(page) - - // Selectors and constants - const darkBackgroundCss = 'oklch(0.3012 0 264.5)' - const lightBackgroundCss = 'oklch(0.9911 0 264.5)' - const darkBackgroundColor: [number, number, number] = [27, 27, 27] - const lightBackgroundColor: [number, number, number] = [245, 245, 245] - const streamBackgroundPixelIsColor = async ( - color: [number, number, number] - ) => { - return u.getGreatestPixDiff({ x: 1000, y: 200 }, color) - } - const toolbar = page.locator('menu').filter({ hasText: 'Start Sketch' }) - - await test.step(`Test setup`, async () => { - await page.setBodyDimensions({ width: 1200, height: 500 }) - await homePage.goToModelingScene() - await u.waitForPageLoad() - await page.waitForTimeout(1000) - await expect(toolbar).toBeVisible() - }) - - await test.step(`Check the background color is light before`, async () => { - await expect(toolbar).toHaveCSS('background-color', lightBackgroundCss) - await expect - .poll(() => streamBackgroundPixelIsColor(lightBackgroundColor)) - .toBeLessThan(15) - }) - - await test.step(`Change media query preference to dark, emulating dusk with system theme`, async () => { - await page.emulateMedia({ colorScheme: 'dark' }) - }) - - await test.step(`Check the background color is dark after`, async () => { - await expect(toolbar).toHaveCSS('background-color', darkBackgroundCss) - await expect - .poll(() => streamBackgroundPixelIsColor(darkBackgroundColor)) - .toBeLessThan(15) - }) + test(`Changing system theme preferences (via media query) should update UI and stream`, async ({ + page, + homePage, + tronApp, + }) => { + if (!tronApp) { + fail() } - ) - test( - `Turning off "Show debug panel" with debug panel open leaves no phantom panel`, - { + await tronApp.cleanProjectDir({ + // Override the settings so that the theme is set to `system` + ...TEST_SETTINGS_DEFAULT_THEME, + }) + + const u = await getUtils(page) + + // Selectors and constants + const darkBackgroundCss = 'oklch(0.3012 0 264.5)' + const lightBackgroundCss = 'oklch(0.9911 0 264.5)' + const darkBackgroundColor: [number, number, number] = [27, 27, 27] + const lightBackgroundColor: [number, number, number] = [245, 245, 245] + const streamBackgroundPixelIsColor = async ( + color: [number, number, number] + ) => { + return u.getGreatestPixDiff({ x: 1000, y: 200 }, color) + } + const toolbar = page.locator('menu').filter({ hasText: 'Start Sketch' }) + + await test.step(`Test setup`, async () => { + await page.setBodyDimensions({ width: 1200, height: 500 }) + await homePage.goToModelingScene() + await u.waitForPageLoad() + await page.waitForTimeout(1000) + await expect(toolbar).toBeVisible() + }) + + await test.step(`Check the background color is light before`, async () => { + await expect(toolbar).toHaveCSS('background-color', lightBackgroundCss) + await expect + .poll(() => streamBackgroundPixelIsColor(lightBackgroundColor)) + .toBeLessThan(15) + }) + + await test.step(`Change media query preference to dark, emulating dusk with system theme`, async () => { + await page.emulateMedia({ colorScheme: 'dark' }) + }) + + await test.step(`Check the background color is dark after`, async () => { + await expect(toolbar).toHaveCSS('background-color', darkBackgroundCss) + await expect + .poll(() => streamBackgroundPixelIsColor(darkBackgroundColor)) + .toBeLessThan(15) + }) + }) + + test(`Turning off "Show debug panel" with debug panel open leaves no phantom panel`, async ({ + context, + page, + homePage, + tronApp, + }) => { + if (!tronApp) { + fail() + } + + await tronApp.cleanProjectDir({ // Override beforeEach test setup // with debug panel open // but "show debug panel" set to false - appSettings: { - ...TEST_SETTINGS, - app: { ...TEST_SETTINGS.app, show_debug_panel: false }, - modeling: { ...TEST_SETTINGS.modeling }, - }, - }, - async ({ context, page, homePage }) => { - const u = await getUtils(page) + ...TEST_SETTINGS, + app: { ...TEST_SETTINGS.app, show_debug_panel: false }, + modeling: { ...TEST_SETTINGS.modeling }, + }) - await context.addInitScript(async () => { - localStorage.setItem( - 'persistModelingContext', - '{"openPanes":["debug"]}' + const u = await getUtils(page) + + await context.addInitScript(async () => { + localStorage.setItem('persistModelingContext', '{"openPanes":["debug"]}') + }) + await page.setBodyDimensions({ width: 1200, height: 500 }) + await homePage.goToModelingScene() + + // Constants and locators + const resizeHandle = page.locator('.sidebar-resize-handles > div.block') + const debugPaneButton = page.getByTestId('debug-pane-button') + const commandsButton = page.getByRole('button', { name: 'Commands' }) + const debugPaneOption = page.getByRole('option', { + name: 'Settings · app · show debug panel', + }) + + async function setShowDebugPanelTo(value: 'On' | 'Off') { + await commandsButton.click() + await debugPaneOption.click() + await page.getByRole('option', { name: value }).click() + await expect( + page.getByText( + `Set show debug panel to "${value === 'On'}" for this project` ) - }) - await page.setBodyDimensions({ width: 1200, height: 500 }) - await homePage.goToModelingScene() - - // Constants and locators - const resizeHandle = page.locator('.sidebar-resize-handles > div.block') - const debugPaneButton = page.getByTestId('debug-pane-button') - const commandsButton = page.getByRole('button', { name: 'Commands' }) - const debugPaneOption = page.getByRole('option', { - name: 'Settings · app · show debug panel', - }) - - async function setShowDebugPanelTo(value: 'On' | 'Off') { - await commandsButton.click() - await debugPaneOption.click() - await page.getByRole('option', { name: value }).click() - await expect( - page.getByText( - `Set show debug panel to "${value === 'On'}" for this project` - ) - ).toBeVisible() - } - - await test.step(`Initial load with corrupted settings`, async () => { - // Check that the debug panel is not visible - await expect(debugPaneButton).not.toBeVisible() - // Check the pane resize handle wrapper is not visible - await expect(resizeHandle).not.toBeVisible() - }) - - await test.step(`Open code pane to verify we see the resize handles`, async () => { - await u.openKclCodePanel() - await expect(resizeHandle).toBeVisible() - await u.closeKclCodePanel() - }) - - await test.step(`Turn on debug panel, open it`, async () => { - await setShowDebugPanelTo('On') - await expect(debugPaneButton).toBeVisible() - // We want the logic to clear the phantom panel, so we shouldn't see - // the real panel (and therefore the resize handle) yet - await expect(resizeHandle).not.toBeVisible() - await u.openDebugPanel() - await expect(resizeHandle).toBeVisible() - }) - - await test.step(`Turn off debug panel setting with it open`, async () => { - await setShowDebugPanelTo('Off') - await expect(debugPaneButton).not.toBeVisible() - await expect(resizeHandle).not.toBeVisible() - }) + ).toBeVisible() } - ) + + await test.step(`Initial load with corrupted settings`, async () => { + // Check that the debug panel is not visible + await expect(debugPaneButton).not.toBeVisible() + // Check the pane resize handle wrapper is not visible + await expect(resizeHandle).not.toBeVisible() + }) + + await test.step(`Open code pane to verify we see the resize handles`, async () => { + await u.openKclCodePanel() + await expect(resizeHandle).toBeVisible() + await u.closeKclCodePanel() + }) + + await test.step(`Turn on debug panel, open it`, async () => { + await setShowDebugPanelTo('On') + await expect(debugPaneButton).toBeVisible() + // We want the logic to clear the phantom panel, so we shouldn't see + // the real panel (and therefore the resize handle) yet + await expect(resizeHandle).not.toBeVisible() + await u.openDebugPanel() + await expect(resizeHandle).toBeVisible() + }) + + await test.step(`Turn off debug panel setting with it open`, async () => { + await setShowDebugPanelTo('Off') + await expect(debugPaneButton).not.toBeVisible() + await expect(resizeHandle).not.toBeVisible() + }) + }) test(`Change inline units setting`, async ({ page, diff --git a/e2e/playwright/text-to-cad-tests.spec.ts b/e2e/playwright/text-to-cad-tests.spec.ts index 5e45a034c..0a97c766b 100644 --- a/e2e/playwright/text-to-cad-tests.spec.ts +++ b/e2e/playwright/text-to-cad-tests.spec.ts @@ -1,4 +1,5 @@ -import { test, expect, Page } from './zoo-test' +import { Page } from '@playwright/test' +import { test, expect } from './zoo-test' import { getUtils, createProject } from './test-utils' import { join } from 'path' import fs from 'fs' diff --git a/e2e/playwright/various.spec.ts b/e2e/playwright/various.spec.ts index 60365bd5d..512ba0c7a 100644 --- a/e2e/playwright/various.spec.ts +++ b/e2e/playwright/various.spec.ts @@ -35,7 +35,7 @@ test.fixme('Units menu', async ({ page, homePage }) => { test( 'Successful export shows a success toast', { tag: '@skipLocalEngine' }, - async ({ page, homePage }) => { + async ({ page, homePage, tronApp }) => { // FYI this test doesn't work with only engine running locally // And you will need to have the KittyCAD CLI installed const u = await getUtils(page) @@ -92,12 +92,17 @@ part001 = startSketchOn('-XZ') await page.waitForTimeout(1000) await u.clearAndCloseDebugPanel() + if (!tronApp?.projectDirName) { + fail() + } + await doExport( { type: 'gltf', storage: 'embedded', presentation: 'pretty', }, + tronApp?.projectDirName, page ) } @@ -465,7 +470,7 @@ test('Delete key does not navigate back', async ({ page, homePage }) => { await expect.poll(() => page.url()).not.toContain('/settings') }) -test('Sketch on face', async ({ page, homePage, scene, cmdBar }) => { +test('Sketch on face', async ({ page, homePage, scene, cmdBar, toolbar }) => { test.setTimeout(90_000) const u = await getUtils(page) await page.addInitScript(async () => { @@ -491,25 +496,22 @@ extrude001 = extrude(sketch001, length = 5 + 7)` await page.setBodyDimensions({ width: 1200, height: 500 }) await homePage.goToModelingScene() - await scene.waitForExecutionDone() - - await expect( - page.getByRole('button', { name: 'Start Sketch' }) - ).not.toBeDisabled() - - await page.getByRole('button', { name: 'Start Sketch' }).click() - await page.waitForTimeout(300) + await scene.connectionEstablished() + await scene.settled(cmdBar) let previousCodeContent = await page.locator('.cm-content').innerText() - await u.openAndClearDebugPanel() - await u.doAndWaitForCmd( - () => page.mouse.click(625, 165), - 'default_camera_get_settings', - true - ) - await page.waitForTimeout(150) - await u.closeDebugPanel() + await toolbar.startSketchThenCallbackThenWaitUntilReady(async () => { + await u.openAndClearDebugPanel() + await u.doAndWaitForCmd( + () => page.mouse.click(625, 165), + 'default_camera_get_settings', + true + ) + await page.waitForTimeout(150) + await u.closeDebugPanel() + }) + await page.waitForTimeout(300) const firstClickPosition = [612, 238] const secondClickPosition = [661, 242] diff --git a/e2e/playwright/zoo-test.ts b/e2e/playwright/zoo-test.ts index 317d79d0e..3e3c433da 100644 --- a/e2e/playwright/zoo-test.ts +++ b/e2e/playwright/zoo-test.ts @@ -1,21 +1,11 @@ -import { - test as playwrightTestFn, - TestInfo as TestInfoPlaywright, - BrowserContext as BrowserContextPlaywright, - Page as PagePlaywright, - TestDetails as TestDetailsPlaywright, - PlaywrightTestArgs, - PlaywrightTestOptions, - PlaywrightWorkerArgs, - PlaywrightWorkerOptions, - ElectronApplication, -} from '@playwright/test' +/* eslint-disable react-hooks/rules-of-hooks */ + +import { test as playwrightTestFn, ElectronApplication } from '@playwright/test' import { - fixtures, + fixturesBasedOnProcessEnvPlatform, Fixtures, - AuthenticatedTronApp, - AuthenticatedApp, + ElectronZoo, } from './fixtures/fixtureSetup' import { Settings } from '@rust/kcl-lib/bindings/Settings' @@ -23,9 +13,6 @@ import { DeepPartial } from 'lib/types' export { expect } from '@playwright/test' declare module '@playwright/test' { - interface TestInfo { - tronApp?: AuthenticatedTronApp - } interface BrowserContext { folderSetupFn: ( cb: (dir: string) => Promise @@ -41,288 +28,29 @@ declare module '@playwright/test' { } } -export type TestInfo = TestInfoPlaywright -export type BrowserContext = BrowserContextPlaywright -export type Page = PagePlaywright -export type TestDetails = TestDetailsPlaywright & { - cleanProjectDir?: boolean - appSettings?: DeepPartial -} +// Each worker spawns a new thread, which will spawn its own ElectronZoo. +// So in some sense there is an implicit pool. +// For example, the variable just beneath this text is reused many times +// *for one worker*. +const electronZooInstance = new ElectronZoo() // Our custom decorated Zoo test object. Makes it easier to add fixtures, and // switch between web and electron if needed. -const pwTestFnWithFixtures = playwrightTestFn.extend(fixtures) - -// In JavaScript you cannot replace a function's body only (despite functions -// are themselves objects, which you'd expect a body property or something...) -// So we must redefine the function and then re-attach properties. -type PWFunction = ( - args: PlaywrightTestArgs & - Fixtures & - PlaywrightWorkerArgs & - PlaywrightTestOptions & - PlaywrightWorkerOptions & { - electronApp?: ElectronApplication - }, - testInfo: TestInfo -) => void | Promise - -let firstUrl = '' - -export const test = ( - desc: string, - objOrFn: PWFunction | TestDetails, - fnMaybe?: PWFunction -) => { - const hasTestConf = typeof objOrFn === 'object' - const fn = hasTestConf ? fnMaybe : objOrFn - - return pwTestFnWithFixtures( - desc, - hasTestConf ? objOrFn : {}, - async ( - { - page, - context, - cmdBar, - editor, - toolbar, - scene, - homePage, - request, - playwright, - browser, - acceptDownloads, - bypassCSP, - colorScheme, - clientCertificates, - deviceScaleFactor, - extraHTTPHeaders, - geolocation, - hasTouch, - httpCredentials, - ignoreHTTPSErrors, - isMobile, - javaScriptEnabled, - locale, - offline, - permissions, - proxy, - storageState, - timezoneId, - userAgent, - viewport, - baseURL, - contextOptions, - actionTimeout, - navigationTimeout, - serviceWorkers, - testIdAttribute, - browserName, - defaultBrowserType, - headless, - channel, - launchOptions, - connectOptions, - screenshot, - trace, - video, - }, - testInfo - ) => { - // To switch to web, use PLATFORM=web environment variable. - // Only use this for debugging, since the playwright tracer is busted - // for electron. - - let tronApp - - if (process.env.PLATFORM === 'web') { - tronApp = new AuthenticatedApp(context, page, testInfo) - } else { - tronApp = new AuthenticatedTronApp(context, page, testInfo) - } - - const fixtures: Fixtures = { cmdBar, editor, toolbar, scene, homePage } - if (tronApp instanceof AuthenticatedTronApp) { - const options = { - fixtures, - } - if (hasTestConf) { - Object.assign(options, { - appSettings: objOrFn?.appSettings, - cleanProjectDir: objOrFn?.cleanProjectDir, - }) - } - await tronApp.initialise(options) - } else { - await tronApp.initialise('') - } - - // We need to patch this because addInitScript will bind too late in our - // electron tests, never running. We need to call reload() after each call - // to guarantee it runs. - const oldContextAddInitScript = tronApp.context.addInitScript - tronApp.context.addInitScript = async function (a, b) { - // @ts-ignore pretty sure way out of tsc's type checking capabilities. - // This code works perfectly fine. - await oldContextAddInitScript.apply(this, [a, b]) - await tronApp.page.reload() - } - - // No idea why we mix and match page and context's addInitScript but we do - const oldPageAddInitScript = tronApp.page.addInitScript - tronApp.page.addInitScript = async function (a: any, b: any) { - // @ts-ignore pretty sure way out of tsc's type checking capabilities. - // This code works perfectly fine. - await oldPageAddInitScript.apply(this, [a, b]) - await tronApp.page.reload() - } - - // Create a consistent way to resize the page across electron and web. - // (lee) I had to do everything in the book to make electron change its - // damn window size. I succeeded in making it consistently and reliably - // do it after a whole afternoon. - tronApp.page.setBodyDimensions = async function (dims: { - width: number - height: number - }) { - await tronApp.page.setViewportSize(dims) - - if (!(tronApp instanceof AuthenticatedTronApp)) { - return - } - - await tronApp.electronApp?.evaluateHandle(async ({ app }, dims) => { - // @ts-ignore sorry jon but see comment in main.ts why this is ignored - await app.resizeWindow(dims.width, dims.height) - }, dims) - - return tronApp.page.evaluate( - async (dims: { width: number; height: number }) => { - await window.electron.resizeWindow(dims.width, dims.height) - window.document.body.style.width = dims.width + 'px' - window.document.body.style.height = dims.height + 'px' - window.document.documentElement.style.width = dims.width + 'px' - window.document.documentElement.style.height = dims.height + 'px' - }, - dims - ) - } - - await tronApp.page.setBodyDimensions(tronApp.viewPortSize) - - // We need to expose this in order for some tests that require folder - // creation. Before they used to do this by their own electronSetup({...}) - // calls. - if (tronApp instanceof AuthenticatedTronApp) { - tronApp.context.folderSetupFn = async function (fn) { - return fn(tronApp.dir) - .then(() => tronApp.page.reload()) - .then(() => ({ - dir: tronApp.dir, - })) - } - } - - if (!firstUrl) { - await tronApp.page.getByText('Your Projects').count() - firstUrl = tronApp.page.url() - } - - // Due to the app controlling its own window context we need to inject new - // options and context here. - // NOTE TO LEE: Seems to destroy page context when calling an electron loadURL. - // await tronApp.electronApp.evaluate(({ app }) => { - // return app.reuseWindowForTest(); - // }); - - await tronApp.electronApp?.evaluate(({ app }, projectDirName) => { - // @ts-ignore can't declaration merge see main.ts - app.testProperty['TEST_SETTINGS_FILE_KEY'] = projectDirName - }, tronApp.dir) - - // Always start at the root view - await tronApp.page.goto(firstUrl) - - // Force a hard reload, destroying the stream and other state - await tronApp.page.reload() - - // tsc aint smart enough to know this'll never be undefined - // but I dont blame it, the logic to know is complex - if (fn) { - await fn( - { - context: tronApp.context, - page: tronApp.page, - electronApp: - tronApp instanceof AuthenticatedTronApp - ? tronApp.electronApp - : undefined, - ...fixtures, - request, - playwright, - browser, - acceptDownloads, - bypassCSP, - colorScheme, - clientCertificates, - deviceScaleFactor, - extraHTTPHeaders, - geolocation, - hasTouch, - httpCredentials, - ignoreHTTPSErrors, - isMobile, - javaScriptEnabled, - locale, - offline, - permissions, - proxy, - storageState, - timezoneId, - userAgent, - viewport, - baseURL, - contextOptions, - actionTimeout, - navigationTimeout, - serviceWorkers, - testIdAttribute, - browserName, - defaultBrowserType, - headless, - channel, - launchOptions, - connectOptions, - screenshot, - trace, - video, - }, - testInfo - ) - } - - testInfo.tronApp = - tronApp instanceof AuthenticatedTronApp ? tronApp : undefined +const playwrightTestFnWithFixtures_ = playwrightTestFn.extend<{ + tronApp?: ElectronZoo +}>({ + tronApp: async ({}, use, testInfo) => { + if (process.env.PLATFORM === 'web') { + await use(undefined) + return } - ) -} -type ZooTest = typeof test + await use(electronZooInstance) + }, +}) -test.describe = pwTestFnWithFixtures.describe -test.beforeEach = pwTestFnWithFixtures.beforeEach -test.afterEach = pwTestFnWithFixtures.afterEach -test.step = pwTestFnWithFixtures.step -test.skip = pwTestFnWithFixtures.skip -test.setTimeout = pwTestFnWithFixtures.setTimeout -test.fixme = pwTestFnWithFixtures.fixme as unknown as ZooTest -test.only = pwTestFnWithFixtures.only -test.fail = pwTestFnWithFixtures.fail -test.slow = pwTestFnWithFixtures.slow -test.beforeAll = pwTestFnWithFixtures.beforeAll -test.afterAll = pwTestFnWithFixtures.afterAll -test.use = pwTestFnWithFixtures.use -test.expect = pwTestFnWithFixtures.expect -test.extend = pwTestFnWithFixtures.extend -test.info = pwTestFnWithFixtures.info +const test = playwrightTestFnWithFixtures_.extend( + fixturesBasedOnProcessEnvPlatform +) + +export { test } diff --git a/package.json b/package.json index f71c89ebf..ec9b402b7 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "files:flip-to-nightly:windows": "./scripts/flip-files-to-nightly.ps1", "files:invalidate-bucket": "./scripts/invalidate-files-bucket.sh", "files:invalidate-bucket:nightly": "./scripts/invalidate-files-bucket.sh --nightly", - "postinstall": "./node_modules/.bin/electron-rebuild", + "postinstall": "yarn --cwd ./rust/kcl-language-server --modules-folder node_modules install && ./node_modules/.bin/electron-rebuild", "make:dev": "make dev", "generate:machine-api": "npx openapi-typescript ./openapi/machine-api.json -o src/lib/machine-api.d.ts", "generate:samples-manifest": "cd public/kcl-samples && node generate-manifest.js", diff --git a/rust/Cargo.lock b/rust/Cargo.lock index a16bfdf7e..ffc87080e 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1783,7 +1783,7 @@ dependencies = [ [[package]] name = "kcl-bumper" -version = "0.1.48" +version = "0.1.49" dependencies = [ "anyhow", "clap", @@ -1794,7 +1794,7 @@ dependencies = [ [[package]] name = "kcl-derive-docs" -version = "0.1.48" +version = "0.1.49" dependencies = [ "Inflector", "anyhow", @@ -1813,7 +1813,7 @@ dependencies = [ [[package]] name = "kcl-directory-test-macro" -version = "0.1.48" +version = "0.1.49" dependencies = [ "proc-macro2", "quote", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "kcl-language-server" -version = "0.2.48" +version = "0.2.49" dependencies = [ "anyhow", "clap", @@ -1843,7 +1843,7 @@ dependencies = [ [[package]] name = "kcl-language-server-release" -version = "0.1.48" +version = "0.1.49" dependencies = [ "anyhow", "clap", @@ -1863,7 +1863,7 @@ dependencies = [ [[package]] name = "kcl-lib" -version = "0.2.48" +version = "0.2.49" dependencies = [ "anyhow", "approx 0.5.1", @@ -1931,7 +1931,7 @@ dependencies = [ [[package]] name = "kcl-python-bindings" -version = "0.3.48" +version = "0.3.49" dependencies = [ "anyhow", "kcl-lib", @@ -1946,7 +1946,7 @@ dependencies = [ [[package]] name = "kcl-test-server" -version = "0.1.48" +version = "0.1.49" dependencies = [ "anyhow", "hyper 0.14.32", @@ -1959,7 +1959,7 @@ dependencies = [ [[package]] name = "kcl-to-core" -version = "0.1.48" +version = "0.1.49" dependencies = [ "anyhow", "async-trait", @@ -1973,7 +1973,7 @@ dependencies = [ [[package]] name = "kcl-wasm-lib" -version = "0.1.48" +version = "0.1.49" dependencies = [ "bson", "console_error_panic_hook", @@ -3097,15 +3097,14 @@ checksum = "e6cd655523701785087f69900df39892fb7b9b0721aa67682f571c38c32ac58a" [[package]] name = "ring" -version = "0.17.8" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" dependencies = [ "cc", "cfg-if", "getrandom 0.2.15", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -3560,12 +3559,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/rust/kcl-bumper/Cargo.toml b/rust/kcl-bumper/Cargo.toml index 3c1b42350..034a02e83 100644 --- a/rust/kcl-bumper/Cargo.toml +++ b/rust/kcl-bumper/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kcl-bumper" -version = "0.1.48" +version = "0.1.49" edition = "2021" repository = "https://github.com/KittyCAD/modeling-api" rust-version = "1.76" diff --git a/rust/kcl-derive-docs/Cargo.toml b/rust/kcl-derive-docs/Cargo.toml index b5e34f23c..bcb1f1727 100644 --- a/rust/kcl-derive-docs/Cargo.toml +++ b/rust/kcl-derive-docs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kcl-derive-docs" description = "A tool for generating documentation from Rust derive macros" -version = "0.1.48" +version = "0.1.49" edition = "2021" license = "MIT" repository = "https://github.com/KittyCAD/modeling-app" diff --git a/rust/kcl-directory-test-macro/Cargo.toml b/rust/kcl-directory-test-macro/Cargo.toml index 9ce3ca0c3..30cd0c682 100644 --- a/rust/kcl-directory-test-macro/Cargo.toml +++ b/rust/kcl-directory-test-macro/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kcl-directory-test-macro" description = "A tool for generating tests from a directory of kcl files" -version = "0.1.48" +version = "0.1.49" edition = "2021" license = "MIT" repository = "https://github.com/KittyCAD/modeling-app" diff --git a/rust/kcl-language-server-release/Cargo.toml b/rust/kcl-language-server-release/Cargo.toml index 5975bbb68..28bdbf3b5 100644 --- a/rust/kcl-language-server-release/Cargo.toml +++ b/rust/kcl-language-server-release/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kcl-language-server-release" -version = "0.1.48" +version = "0.1.49" edition = "2021" authors = ["KittyCAD Inc "] publish = false diff --git a/rust/kcl-language-server-release/src/build.rs b/rust/kcl-language-server-release/src/build.rs index 4e8fe3bfc..0e27d288d 100644 --- a/rust/kcl-language-server-release/src/build.rs +++ b/rust/kcl-language-server-release/src/build.rs @@ -72,7 +72,7 @@ impl Build { } fn build_client(sh: &Shell, version: &str, release_tag: &str, target: &Target) -> anyhow::Result<()> { - let bundle_path = Path::new("server"); + let bundle_path = Path::new("kcl-language-server/server"); sh.create_dir(bundle_path)?; sh.copy_file(&target.server_path, bundle_path)?; if let Some(symbols_path) = &target.symbols_path { diff --git a/rust/kcl-language-server/Cargo.toml b/rust/kcl-language-server/Cargo.toml index 8f0bd9bf5..e83b6001d 100644 --- a/rust/kcl-language-server/Cargo.toml +++ b/rust/kcl-language-server/Cargo.toml @@ -2,7 +2,7 @@ name = "kcl-language-server" description = "A language server for KCL." authors = ["KittyCAD Inc "] -version = "0.2.48" +version = "0.2.49" edition = "2021" license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/rust/kcl-language-server/client/src/bootstrap.ts b/rust/kcl-language-server/client/src/bootstrap.ts index 02472bbf6..77d5e0f04 100644 --- a/rust/kcl-language-server/client/src/bootstrap.ts +++ b/rust/kcl-language-server/client/src/bootstrap.ts @@ -97,7 +97,7 @@ async function getServer( 'You need to manually clone the kcl-lsp repository and ' + 'run `cargo install` to build the language server from sources. ' + 'If you feel that your platform should be supported, please create an issue ' + - 'about that [here](https://github.com/kittycad/kcl-lsp/issues) and we ' + + 'about that [here](https://github.com/kittycad/modeling-app/issues) and we ' + 'will consider it.' ) return undefined diff --git a/rust/kcl-lib/Cargo.toml b/rust/kcl-lib/Cargo.toml index ef846ffd4..cf1ace425 100644 --- a/rust/kcl-lib/Cargo.toml +++ b/rust/kcl-lib/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kcl-lib" description = "KittyCAD Language implementation and tools" -version = "0.2.48" +version = "0.2.49" edition = "2021" license = "MIT" repository = "https://github.com/KittyCAD/modeling-app" diff --git a/rust/kcl-lib/e2e/executor/inputs/fillet_duplicate_tags.kcl b/rust/kcl-lib/e2e/executor/inputs/fillet_duplicate_tags.kcl index d2ef7a41c..a33d3a5f1 100644 --- a/rust/kcl-lib/e2e/executor/inputs/fillet_duplicate_tags.kcl +++ b/rust/kcl-lib/e2e/executor/inputs/fillet_duplicate_tags.kcl @@ -1,8 +1,15 @@ -const part001 = startSketchOn('XY') - |> startProfileAt([0,0], %) - |> line(end = [0, 10], tag = $thing) - |> line(end = [10, 0]) - |> line(end = [0, -10], tag = $thing2) - |> close() - |> extrude(length = 10) - |> fillet(radius = 0.5, tags = [thing, thing]) +startProfileAt([0, 0], startSketchOn("XY")) + |> xLine(length = 10, tag = $line000) + |> yLine(length = 10, tag = $line001) + |> xLine(endAbsolute = profileStartX(%), tag = $line002) + |> close(tag = $line003) + |> extrude(length = 10) + |> fillet( + radius = 1, + tags = [ + line003, + getNextAdjacentEdge(line000), + getPreviousAdjacentEdge(line001) + ], + ) + diff --git a/rust/kcl-lib/e2e/executor/main.rs b/rust/kcl-lib/e2e/executor/main.rs index 9bbabc1e8..64aacaf10 100644 --- a/rust/kcl-lib/e2e/executor/main.rs +++ b/rust/kcl-lib/e2e/executor/main.rs @@ -27,11 +27,14 @@ async fn kcl_test_fillet_duplicate_tags() { let code = kcl_input!("fillet_duplicate_tags"); let result = execute_and_snapshot(code, UnitLength::Mm, None).await; - assert!(result.is_err()); + let err = result.expect_err("Code should have failed due to the duplicate edges being filletted"); + + let err = err.as_kcl_error().unwrap(); assert_eq!( - result.err().unwrap().to_string(), - r#"type: KclErrorDetails { source_ranges: [SourceRange([229, 272, 0])], message: "Duplicate tags are not allowed." }"#, + err.message(), + "The same edge ID is being referenced multiple times, which is not allowed. Please select a different edge" ); + assert_eq!(err.source_ranges().len(), 2); } #[tokio::test(flavor = "multi_thread")] @@ -857,7 +860,7 @@ part = rectShape([0, 0], 20, 20) }; assert_eq!( err.error.message(), - "This function expected this argument to be of type SketchOrSurface but it's actually of type string (text)" + "This function expected the input argument to be of type SketchOrSurface but it's actually of type string (text)" ); } @@ -2103,7 +2106,7 @@ async fn kcl_test_better_type_names() { }, None => todo!(), }; - assert_eq!(err, "This function expected this argument to be of type SolidSet but it's actually of type Sketch. You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`"); + assert_eq!(err, "This function expected the input argument to be of type SolidSet but it's actually of type Sketch. You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`"); } #[tokio::test(flavor = "multi_thread")] diff --git a/rust/kcl-lib/src/errors.rs b/rust/kcl-lib/src/errors.rs index 21abb253f..6d3f47b4f 100644 --- a/rust/kcl-lib/src/errors.rs +++ b/rust/kcl-lib/src/errors.rs @@ -48,6 +48,15 @@ impl ExecErrorWithState { } } +impl ExecError { + pub fn as_kcl_error(&self) -> Option<&crate::KclError> { + let ExecError::Kcl(k) = &self else { + return None; + }; + Some(&k.error) + } +} + impl From for ExecErrorWithState { fn from(error: ExecError) -> Self { Self { diff --git a/rust/kcl-lib/src/execution/exec_ast.rs b/rust/kcl-lib/src/execution/exec_ast.rs index ddee7f0d2..12a5acd84 100644 --- a/rust/kcl-lib/src/execution/exec_ast.rs +++ b/rust/kcl-lib/src/execution/exec_ast.rs @@ -596,12 +596,11 @@ impl ExecutorContext { self.exec_module_for_result(module_id, exec_state, ExecutionKind::Normal, metadata.source_range) .await? .unwrap_or_else(|| { - // The module didn't have a return value. Currently, - // the only way to have a return value is with the final - // statement being an expression statement. - // - // TODO: Make a warning when we support them in the - // execution phase. + exec_state.warn(CompilationError::err( + metadata.source_range, + "Imported module has no return value. The last statement of the module must be an expression, usually the Solid.", + )); + let mut new_meta = vec![metadata.to_owned()]; new_meta.extend(meta); KclValue::KclNone { @@ -1187,7 +1186,7 @@ impl Node { }, self.into(), ctx.clone(), - exec_state.mod_local.pipe_value.clone().map(Arg::synthetic), + exec_state.mod_local.pipe_value.clone().map(|v| Arg::new(v, callsite)), ); match ctx.stdlib.get_either(fn_name) { FunctionKind::Core(func) => { @@ -1349,7 +1348,7 @@ impl Node { fn_args, self.into(), ctx.clone(), - exec_state.mod_local.pipe_value.clone().map(Arg::synthetic), + exec_state.mod_local.pipe_value.clone().map(|v| Arg::new(v, callsite)), ); let mut return_value = { // Don't early-return in this block. @@ -2000,7 +1999,11 @@ impl FunctionSource { args, source_range, ctx.clone(), - exec_state.mod_local.pipe_value.clone().map(Arg::synthetic), + exec_state + .mod_local + .pipe_value + .clone() + .map(|v| Arg::new(v, source_range)), ); func(exec_state, args).await.map(Some) diff --git a/rust/kcl-lib/src/execution/kcl_value.rs b/rust/kcl-lib/src/execution/kcl_value.rs index 8426111b2..0a228cc9b 100644 --- a/rust/kcl-lib/src/execution/kcl_value.rs +++ b/rust/kcl-lib/src/execution/kcl_value.rs @@ -659,7 +659,11 @@ impl KclValue { args, source_range, ctx.clone(), - exec_state.mod_local.pipe_value.clone().map(Arg::synthetic), + exec_state + .mod_local + .pipe_value + .clone() + .map(|v| Arg::new(v, source_range)), ); let result = func(exec_state, args).await.map(Some); exec_state.mut_stack().pop_env(); diff --git a/rust/kcl-lib/src/parsing/parser.rs b/rust/kcl-lib/src/parsing/parser.rs index 9ee14d09b..42a23e925 100644 --- a/rust/kcl-lib/src/parsing/parser.rs +++ b/rust/kcl-lib/src/parsing/parser.rs @@ -844,11 +844,23 @@ fn object_property(i: &mut TokenSlice) -> PResult> { )) .parse_next(i)?; ignore_whitespace(i); - let expr = expression + let expr = match expression .context(expected( "the value which you're setting the property to, e.g. in 'height: 4', the value is 4", )) - .parse_next(i)?; + .parse_next(i) + { + Ok(expr) => expr, + Err(_) => { + return Err(ErrMode::Cut( + CompilationError::fatal( + SourceRange::from(sep), + "This property has a label, but no value. Put some value after the equals sign", + ) + .into(), + )); + } + }; let result = Node { start: key.start, @@ -2810,7 +2822,7 @@ fn fn_call_kw(i: &mut TokenSlice) -> PResult> { ignore_whitespace(i); #[allow(clippy::large_enum_variant)] - pub enum ArgPlace { + enum ArgPlace { NonCode(Node), LabeledArg(LabeledArg), UnlabeledArg(Expr), @@ -2827,22 +2839,34 @@ fn fn_call_kw(i: &mut TokenSlice) -> PResult> { .parse_next(i)?; let (args, non_code_nodes): (Vec<_>, BTreeMap) = args.into_iter().enumerate().try_fold( (Vec::new(), BTreeMap::new()), - |(mut args, mut non_code_nodes), (i, e)| { + |(mut args, mut non_code_nodes), (index, e)| { match e { ArgPlace::NonCode(x) => { - non_code_nodes.insert(i, vec![x]); + non_code_nodes.insert(index, vec![x]); } ArgPlace::LabeledArg(x) => { args.push(x); } ArgPlace::UnlabeledArg(arg) => { - return Err(ErrMode::Cut( - CompilationError::fatal( - SourceRange::from(arg), - "This argument needs a label, but it doesn't have one", + let followed_by_equals = peek((opt(whitespace), equals)).parse_next(i).is_ok(); + let err = if followed_by_equals { + ErrMode::Cut( + CompilationError::fatal( + SourceRange::from(arg), + "This argument has a label, but no value. Put some value after the equals sign", + ) + .into(), ) - .into(), - )); + } else { + ErrMode::Cut( + CompilationError::fatal( + SourceRange::from(arg), + "This argument needs a label, but it doesn't have one", + ) + .into(), + ) + }; + return Err(err); } } Ok((args, non_code_nodes)) @@ -4678,6 +4702,42 @@ baz = 2 ); } } + + #[test] + fn test_sensible_error_when_missing_rhs_of_kw_arg() { + for (i, program) in ["f(x, y=)"].into_iter().enumerate() { + let tokens = crate::parsing::token::lex(program, ModuleId::default()).unwrap(); + let err = fn_call_kw.parse(tokens.as_slice()).unwrap_err(); + let cause = err.inner().cause.as_ref().unwrap(); + assert_eq!( + cause.message, "This argument has a label, but no value. Put some value after the equals sign", + "failed test {i}: {program}" + ); + assert_eq!( + cause.source_range.start(), + program.find("y").unwrap(), + "failed test {i}: {program}" + ); + } + } + + #[test] + fn test_sensible_error_when_missing_rhs_of_obj_property() { + for (i, program) in ["{x = 1, y =}"].into_iter().enumerate() { + let tokens = crate::parsing::token::lex(program, ModuleId::default()).unwrap(); + let err = object.parse(tokens.as_slice()).unwrap_err(); + let cause = err.inner().cause.as_ref().unwrap(); + assert_eq!( + cause.message, "This property has a label, but no value. Put some value after the equals sign", + "failed test {i}: {program}" + ); + assert_eq!( + cause.source_range.start(), + program.rfind('=').unwrap(), + "failed test {i}: {program}" + ); + } + } } #[cfg(test)] diff --git a/rust/kcl-lib/src/std/args.rs b/rust/kcl-lib/src/std/args.rs index 3e068e6d8..4cbfbc97b 100644 --- a/rust/kcl-lib/src/std/args.rs +++ b/rust/kcl-lib/src/std/args.rs @@ -159,6 +159,49 @@ impl Args { }) } + /// Get a labelled keyword arg, check it's an array, and return all items in the array + /// plus their source range. + pub(crate) fn kw_arg_array_and_source<'a, T>(&'a self, label: &str) -> Result, KclError> + where + T: FromKclValue<'a>, + { + let Some(arg) = self.kw_args.labeled.get(label) else { + let err = KclError::Semantic(KclErrorDetails { + source_ranges: vec![self.source_range], + message: format!("This function requires a keyword argument '{label}'"), + }); + return Err(err); + }; + let Some(array) = arg.value.as_array() else { + let err = KclError::Semantic(KclErrorDetails { + source_ranges: vec![arg.source_range], + message: format!( + "Expected an array of {} but found {}", + type_name::(), + arg.value.human_friendly_type() + ), + }); + return Err(err); + }; + array + .iter() + .map(|item| { + let source = SourceRange::from(item); + let val = FromKclValue::from_kcl_val(item).ok_or_else(|| { + KclError::Semantic(KclErrorDetails { + source_ranges: arg.source_ranges(), + message: format!( + "Expected a {} but found {}", + type_name::(), + arg.value.human_friendly_type() + ), + }) + })?; + Ok((val, source)) + }) + .collect::, _>>() + } + /// Get the unlabeled keyword argument. If not set, returns None. pub(crate) fn unlabeled_kw_arg_unconverted(&self) -> Option<&Arg> { self.kw_args @@ -184,7 +227,7 @@ impl Args { T::from_kcl_val(&arg.value).ok_or_else(|| { let expected_type_name = tynm::type_name::(); let actual_type_name = arg.value.human_friendly_type(); - let msg_base = format!("This function expected this argument to be of type {expected_type_name} but it's actually of type {actual_type_name}"); + let msg_base = format!("This function expected the input argument to be of type {expected_type_name} but it's actually of type {actual_type_name}"); let suggestion = match (expected_type_name.as_str(), actual_type_name) { ("SolidSet", "Sketch") => Some( "You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`", diff --git a/rust/kcl-lib/src/std/chamfer.rs b/rust/kcl-lib/src/std/chamfer.rs index 7ca498695..86a3b0293 100644 --- a/rust/kcl-lib/src/std/chamfer.rs +++ b/rust/kcl-lib/src/std/chamfer.rs @@ -5,7 +5,6 @@ use kcl_derive_docs::stdlib; use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::CutType, ModelingCmd}; use kittycad_modeling_cmds as kcmc; -use super::utils::unique_count; use crate::{ errors::{KclError, KclErrorDetails}, execution::{ChamferSurface, EdgeCut, ExecState, ExtrudeSurface, GeoMeta, KclValue, Solid}, @@ -19,9 +18,11 @@ pub(crate) const DEFAULT_TOLERANCE: f64 = 0.0000001; pub async fn chamfer(exec_state: &mut ExecState, args: Args) -> Result { let solid = args.get_unlabeled_kw_arg("solid")?; let length = args.get_kw_arg("length")?; - let tags = args.get_kw_arg("tags")?; + let tags = args.kw_arg_array_and_source::("tags")?; let tag = args.get_kw_arg_opt("tag")?; + super::fillet::validate_unique(&tags)?; + let tags: Vec = tags.into_iter().map(|item| item.0).collect(); let value = inner_chamfer(solid, length, tags, tag, exec_state, args).await?; Ok(KclValue::Solid { value }) } @@ -109,15 +110,6 @@ async fn inner_chamfer( exec_state: &mut ExecState, args: Args, ) -> Result, KclError> { - // Check if tags contains any duplicate values. - let unique_tags = unique_count(tags.clone()); - if unique_tags != tags.len() { - return Err(KclError::Type(KclErrorDetails { - message: "Duplicate tags are not allowed.".to_string(), - source_ranges: vec![args.source_range], - })); - } - // If you try and tag multiple edges with a tagged chamfer, we want to return an // error to the user that they can only tag one edge at a time. if tag.is_some() && tags.len() > 1 { diff --git a/rust/kcl-lib/src/std/fillet.rs b/rust/kcl-lib/src/std/fillet.rs index 9b7474db2..08369c725 100644 --- a/rust/kcl-lib/src/std/fillet.rs +++ b/rust/kcl-lib/src/std/fillet.rs @@ -1,6 +1,7 @@ //! Standard library fillets. use anyhow::Result; +use indexmap::IndexMap; use kcl_derive_docs::stdlib; use kcmc::{ each_cmd as mcmd, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, shared::CutType, @@ -11,13 +12,13 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use super::utils::unique_count; use crate::{ errors::{KclError, KclErrorDetails}, execution::{EdgeCut, ExecState, ExtrudeSurface, FilletSurface, GeoMeta, KclValue, Solid, TagIdentifier}, parsing::ast::types::TagNode, settings::types::UnitLength, std::Args, + SourceRange, }; /// A tag or a uuid of an edge. @@ -40,13 +41,39 @@ impl EdgeReference { } } +pub(super) fn validate_unique(tags: &[(T, SourceRange)]) -> Result<(), KclError> { + // Check if tags contains any duplicate values. + let mut tag_counts: IndexMap<&T, Vec> = Default::default(); + for tag in tags { + tag_counts.entry(&tag.0).or_insert(Vec::new()).push(tag.1); + } + let mut duplicate_tags_source = Vec::new(); + for (_tag, count) in tag_counts { + if count.len() > 1 { + duplicate_tags_source.extend(count) + } + } + if !duplicate_tags_source.is_empty() { + return Err(KclError::Type(KclErrorDetails { + message: "The same edge ID is being referenced multiple times, which is not allowed. Please select a different edge".to_string(), + source_ranges: duplicate_tags_source, + })); + } + Ok(()) +} + /// Create fillets on tagged paths. pub async fn fillet(exec_state: &mut ExecState, args: Args) -> Result { + // Get all args: let solid = args.get_unlabeled_kw_arg("solid")?; let radius = args.get_kw_arg("radius")?; let tolerance = args.get_kw_arg_opt("tolerance")?; - let tags = args.get_kw_arg("tags")?; + let tags = args.kw_arg_array_and_source::("tags")?; let tag = args.get_kw_arg_opt("tag")?; + + // Run the function. + validate_unique(&tags)?; + let tags: Vec = tags.into_iter().map(|item| item.0).collect(); let value = inner_fillet(solid, radius, tags, tolerance, tag, exec_state, args).await?; Ok(KclValue::Solid { value }) } @@ -129,15 +156,6 @@ async fn inner_fillet( exec_state: &mut ExecState, args: Args, ) -> Result, KclError> { - // Check if tags contains any duplicate values. - let unique_tags = unique_count(tags.clone()); - if unique_tags != tags.len() { - return Err(KclError::Type(KclErrorDetails { - message: "Duplicate tags are not allowed.".to_string(), - source_ranges: vec![args.source_range], - })); - } - let mut solid = solid.clone(); for edge_tag in tags { let edge_id = edge_tag.get_engine_id(exec_state, &args)?; @@ -432,3 +450,22 @@ pub(crate) fn default_tolerance(units: &UnitLength) -> f64 { UnitLength::M => 0.001, } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_validate_unique() { + let dup_a = SourceRange::from([1, 3, 0]); + let dup_b = SourceRange::from([10, 30, 0]); + // Two entries are duplicates (abc) with different source ranges. + let tags = vec![("abc", dup_a), ("abc", dup_b), ("def", SourceRange::from([2, 4, 0]))]; + let actual = validate_unique(&tags); + // Both the duplicates should show up as errors, with both of the + // source ranges they correspond to. + // But the unique source range 'def' should not. + let expected = vec![dup_a, dup_b]; + assert_eq!(actual.err().unwrap().source_ranges(), expected); + } +} diff --git a/rust/kcl-lib/src/std/utils.rs b/rust/kcl-lib/src/std/utils.rs index f0e3f8643..4d7aefd79 100644 --- a/rust/kcl-lib/src/std/utils.rs +++ b/rust/kcl-lib/src/std/utils.rs @@ -1,4 +1,4 @@ -use std::{collections::HashSet, f64::consts::PI}; +use std::f64::consts::PI; use kittycad_modeling_cmds::shared::Angle; @@ -8,16 +8,6 @@ use crate::{ source_range::SourceRange, }; -/// Count the number of unique items in a `Vec` in O(n) time. -pub(crate) fn unique_count(vec: Vec) -> usize { - // Add to a set. - let mut set = HashSet::with_capacity(vec.len()); - for item in vec { - set.insert(item); - } - set.len() -} - /// Get the distance between two points. pub fn distance(a: Point2d, b: Point2d) -> f64 { ((b.x - a.x).powi(2) + (b.y - a.y).powi(2)).sqrt() @@ -686,11 +676,6 @@ mod get_tangential_arc_to_info_tests { (num * 1000.0).round() / 1000.0 } - #[test] - fn test_unique_count() { - assert_eq!(unique_count(vec![1, 2, 2, 3, 2]), 3); - } - #[test] fn test_basic_case() { let result = get_tangential_arc_to_info(TangentialArcInfoInput { diff --git a/rust/kcl-lib/tests/angled_line/ops.snap b/rust/kcl-lib/tests/angled_line/ops.snap index 0f28c2d8b..2139b6710 100644 --- a/rust/kcl-lib/tests/angled_line/ops.snap +++ b/rust/kcl-lib/tests/angled_line/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed angled_line.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed angled_line.kcl } }, "sourceRange": [ - 0, - 0, + 270, + 289, 0 ] } diff --git a/rust/kcl-lib/tests/artifact_graph_example_code1/ops.snap b/rust/kcl-lib/tests/artifact_graph_example_code1/ops.snap index f6e2d53b3..cd26da8cc 100644 --- a/rust/kcl-lib/tests/artifact_graph_example_code1/ops.snap +++ b/rust/kcl-lib/tests/artifact_graph_example_code1/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed artifact_graph_example_code1.kcl --- [ @@ -125,8 +125,8 @@ description: Operations executed artifact_graph_example_code1.kcl } }, "sourceRange": [ - 0, - 0, + 298, + 332, 0 ] } diff --git a/rust/kcl-lib/tests/basic_fillet_cube_close_opposite/ops.snap b/rust/kcl-lib/tests/basic_fillet_cube_close_opposite/ops.snap index c2b459d90..5f2042e86 100644 --- a/rust/kcl-lib/tests/basic_fillet_cube_close_opposite/ops.snap +++ b/rust/kcl-lib/tests/basic_fillet_cube_close_opposite/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed basic_fillet_cube_close_opposite.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed basic_fillet_cube_close_opposite.kcl } }, "sourceRange": [ - 0, - 0, + 197, + 217, 0 ] } @@ -129,8 +129,8 @@ description: Operations executed basic_fillet_cube_close_opposite.kcl } }, "sourceRange": [ - 0, - 0, + 223, + 283, 0 ] } diff --git a/rust/kcl-lib/tests/basic_fillet_cube_end/ops.snap b/rust/kcl-lib/tests/basic_fillet_cube_end/ops.snap index 5ce17c481..600a3b92d 100644 --- a/rust/kcl-lib/tests/basic_fillet_cube_end/ops.snap +++ b/rust/kcl-lib/tests/basic_fillet_cube_end/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed basic_fillet_cube_end.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed basic_fillet_cube_end.kcl } }, "sourceRange": [ - 0, - 0, + 185, + 205, 0 ] } @@ -129,8 +129,8 @@ description: Operations executed basic_fillet_cube_end.kcl } }, "sourceRange": [ - 0, - 0, + 211, + 269, 0 ] } diff --git a/rust/kcl-lib/tests/basic_fillet_cube_next_adjacent/ops.snap b/rust/kcl-lib/tests/basic_fillet_cube_next_adjacent/ops.snap index 53208dd67..8e8ea0c61 100644 --- a/rust/kcl-lib/tests/basic_fillet_cube_next_adjacent/ops.snap +++ b/rust/kcl-lib/tests/basic_fillet_cube_next_adjacent/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed basic_fillet_cube_next_adjacent.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed basic_fillet_cube_next_adjacent.kcl } }, "sourceRange": [ - 0, - 0, + 212, + 232, 0 ] } @@ -124,8 +124,8 @@ description: Operations executed basic_fillet_cube_next_adjacent.kcl } }, "sourceRange": [ - 0, - 0, + 238, + 294, 0 ] } diff --git a/rust/kcl-lib/tests/basic_fillet_cube_previous_adjacent/ops.snap b/rust/kcl-lib/tests/basic_fillet_cube_previous_adjacent/ops.snap index 235cf948a..c17b2272f 100644 --- a/rust/kcl-lib/tests/basic_fillet_cube_previous_adjacent/ops.snap +++ b/rust/kcl-lib/tests/basic_fillet_cube_previous_adjacent/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed basic_fillet_cube_previous_adjacent.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed basic_fillet_cube_previous_adjacent.kcl } }, "sourceRange": [ - 0, - 0, + 212, + 232, 0 ] } @@ -124,8 +124,8 @@ description: Operations executed basic_fillet_cube_previous_adjacent.kcl } }, "sourceRange": [ - 0, - 0, + 238, + 298, 0 ] } diff --git a/rust/kcl-lib/tests/basic_fillet_cube_start/ops.snap b/rust/kcl-lib/tests/basic_fillet_cube_start/ops.snap index 145e16138..5b29c2d2b 100644 --- a/rust/kcl-lib/tests/basic_fillet_cube_start/ops.snap +++ b/rust/kcl-lib/tests/basic_fillet_cube_start/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed basic_fillet_cube_start.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed basic_fillet_cube_start.kcl } }, "sourceRange": [ - 0, - 0, + 185, + 205, 0 ] } @@ -130,8 +130,8 @@ description: Operations executed basic_fillet_cube_start.kcl } }, "sourceRange": [ - 0, - 0, + 211, + 253, 0 ] } diff --git a/rust/kcl-lib/tests/big_number_angle_to_match_length_x/ops.snap b/rust/kcl-lib/tests/big_number_angle_to_match_length_x/ops.snap index c575ad8d4..3fc52ee33 100644 --- a/rust/kcl-lib/tests/big_number_angle_to_match_length_x/ops.snap +++ b/rust/kcl-lib/tests/big_number_angle_to_match_length_x/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed big_number_angle_to_match_length_x.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed big_number_angle_to_match_length_x.kcl } }, "sourceRange": [ - 0, - 0, + 183, + 203, 0 ] } diff --git a/rust/kcl-lib/tests/big_number_angle_to_match_length_y/ops.snap b/rust/kcl-lib/tests/big_number_angle_to_match_length_y/ops.snap index 5a490e8fc..58ced2937 100644 --- a/rust/kcl-lib/tests/big_number_angle_to_match_length_y/ops.snap +++ b/rust/kcl-lib/tests/big_number_angle_to_match_length_y/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed big_number_angle_to_match_length_y.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed big_number_angle_to_match_length_y.kcl } }, "sourceRange": [ - 0, - 0, + 183, + 203, 0 ] } diff --git a/rust/kcl-lib/tests/circle_three_point/ops.snap b/rust/kcl-lib/tests/circle_three_point/ops.snap index 7be2e0867..4f230720b 100644 --- a/rust/kcl-lib/tests/circle_three_point/ops.snap +++ b/rust/kcl-lib/tests/circle_three_point/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed circle_three_point.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed circle_three_point.kcl } }, "sourceRange": [ - 0, - 0, + 104, + 124, 0 ] } diff --git a/rust/kcl-lib/tests/circular_pattern3d_a_pattern/ops.snap b/rust/kcl-lib/tests/circular_pattern3d_a_pattern/ops.snap index 92102854a..f89438104 100644 --- a/rust/kcl-lib/tests/circular_pattern3d_a_pattern/ops.snap +++ b/rust/kcl-lib/tests/circular_pattern3d_a_pattern/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed circular_pattern3d_a_pattern.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed circular_pattern3d_a_pattern.kcl } }, "sourceRange": [ - 0, - 0, + 159, + 178, 0 ] } diff --git a/rust/kcl-lib/tests/cube/ops.snap b/rust/kcl-lib/tests/cube/ops.snap index a89203d18..58b9d89b0 100644 --- a/rust/kcl-lib/tests/cube/ops.snap +++ b/rust/kcl-lib/tests/cube/ops.snap @@ -139,8 +139,8 @@ description: Operations executed cube.kcl } }, "sourceRange": [ - 0, - 0, + 374, + 402, 0 ] } diff --git a/rust/kcl-lib/tests/cube_with_error/ops.snap b/rust/kcl-lib/tests/cube_with_error/ops.snap index 7f618d0d8..f2f4f2e73 100644 --- a/rust/kcl-lib/tests/cube_with_error/ops.snap +++ b/rust/kcl-lib/tests/cube_with_error/ops.snap @@ -80,8 +80,8 @@ description: Operations executed cube_with_error.kcl } }, "sourceRange": [ - 0, - 0, + 366, + 390, 0 ] } diff --git a/rust/kcl-lib/tests/fillet-and-shell/ops.snap b/rust/kcl-lib/tests/fillet-and-shell/ops.snap index 0d1c86370..c03728f44 100644 --- a/rust/kcl-lib/tests/fillet-and-shell/ops.snap +++ b/rust/kcl-lib/tests/fillet-and-shell/ops.snap @@ -87,8 +87,8 @@ description: Operations executed fillet-and-shell.kcl } }, "sourceRange": [ - 0, - 0, + 1057, + 1085, 0 ] } @@ -159,8 +159,8 @@ description: Operations executed fillet-and-shell.kcl } }, "sourceRange": [ - 0, - 0, + 1091, + 1297, 0 ] } @@ -280,8 +280,8 @@ description: Operations executed fillet-and-shell.kcl } }, "sourceRange": [ - 0, - 0, + 1497, + 1521, 0 ] } @@ -404,8 +404,8 @@ description: Operations executed fillet-and-shell.kcl } }, "sourceRange": [ - 0, - 0, + 1497, + 1521, 0 ] } @@ -528,8 +528,8 @@ description: Operations executed fillet-and-shell.kcl } }, "sourceRange": [ - 0, - 0, + 1497, + 1521, 0 ] } @@ -652,8 +652,8 @@ description: Operations executed fillet-and-shell.kcl } }, "sourceRange": [ - 0, - 0, + 1497, + 1521, 0 ] } diff --git a/rust/kcl-lib/tests/function_sketch/ops.snap b/rust/kcl-lib/tests/function_sketch/ops.snap index e5b054d04..927420743 100644 --- a/rust/kcl-lib/tests/function_sketch/ops.snap +++ b/rust/kcl-lib/tests/function_sketch/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed function_sketch.kcl --- [ @@ -80,8 +80,8 @@ description: Operations executed function_sketch.kcl } }, "sourceRange": [ - 0, - 0, + 183, + 202, 0 ] } diff --git a/rust/kcl-lib/tests/function_sketch_with_position/ops.snap b/rust/kcl-lib/tests/function_sketch_with_position/ops.snap index 5ce897598..a9f644843 100644 --- a/rust/kcl-lib/tests/function_sketch_with_position/ops.snap +++ b/rust/kcl-lib/tests/function_sketch_with_position/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed function_sketch_with_position.kcl --- [ @@ -80,8 +80,8 @@ description: Operations executed function_sketch_with_position.kcl } }, "sourceRange": [ - 0, - 0, + 181, + 200, 0 ] } diff --git a/rust/kcl-lib/tests/helix_ccw/ops.snap b/rust/kcl-lib/tests/helix_ccw/ops.snap index 9d1885031..c6193af09 100644 --- a/rust/kcl-lib/tests/helix_ccw/ops.snap +++ b/rust/kcl-lib/tests/helix_ccw/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed helix_ccw.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed helix_ccw.kcl } }, "sourceRange": [ - 0, - 0, + 77, + 97, 0 ] } diff --git a/rust/kcl-lib/tests/i_shape/ops.snap b/rust/kcl-lib/tests/i_shape/ops.snap index 11d1f3104..b81558b10 100644 --- a/rust/kcl-lib/tests/i_shape/ops.snap +++ b/rust/kcl-lib/tests/i_shape/ops.snap @@ -125,8 +125,8 @@ description: Operations executed i_shape.kcl } }, "sourceRange": [ - 0, - 0, + 2510, + 2531, 0 ] } diff --git a/rust/kcl-lib/tests/import_whole/ops.snap b/rust/kcl-lib/tests/import_whole/ops.snap index 9488a96d2..4ebaae2f2 100644 --- a/rust/kcl-lib/tests/import_whole/ops.snap +++ b/rust/kcl-lib/tests/import_whole/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed import_whole.kcl --- [ @@ -64,9 +64,9 @@ description: Operations executed import_whole.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 103, + 123, + 3 ] } }, @@ -124,8 +124,8 @@ description: Operations executed import_whole.kcl } }, "sourceRange": [ - 0, - 0, + 83, + 123, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/3d-boaty/ops.snap b/rust/kcl-lib/tests/kcl_samples/3d-boaty/ops.snap index c54eda201..e482b52b4 100644 --- a/rust/kcl-lib/tests/kcl_samples/3d-boaty/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/3d-boaty/ops.snap @@ -93,9 +93,9 @@ description: Operations executed 3d-boaty.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1379, + 1417, + 3 ] } }, @@ -173,9 +173,9 @@ description: Operations executed 3d-boaty.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1455, + 1494, + 3 ] } }, @@ -428,9 +428,9 @@ description: Operations executed 3d-boaty.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1379, + 1417, + 3 ] } }, @@ -508,9 +508,9 @@ description: Operations executed 3d-boaty.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1455, + 1494, + 3 ] } }, @@ -763,9 +763,9 @@ description: Operations executed 3d-boaty.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1379, + 1417, + 3 ] } }, @@ -843,9 +843,9 @@ description: Operations executed 3d-boaty.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1455, + 1494, + 3 ] } }, @@ -1104,9 +1104,9 @@ description: Operations executed 3d-boaty.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1949, + 1973, + 3 ] } }, @@ -1190,9 +1190,9 @@ description: Operations executed 3d-boaty.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 2015, + 2039, + 3 ] } }, @@ -1339,9 +1339,9 @@ description: Operations executed 3d-boaty.kcl ] }, "sourceRange": [ - 0, - 0, - 0 + 2523, + 2547, + 3 ] } }, @@ -1485,9 +1485,9 @@ description: Operations executed 3d-boaty.kcl ] }, "sourceRange": [ - 0, - 0, - 0 + 3047, + 3071, + 3 ] } }, diff --git a/rust/kcl-lib/tests/kcl_samples/80-20-rail/ops.snap b/rust/kcl-lib/tests/kcl_samples/80-20-rail/ops.snap index e8f850d08..48c11372a 100644 --- a/rust/kcl-lib/tests/kcl_samples/80-20-rail/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/80-20-rail/ops.snap @@ -118,8 +118,8 @@ description: Operations executed 80-20-rail.kcl } }, "sourceRange": [ - 0, - 0, + 6006, + 6034, 0 ] } @@ -238,8 +238,8 @@ description: Operations executed 80-20-rail.kcl } }, "sourceRange": [ - 0, - 0, + 6042, + 6746, 0 ] } @@ -358,8 +358,8 @@ description: Operations executed 80-20-rail.kcl } }, "sourceRange": [ - 0, - 0, + 6754, + 7457, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/a-parametric-bearing-pillow-block/ops.snap b/rust/kcl-lib/tests/kcl_samples/a-parametric-bearing-pillow-block/ops.snap index ea023299f..a3f6ffba7 100644 --- a/rust/kcl-lib/tests/kcl_samples/a-parametric-bearing-pillow-block/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/a-parametric-bearing-pillow-block/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed a-parametric-bearing-pillow-block.kcl --- [ @@ -254,8 +254,8 @@ description: Operations executed a-parametric-bearing-pillow-block.kcl } }, "sourceRange": [ - 0, - 0, + 1902, + 1936, 0 ] } @@ -693,8 +693,8 @@ description: Operations executed a-parametric-bearing-pillow-block.kcl } }, "sourceRange": [ - 0, - 0, + 3383, + 3408, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/ball-bearing/ops.snap b/rust/kcl-lib/tests/kcl_samples/ball-bearing/ops.snap index 3c7588e66..7454cd57e 100644 --- a/rust/kcl-lib/tests/kcl_samples/ball-bearing/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/ball-bearing/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed ball-bearing.kcl --- [ @@ -519,8 +519,8 @@ description: Operations executed ball-bearing.kcl } }, "sourceRange": [ - 0, - 0, + 1561, + 1721, 0 ] } @@ -779,8 +779,8 @@ description: Operations executed ball-bearing.kcl } }, "sourceRange": [ - 0, - 0, + 2214, + 2374, 0 ] } @@ -1027,8 +1027,8 @@ description: Operations executed ball-bearing.kcl } }, "sourceRange": [ - 0, - 0, + 2718, + 2878, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/bracket/ops.snap b/rust/kcl-lib/tests/kcl_samples/bracket/ops.snap index c1ce4b6f7..ba5170c9d 100644 --- a/rust/kcl-lib/tests/kcl_samples/bracket/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/bracket/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed bracket.kcl --- [ @@ -274,8 +274,8 @@ description: Operations executed bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1903, + 2052, 0 ] } @@ -724,8 +724,8 @@ description: Operations executed bracket.kcl } }, "sourceRange": [ - 0, - 0, + 3306, + 3455, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/car-wheel-assembly/ops.snap b/rust/kcl-lib/tests/kcl_samples/car-wheel-assembly/ops.snap index 2203afcdd..38643274f 100644 --- a/rust/kcl-lib/tests/kcl_samples/car-wheel-assembly/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/car-wheel-assembly/ops.snap @@ -1510,9 +1510,9 @@ description: Operations executed car-wheel-assembly.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 529, + 562, + 3 ] } }, @@ -1622,9 +1622,9 @@ description: Operations executed car-wheel-assembly.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 859, + 892, + 3 ] } }, @@ -1710,9 +1710,9 @@ description: Operations executed car-wheel-assembly.kcl ] }, "sourceRange": [ - 0, - 0, - 0 + 1214, + 1248, + 3 ] } }, @@ -1798,9 +1798,9 @@ description: Operations executed car-wheel-assembly.kcl ] }, "sourceRange": [ - 0, - 0, - 0 + 1572, + 1606, + 3 ] } }, @@ -2362,9 +2362,9 @@ description: Operations executed car-wheel-assembly.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 4067, + 4247, + 3 ] } }, @@ -2801,9 +2801,9 @@ description: Operations executed car-wheel-assembly.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 4067, + 4247, + 3 ] } }, @@ -3298,8 +3298,8 @@ description: Operations executed car-wheel-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 373, + 524, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/enclosure/ops.snap b/rust/kcl-lib/tests/kcl_samples/enclosure/ops.snap index 775397ca8..523db20fb 100644 --- a/rust/kcl-lib/tests/kcl_samples/enclosure/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/enclosure/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed enclosure.kcl --- [ @@ -130,8 +130,8 @@ description: Operations executed enclosure.kcl } }, "sourceRange": [ - 0, - 0, + 740, + 1021, 0 ] } @@ -190,8 +190,8 @@ description: Operations executed enclosure.kcl } }, "sourceRange": [ - 0, - 0, + 1100, + 1170, 0 ] } @@ -1699,8 +1699,8 @@ description: Operations executed enclosure.kcl } }, "sourceRange": [ - 0, - 0, + 3601, + 3882, 0 ] } @@ -1997,8 +1997,8 @@ description: Operations executed enclosure.kcl } }, "sourceRange": [ - 0, - 0, + 5327, + 5608, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/exhaust-manifold/ops.snap b/rust/kcl-lib/tests/kcl_samples/exhaust-manifold/ops.snap index 574916aa6..1e4b59a06 100644 --- a/rust/kcl-lib/tests/kcl_samples/exhaust-manifold/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/exhaust-manifold/ops.snap @@ -338,8 +338,8 @@ description: Operations executed exhaust-manifold.kcl } }, "sourceRange": [ - 0, - 0, + 1547, + 1570, 0 ] } @@ -682,8 +682,8 @@ description: Operations executed exhaust-manifold.kcl } }, "sourceRange": [ - 0, - 0, + 1547, + 1570, 0 ] } @@ -1026,8 +1026,8 @@ description: Operations executed exhaust-manifold.kcl } }, "sourceRange": [ - 0, - 0, + 1547, + 1570, 0 ] } @@ -1370,8 +1370,8 @@ description: Operations executed exhaust-manifold.kcl } }, "sourceRange": [ - 0, - 0, + 1547, + 1570, 0 ] } @@ -1744,8 +1744,8 @@ description: Operations executed exhaust-manifold.kcl } }, "sourceRange": [ - 0, - 0, + 3933, + 3962, 0 ] } @@ -1808,8 +1808,8 @@ description: Operations executed exhaust-manifold.kcl } }, "sourceRange": [ - 0, - 0, + 3968, + 4101, 0 ] } @@ -1872,8 +1872,8 @@ description: Operations executed exhaust-manifold.kcl } }, "sourceRange": [ - 0, - 0, + 4107, + 4240, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/flange-with-patterns/ops.snap b/rust/kcl-lib/tests/kcl_samples/flange-with-patterns/ops.snap index 202a7bef2..bdf1b1385 100644 --- a/rust/kcl-lib/tests/kcl_samples/flange-with-patterns/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/flange-with-patterns/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed flange-with-patterns.kcl --- [ @@ -174,8 +174,8 @@ description: Operations executed flange-with-patterns.kcl } }, "sourceRange": [ - 0, - 0, + 1413, + 1444, 0 ] } @@ -461,8 +461,8 @@ description: Operations executed flange-with-patterns.kcl } }, "sourceRange": [ - 0, - 0, + 1928, + 1963, 0 ] } @@ -566,8 +566,8 @@ description: Operations executed flange-with-patterns.kcl } }, "sourceRange": [ - 0, - 0, + 2230, + 2264, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/flange-xy/ops.snap b/rust/kcl-lib/tests/kcl_samples/flange-xy/ops.snap index 7c84b3bc4..2ec583df9 100644 --- a/rust/kcl-lib/tests/kcl_samples/flange-xy/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/flange-xy/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed flange-xy.kcl --- [ @@ -254,8 +254,8 @@ description: Operations executed flange-xy.kcl } }, "sourceRange": [ - 0, - 0, + 1555, + 1586, 0 ] } @@ -552,8 +552,8 @@ description: Operations executed flange-xy.kcl } }, "sourceRange": [ - 0, - 0, + 2077, + 2112, 0 ] } @@ -657,8 +657,8 @@ description: Operations executed flange-xy.kcl } }, "sourceRange": [ - 0, - 0, + 2379, + 2413, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/focusrite-scarlett-mounting-bracket/ops.snap b/rust/kcl-lib/tests/kcl_samples/focusrite-scarlett-mounting-bracket/ops.snap index 6c6945376..80304d94d 100644 --- a/rust/kcl-lib/tests/kcl_samples/focusrite-scarlett-mounting-bracket/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/focusrite-scarlett-mounting-bracket/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed focusrite-scarlett-mounting-bracket.kcl --- [ @@ -253,8 +253,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1831, + 1865, 0 ] } @@ -325,8 +325,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1871, + 2129, 0 ] } @@ -612,8 +612,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 2875, + 2900, 0 ] } @@ -670,8 +670,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 2906, + 3050, 0 ] } @@ -779,8 +779,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 3056, + 3184, 0 ] } @@ -1066,8 +1066,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 3719, + 3744, 0 ] } @@ -1124,8 +1124,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 3750, + 3894, 0 ] } @@ -1233,8 +1233,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 3900, + 4028, 0 ] } @@ -1476,8 +1476,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 4458, + 4486, 0 ] } @@ -1719,8 +1719,8 @@ description: Operations executed focusrite-scarlett-mounting-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 4706, + 4734, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/french-press/ops.snap b/rust/kcl-lib/tests/kcl_samples/french-press/ops.snap index 05ebc25d1..17b8a9f40 100644 --- a/rust/kcl-lib/tests/kcl_samples/french-press/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/french-press/ops.snap @@ -323,8 +323,8 @@ description: Operations executed french-press.kcl } }, "sourceRange": [ - 0, - 0, + 2157, + 2179, 0 ] } @@ -500,8 +500,8 @@ description: Operations executed french-press.kcl } }, "sourceRange": [ - 0, - 0, + 2185, + 2340, 0 ] } @@ -1293,8 +1293,8 @@ description: Operations executed french-press.kcl } }, "sourceRange": [ - 0, - 0, + 5053, + 5092, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/gear-rack/ops.snap b/rust/kcl-lib/tests/kcl_samples/gear-rack/ops.snap index 4252f7fba..14380faa8 100644 --- a/rust/kcl-lib/tests/kcl_samples/gear-rack/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/gear-rack/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed gear-rack.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed gear-rack.kcl } }, "sourceRange": [ - 0, - 0, + 731, + 754, 0 ] } @@ -147,8 +147,8 @@ description: Operations executed gear-rack.kcl } }, "sourceRange": [ - 0, - 0, + 1279, + 1302, 0 ] } @@ -265,8 +265,8 @@ description: Operations executed gear-rack.kcl } }, "sourceRange": [ - 0, - 0, + 1409, + 1508, 0 ] } @@ -332,8 +332,8 @@ description: Operations executed gear-rack.kcl } }, "sourceRange": [ - 0, - 0, + 1820, + 1843, 0 ] } @@ -399,8 +399,8 @@ description: Operations executed gear-rack.kcl } }, "sourceRange": [ - 0, - 0, + 2157, + 2180, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/gear/ops.snap b/rust/kcl-lib/tests/kcl_samples/gear/ops.snap index 1dfcaf42e..4ea04bf24 100644 --- a/rust/kcl-lib/tests/kcl_samples/gear/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/gear/ops.snap @@ -5897,8 +5897,8 @@ description: Operations executed gear.kcl } }, "sourceRange": [ - 0, - 0, + 1405, + 1433, 0 ] } @@ -9802,8 +9802,8 @@ description: Operations executed gear.kcl } }, "sourceRange": [ - 0, - 0, + 2128, + 2156, 0 ] } @@ -9979,8 +9979,8 @@ description: Operations executed gear.kcl } }, "sourceRange": [ - 0, - 0, + 2162, + 2322, 0 ] } @@ -10097,8 +10097,8 @@ description: Operations executed gear.kcl } }, "sourceRange": [ - 0, - 0, + 3058, + 3087, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate-magnets/ops.snap b/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate-magnets/ops.snap index f5c5e71cb..3ff4e1a7e 100644 --- a/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate-magnets/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate-magnets/ops.snap @@ -919,8 +919,8 @@ description: Operations executed gridfinity-baseplate-magnets.kcl ] }, "sourceRange": [ - 0, - 0, + 2243, + 2360, 0 ] } @@ -1183,8 +1183,8 @@ description: Operations executed gridfinity-baseplate-magnets.kcl ] }, "sourceRange": [ - 0, - 0, + 2584, + 2701, 0 ] } @@ -2008,8 +2008,8 @@ description: Operations executed gridfinity-baseplate-magnets.kcl ] }, "sourceRange": [ - 0, - 0, + 6613, + 6730, 0 ] } @@ -2243,8 +2243,8 @@ description: Operations executed gridfinity-baseplate-magnets.kcl ] }, "sourceRange": [ - 0, - 0, + 6933, + 7050, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate/ops.snap b/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate/ops.snap index 821a966a0..ce4ee3e5d 100644 --- a/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/gridfinity-baseplate/ops.snap @@ -919,8 +919,8 @@ description: Operations executed gridfinity-baseplate.kcl ] }, "sourceRange": [ - 0, - 0, + 2118, + 2235, 0 ] } @@ -1183,8 +1183,8 @@ description: Operations executed gridfinity-baseplate.kcl ] }, "sourceRange": [ - 0, - 0, + 2459, + 2576, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/gridfinity-bins-stacking-lip/ops.snap b/rust/kcl-lib/tests/kcl_samples/gridfinity-bins-stacking-lip/ops.snap index 1cd5a9a79..248936260 100644 --- a/rust/kcl-lib/tests/kcl_samples/gridfinity-bins-stacking-lip/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/gridfinity-bins-stacking-lip/ops.snap @@ -722,8 +722,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl } }, "sourceRange": [ - 0, - 0, + 2875, + 2899, 0 ] } @@ -794,8 +794,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl } }, "sourceRange": [ - 0, - 0, + 2905, + 3134, 0 ] } @@ -885,8 +885,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl ] }, "sourceRange": [ - 0, - 0, + 3580, + 3607, 0 ] } @@ -1137,8 +1137,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl ] }, "sourceRange": [ - 0, - 0, + 3813, + 3943, 0 ] } @@ -1389,8 +1389,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl ] }, "sourceRange": [ - 0, - 0, + 4174, + 4304, 0 ] } @@ -1612,8 +1612,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl ] }, "sourceRange": [ - 0, - 0, + 4529, + 4659, 0 ] } @@ -1715,8 +1715,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl } }, "sourceRange": [ - 0, - 0, + 5002, + 5046, 0 ] } @@ -1787,8 +1787,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl } }, "sourceRange": [ - 0, - 0, + 5052, + 5284, 0 ] } @@ -1847,8 +1847,8 @@ description: Operations executed gridfinity-bins-stacking-lip.kcl } }, "sourceRange": [ - 0, - 0, + 5290, + 5332, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/gridfinity-bins/ops.snap b/rust/kcl-lib/tests/kcl_samples/gridfinity-bins/ops.snap index e8c6b7dba..46932a4e2 100644 --- a/rust/kcl-lib/tests/kcl_samples/gridfinity-bins/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/gridfinity-bins/ops.snap @@ -722,8 +722,8 @@ description: Operations executed gridfinity-bins.kcl } }, "sourceRange": [ - 0, - 0, + 2618, + 2642, 0 ] } @@ -794,8 +794,8 @@ description: Operations executed gridfinity-bins.kcl } }, "sourceRange": [ - 0, - 0, + 2648, + 2877, 0 ] } @@ -885,8 +885,8 @@ description: Operations executed gridfinity-bins.kcl ] }, "sourceRange": [ - 0, - 0, + 3323, + 3350, 0 ] } @@ -1137,8 +1137,8 @@ description: Operations executed gridfinity-bins.kcl ] }, "sourceRange": [ - 0, - 0, + 3556, + 3686, 0 ] } @@ -1389,8 +1389,8 @@ description: Operations executed gridfinity-bins.kcl ] }, "sourceRange": [ - 0, - 0, + 3917, + 4047, 0 ] } @@ -1612,8 +1612,8 @@ description: Operations executed gridfinity-bins.kcl ] }, "sourceRange": [ - 0, - 0, + 4272, + 4402, 0 ] } @@ -1715,8 +1715,8 @@ description: Operations executed gridfinity-bins.kcl } }, "sourceRange": [ - 0, - 0, + 4771, + 4815, 0 ] } @@ -1787,8 +1787,8 @@ description: Operations executed gridfinity-bins.kcl } }, "sourceRange": [ - 0, - 0, + 4821, + 5053, 0 ] } @@ -1847,8 +1847,8 @@ description: Operations executed gridfinity-bins.kcl } }, "sourceRange": [ - 0, - 0, + 5059, + 5101, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/hex-nut/ops.snap b/rust/kcl-lib/tests/kcl_samples/hex-nut/ops.snap index e8885fa73..d15e8b9ea 100644 --- a/rust/kcl-lib/tests/kcl_samples/hex-nut/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/hex-nut/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed hex-nut.kcl --- [ @@ -118,8 +118,8 @@ description: Operations executed hex-nut.kcl } }, "sourceRange": [ - 0, - 0, + 1038, + 1059, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/i-beam/ops.snap b/rust/kcl-lib/tests/kcl_samples/i-beam/ops.snap index 87687bae0..6df083361 100644 --- a/rust/kcl-lib/tests/kcl_samples/i-beam/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/i-beam/ops.snap @@ -66,8 +66,8 @@ description: Operations executed i-beam.kcl ] }, "sourceRange": [ - 0, - 0, + 652, + 680, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/kitt/ops.snap b/rust/kcl-lib/tests/kcl_samples/kitt/ops.snap index c3ac796ca..fc831cf5c 100644 --- a/rust/kcl-lib/tests/kcl_samples/kitt/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/kitt/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed kitt.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 900, + 930, 0 ] } @@ -160,8 +160,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -243,8 +243,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 2204, + 2235, 0 ] } @@ -339,8 +339,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -438,8 +438,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -537,8 +537,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -636,8 +636,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -719,8 +719,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 3485, + 3514, 0 ] } @@ -815,8 +815,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -914,8 +914,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -1013,8 +1013,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -1112,8 +1112,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -1211,8 +1211,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -1310,8 +1310,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -1409,8 +1409,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -1508,8 +1508,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -1607,8 +1607,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -1706,8 +1706,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -1805,8 +1805,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -1904,8 +1904,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -2003,8 +2003,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -2185,8 +2185,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -2370,8 +2370,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -2489,8 +2489,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -2588,8 +2588,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -2687,8 +2687,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -2786,8 +2786,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -2905,8 +2905,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -3004,8 +3004,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -3103,8 +3103,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -3202,8 +3202,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -3305,8 +3305,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -3405,8 +3405,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -3505,8 +3505,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -3605,8 +3605,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -3705,8 +3705,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -3805,8 +3805,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -3905,8 +3905,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -4005,8 +4005,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -4105,8 +4105,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } @@ -4205,8 +4205,8 @@ description: Operations executed kitt.kcl } }, "sourceRange": [ - 0, - 0, + 449, + 472, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/lego/ops.snap b/rust/kcl-lib/tests/kcl_samples/lego/ops.snap index 6af7c6a52..56f319278 100644 --- a/rust/kcl-lib/tests/kcl_samples/lego/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/lego/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed lego.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed lego.kcl } }, "sourceRange": [ - 0, - 0, + 1780, + 1804, 0 ] } @@ -138,8 +138,8 @@ description: Operations executed lego.kcl } }, "sourceRange": [ - 0, - 0, + 2221, + 2252, 0 ] } @@ -262,8 +262,8 @@ description: Operations executed lego.kcl ] }, "sourceRange": [ - 0, - 0, + 2687, + 2715, 0 ] } @@ -528,8 +528,8 @@ description: Operations executed lego.kcl ] }, "sourceRange": [ - 0, - 0, + 3197, + 3226, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/mounting-plate/ops.snap b/rust/kcl-lib/tests/kcl_samples/mounting-plate/ops.snap index edab4230a..954b3067e 100644 --- a/rust/kcl-lib/tests/kcl_samples/mounting-plate/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/mounting-plate/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed mounting-plate.kcl --- [ @@ -273,8 +273,8 @@ description: Operations executed mounting-plate.kcl } }, "sourceRange": [ - 0, - 0, + 1825, + 1857, 0 ] } @@ -345,8 +345,8 @@ description: Operations executed mounting-plate.kcl } }, "sourceRange": [ - 0, - 0, + 1863, + 2127, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/ops.snap b/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/ops.snap index 4690aef41..856f6a977 100644 --- a/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/multi-axis-robot/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed multi-axis-robot.kcl --- [ @@ -212,9 +212,9 @@ description: Operations executed multi-axis-robot.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 769, + 1045, + 3 ] } }, @@ -352,9 +352,9 @@ description: Operations executed multi-axis-robot.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1280, + 1362, + 3 ] } }, @@ -923,9 +923,9 @@ description: Operations executed multi-axis-robot.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 323, + 406, + 4 ] } }, @@ -1340,9 +1340,9 @@ description: Operations executed multi-axis-robot.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1143, + 1226, + 4 ] } }, @@ -1685,9 +1685,9 @@ description: Operations executed multi-axis-robot.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1996, + 2079, + 4 ] } }, @@ -2341,9 +2341,9 @@ description: Operations executed multi-axis-robot.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1033, + 1116, + 5 ] } }, @@ -2519,9 +2519,9 @@ description: Operations executed multi-axis-robot.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1415, + 1498, + 5 ] } }, @@ -3400,9 +3400,9 @@ description: Operations executed multi-axis-robot.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 1299, + 1382, + 6 ] } }, diff --git a/rust/kcl-lib/tests/kcl_samples/pipe-flange-assembly/ops.snap b/rust/kcl-lib/tests/kcl_samples/pipe-flange-assembly/ops.snap index 9d099aef4..4278d789c 100644 --- a/rust/kcl-lib/tests/kcl_samples/pipe-flange-assembly/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/pipe-flange-assembly/ops.snap @@ -247,8 +247,8 @@ description: Operations executed pipe-flange-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 5504, + 5535, 0 ] } @@ -410,8 +410,8 @@ description: Operations executed pipe-flange-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 5838, + 5872, 0 ] } @@ -713,8 +713,8 @@ description: Operations executed pipe-flange-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 3177, + 3198, 0 ] } @@ -893,8 +893,8 @@ description: Operations executed pipe-flange-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 6049, + 6204, 0 ] } @@ -1431,8 +1431,8 @@ description: Operations executed pipe-flange-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 6407, + 6562, 0 ] } @@ -1857,8 +1857,8 @@ description: Operations executed pipe-flange-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 6781, + 6936, 0 ] } @@ -2160,8 +2160,8 @@ description: Operations executed pipe-flange-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 3177, + 3198, 0 ] } @@ -2340,8 +2340,8 @@ description: Operations executed pipe-flange-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 7426, + 7581, 0 ] } @@ -2643,8 +2643,8 @@ description: Operations executed pipe-flange-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 4236, + 4258, 0 ] } @@ -2823,8 +2823,8 @@ description: Operations executed pipe-flange-assembly.kcl } }, "sourceRange": [ - 0, - 0, + 7778, + 7933, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/poopy-shoe/ops.snap b/rust/kcl-lib/tests/kcl_samples/poopy-shoe/ops.snap index b29db4d7d..43bea25ba 100644 --- a/rust/kcl-lib/tests/kcl_samples/poopy-shoe/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/poopy-shoe/ops.snap @@ -209,8 +209,8 @@ description: Operations executed poopy-shoe.kcl } }, "sourceRange": [ - 0, - 0, + 1706, + 1743, 0 ] } @@ -452,8 +452,8 @@ description: Operations executed poopy-shoe.kcl } }, "sourceRange": [ - 0, - 0, + 2178, + 2209, 0 ] } @@ -532,8 +532,8 @@ description: Operations executed poopy-shoe.kcl } }, "sourceRange": [ - 0, - 0, + 2907, + 2938, 0 ] } @@ -775,8 +775,8 @@ description: Operations executed poopy-shoe.kcl } }, "sourceRange": [ - 0, - 0, + 3566, + 3597, 0 ] } @@ -856,8 +856,8 @@ description: Operations executed poopy-shoe.kcl } }, "sourceRange": [ - 0, - 0, + 3816, + 3847, 0 ] } @@ -930,8 +930,8 @@ description: Operations executed poopy-shoe.kcl } }, "sourceRange": [ - 0, - 0, + 4043, + 4093, 0 ] } @@ -1173,8 +1173,8 @@ description: Operations executed poopy-shoe.kcl } }, "sourceRange": [ - 0, - 0, + 4597, + 4629, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/sheet-metal-bracket/ops.snap b/rust/kcl-lib/tests/kcl_samples/sheet-metal-bracket/ops.snap index 4fe03bd6e..95f8ead8d 100644 --- a/rust/kcl-lib/tests/kcl_samples/sheet-metal-bracket/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/sheet-metal-bracket/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed sheet-metal-bracket.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1299, + 1325, 0 ] } @@ -124,8 +124,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1331, + 1410, 0 ] } @@ -184,8 +184,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1416, + 1502, 0 ] } @@ -244,8 +244,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1508, + 1594, 0 ] } @@ -304,8 +304,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1600, + 1679, 0 ] } @@ -364,8 +364,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1685, + 1771, 0 ] } @@ -424,8 +424,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1777, + 1856, 0 ] } @@ -484,8 +484,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1862, + 1942, 0 ] } @@ -544,8 +544,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 1948, + 2035, 0 ] } @@ -687,8 +687,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 2446, + 2473, 0 ] } @@ -751,8 +751,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 2479, + 2608, 0 ] } @@ -894,8 +894,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 2976, + 3003, 0 ] } @@ -958,8 +958,8 @@ description: Operations executed sheet-metal-bracket.kcl } }, "sourceRange": [ - 0, - 0, + 3009, + 3139, 0 ] } diff --git a/rust/kcl-lib/tests/kcl_samples/walkie-talkie/ops.snap b/rust/kcl-lib/tests/kcl_samples/walkie-talkie/ops.snap index d611cd202..b00637bd2 100644 --- a/rust/kcl-lib/tests/kcl_samples/walkie-talkie/ops.snap +++ b/rust/kcl-lib/tests/kcl_samples/walkie-talkie/ops.snap @@ -136,9 +136,9 @@ description: Operations executed walkie-talkie.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 564, + 794, + 3 ] } }, @@ -2035,9 +2035,9 @@ description: Operations executed walkie-talkie.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 745, + 890, + 8 ] } }, @@ -2227,9 +2227,9 @@ description: Operations executed walkie-talkie.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 745, + 890, + 8 ] } }, @@ -2419,9 +2419,9 @@ description: Operations executed walkie-talkie.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 745, + 890, + 8 ] } }, @@ -2611,9 +2611,9 @@ description: Operations executed walkie-talkie.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 745, + 890, + 8 ] } }, @@ -2923,9 +2923,9 @@ description: Operations executed walkie-talkie.kcl } }, "sourceRange": [ - 0, - 0, - 0 + 891, + 1096, + 6 ] } }, diff --git a/rust/kcl-lib/tests/kittycad_svg/ops.snap b/rust/kcl-lib/tests/kittycad_svg/ops.snap index 04cfc2861..08b7c1cf8 100644 --- a/rust/kcl-lib/tests/kittycad_svg/ops.snap +++ b/rust/kcl-lib/tests/kittycad_svg/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed kittycad_svg.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed kittycad_svg.kcl } }, "sourceRange": [ - 0, - 0, + 18347, + 18366, 0 ] } diff --git a/rust/kcl-lib/tests/linear_pattern3d_a_pattern/ops.snap b/rust/kcl-lib/tests/linear_pattern3d_a_pattern/ops.snap index 47c026d9a..c59668c7c 100644 --- a/rust/kcl-lib/tests/linear_pattern3d_a_pattern/ops.snap +++ b/rust/kcl-lib/tests/linear_pattern3d_a_pattern/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed linear_pattern3d_a_pattern.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed linear_pattern3d_a_pattern.kcl } }, "sourceRange": [ - 0, - 0, + 159, + 178, 0 ] } diff --git a/rust/kcl-lib/tests/mike_stress_test/ops.snap b/rust/kcl-lib/tests/mike_stress_test/ops.snap index 53cd909f9..261009025 100644 --- a/rust/kcl-lib/tests/mike_stress_test/ops.snap +++ b/rust/kcl-lib/tests/mike_stress_test/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed mike_stress_test.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed mike_stress_test.kcl } }, "sourceRange": [ - 0, - 0, + 77102, + 77121, 0 ] } diff --git a/rust/kcl-lib/tests/neg_xz_plane/ops.snap b/rust/kcl-lib/tests/neg_xz_plane/ops.snap index d5e4f21fd..7e85dce1a 100644 --- a/rust/kcl-lib/tests/neg_xz_plane/ops.snap +++ b/rust/kcl-lib/tests/neg_xz_plane/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed neg_xz_plane.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed neg_xz_plane.kcl } }, "sourceRange": [ - 0, - 0, + 151, + 174, 0 ] } diff --git a/rust/kcl-lib/tests/parametric/ops.snap b/rust/kcl-lib/tests/parametric/ops.snap index 4db42c819..3e68da091 100644 --- a/rust/kcl-lib/tests/parametric/ops.snap +++ b/rust/kcl-lib/tests/parametric/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed parametric.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed parametric.kcl } }, "sourceRange": [ - 0, - 0, + 465, + 488, 0 ] } diff --git a/rust/kcl-lib/tests/parametric_with_tan_arc/ops.snap b/rust/kcl-lib/tests/parametric_with_tan_arc/ops.snap index 0f5c2bbf0..4c920f8cc 100644 --- a/rust/kcl-lib/tests/parametric_with_tan_arc/ops.snap +++ b/rust/kcl-lib/tests/parametric_with_tan_arc/ops.snap @@ -64,8 +64,8 @@ description: Operations executed parametric_with_tan_arc.kcl } }, "sourceRange": [ - 0, - 0, + 622, + 645, 0 ] } diff --git a/rust/kcl-lib/tests/pentagon_fillet_sugar/ops.snap b/rust/kcl-lib/tests/pentagon_fillet_sugar/ops.snap index 9634852de..443acd5af 100644 --- a/rust/kcl-lib/tests/pentagon_fillet_sugar/ops.snap +++ b/rust/kcl-lib/tests/pentagon_fillet_sugar/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed pentagon_fillet_sugar.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed pentagon_fillet_sugar.kcl } }, "sourceRange": [ - 0, - 0, + 379, + 411, 0 ] } @@ -164,8 +164,8 @@ description: Operations executed pentagon_fillet_sugar.kcl } }, "sourceRange": [ - 0, - 0, + 612, + 640, 0 ] } @@ -229,8 +229,8 @@ description: Operations executed pentagon_fillet_sugar.kcl } }, "sourceRange": [ - 0, - 0, + 646, + 773, 0 ] } @@ -329,8 +329,8 @@ description: Operations executed pentagon_fillet_sugar.kcl } }, "sourceRange": [ - 0, - 0, + 812, + 840, 0 ] } @@ -394,8 +394,8 @@ description: Operations executed pentagon_fillet_sugar.kcl } }, "sourceRange": [ - 0, - 0, + 846, + 973, 0 ] } diff --git a/rust/kcl-lib/tests/pipe_as_arg/ops.snap b/rust/kcl-lib/tests/pipe_as_arg/ops.snap index 84444ccc8..41993cd81 100644 --- a/rust/kcl-lib/tests/pipe_as_arg/ops.snap +++ b/rust/kcl-lib/tests/pipe_as_arg/ops.snap @@ -93,8 +93,8 @@ description: Operations executed pipe_as_arg.kcl } }, "sourceRange": [ - 0, - 0, + 367, + 391, 0 ] } diff --git a/rust/kcl-lib/tests/poop_chute/ops.snap b/rust/kcl-lib/tests/poop_chute/ops.snap index dae645311..ef65198c1 100644 --- a/rust/kcl-lib/tests/poop_chute/ops.snap +++ b/rust/kcl-lib/tests/poop_chute/ops.snap @@ -209,8 +209,8 @@ description: Operations executed poop_chute.kcl } }, "sourceRange": [ - 0, - 0, + 1719, + 1757, 0 ] } diff --git a/rust/kcl-lib/tests/riddle_small/ops.snap b/rust/kcl-lib/tests/riddle_small/ops.snap index 4b3ee5f06..6711c3a8e 100644 --- a/rust/kcl-lib/tests/riddle_small/ops.snap +++ b/rust/kcl-lib/tests/riddle_small/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed riddle_small.kcl --- [ @@ -102,8 +102,8 @@ description: Operations executed riddle_small.kcl } }, "sourceRange": [ - 0, - 0, + 287, + 306, 0 ] } diff --git a/rust/kcl-lib/tests/sketch-on-chamfer-two-times-different-order/ops.snap b/rust/kcl-lib/tests/sketch-on-chamfer-two-times-different-order/ops.snap index 3e8a392f1..3fd80e612 100644 --- a/rust/kcl-lib/tests/sketch-on-chamfer-two-times-different-order/ops.snap +++ b/rust/kcl-lib/tests/sketch-on-chamfer-two-times-different-order/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed sketch-on-chamfer-two-times-different-order.kcl --- [ @@ -125,8 +125,8 @@ description: Operations executed sketch-on-chamfer-two-times-different-order.kcl } }, "sourceRange": [ - 0, - 0, + 492, + 527, 0 ] } @@ -196,8 +196,8 @@ description: Operations executed sketch-on-chamfer-two-times-different-order.kcl } }, "sourceRange": [ - 0, - 0, + 533, + 600, 0 ] } @@ -268,8 +268,8 @@ description: Operations executed sketch-on-chamfer-two-times-different-order.kcl } }, "sourceRange": [ - 0, - 0, + 606, + 656, 0 ] } diff --git a/rust/kcl-lib/tests/sketch-on-chamfer-two-times/ops.snap b/rust/kcl-lib/tests/sketch-on-chamfer-two-times/ops.snap index 19947d70b..e06ca0ed0 100644 --- a/rust/kcl-lib/tests/sketch-on-chamfer-two-times/ops.snap +++ b/rust/kcl-lib/tests/sketch-on-chamfer-two-times/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed sketch-on-chamfer-two-times.kcl --- [ @@ -125,8 +125,8 @@ description: Operations executed sketch-on-chamfer-two-times.kcl } }, "sourceRange": [ - 0, - 0, + 492, + 527, 0 ] } @@ -197,8 +197,8 @@ description: Operations executed sketch-on-chamfer-two-times.kcl } }, "sourceRange": [ - 0, - 0, + 533, + 583, 0 ] } @@ -268,8 +268,8 @@ description: Operations executed sketch-on-chamfer-two-times.kcl } }, "sourceRange": [ - 0, - 0, + 589, + 656, 0 ] } diff --git a/rust/kcl-lib/tests/sketch_in_object/ops.snap b/rust/kcl-lib/tests/sketch_in_object/ops.snap index c2c78cf59..7719a387a 100644 --- a/rust/kcl-lib/tests/sketch_in_object/ops.snap +++ b/rust/kcl-lib/tests/sketch_in_object/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed sketch_in_object.kcl --- [ @@ -83,8 +83,8 @@ description: Operations executed sketch_in_object.kcl } }, "sourceRange": [ - 0, - 0, + 425, + 446, 0 ] } @@ -169,8 +169,8 @@ description: Operations executed sketch_in_object.kcl } }, "sourceRange": [ - 0, - 0, + 483, + 503, 0 ] } diff --git a/rust/kcl-lib/tests/sketch_on_face/ops.snap b/rust/kcl-lib/tests/sketch_on_face/ops.snap index d00d3e95f..6308ff1c0 100644 --- a/rust/kcl-lib/tests/sketch_on_face/ops.snap +++ b/rust/kcl-lib/tests/sketch_on_face/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed sketch_on_face.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed sketch_on_face.kcl } }, "sourceRange": [ - 0, - 0, + 200, + 219, 0 ] } @@ -145,8 +145,8 @@ description: Operations executed sketch_on_face.kcl } }, "sourceRange": [ - 0, - 0, + 386, + 405, 0 ] } diff --git a/rust/kcl-lib/tests/sketch_on_face_after_fillets_referencing_face/ops.snap b/rust/kcl-lib/tests/sketch_on_face_after_fillets_referencing_face/ops.snap index 0d9d425f7..d2a4fcd90 100644 --- a/rust/kcl-lib/tests/sketch_on_face_after_fillets_referencing_face/ops.snap +++ b/rust/kcl-lib/tests/sketch_on_face_after_fillets_referencing_face/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed sketch_on_face_after_fillets_referencing_face.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed sketch_on_face_after_fillets_referencing_face.k } }, "sourceRange": [ - 0, - 0, + 1305, + 1328, 0 ] } @@ -124,8 +124,8 @@ description: Operations executed sketch_on_face_after_fillets_referencing_face.k } }, "sourceRange": [ - 0, - 0, + 1334, + 1399, 0 ] } @@ -178,8 +178,8 @@ description: Operations executed sketch_on_face_after_fillets_referencing_face.k } }, "sourceRange": [ - 0, - 0, + 1405, + 1482, 0 ] } @@ -259,8 +259,8 @@ description: Operations executed sketch_on_face_after_fillets_referencing_face.k } }, "sourceRange": [ - 0, - 0, + 1737, + 1757, 0 ] } diff --git a/rust/kcl-lib/tests/sketch_on_face_circle_tagged/ops.snap b/rust/kcl-lib/tests/sketch_on_face_circle_tagged/ops.snap index d6cf33271..b682ed0db 100644 --- a/rust/kcl-lib/tests/sketch_on_face_circle_tagged/ops.snap +++ b/rust/kcl-lib/tests/sketch_on_face_circle_tagged/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed sketch_on_face_circle_tagged.kcl --- [ @@ -83,8 +83,8 @@ description: Operations executed sketch_on_face_circle_tagged.kcl } }, "sourceRange": [ - 0, - 0, + 231, + 251, 0 ] } @@ -163,8 +163,8 @@ description: Operations executed sketch_on_face_circle_tagged.kcl } }, "sourceRange": [ - 0, - 0, + 356, + 375, 0 ] } diff --git a/rust/kcl-lib/tests/sketch_on_face_end/ops.snap b/rust/kcl-lib/tests/sketch_on_face_end/ops.snap index efc1c65cf..7d2265112 100644 --- a/rust/kcl-lib/tests/sketch_on_face_end/ops.snap +++ b/rust/kcl-lib/tests/sketch_on_face_end/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed sketch_on_face_end.kcl --- [ @@ -83,8 +83,8 @@ description: Operations executed sketch_on_face_end.kcl } }, "sourceRange": [ - 0, - 0, + 231, + 251, 0 ] } @@ -163,8 +163,8 @@ description: Operations executed sketch_on_face_end.kcl } }, "sourceRange": [ - 0, - 0, + 419, + 438, 0 ] } diff --git a/rust/kcl-lib/tests/sketch_on_face_end_negative_extrude/ops.snap b/rust/kcl-lib/tests/sketch_on_face_end_negative_extrude/ops.snap index 1e4eb37ad..9d59c46f8 100644 --- a/rust/kcl-lib/tests/sketch_on_face_end_negative_extrude/ops.snap +++ b/rust/kcl-lib/tests/sketch_on_face_end_negative_extrude/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed sketch_on_face_end_negative_extrude.kcl --- [ @@ -83,8 +83,8 @@ description: Operations executed sketch_on_face_end_negative_extrude.kcl } }, "sourceRange": [ - 0, - 0, + 231, + 251, 0 ] } @@ -163,8 +163,8 @@ description: Operations executed sketch_on_face_end_negative_extrude.kcl } }, "sourceRange": [ - 0, - 0, + 419, + 439, 0 ] } diff --git a/rust/kcl-lib/tests/sketch_on_face_start/ops.snap b/rust/kcl-lib/tests/sketch_on_face_start/ops.snap index d719989ce..ce04557a2 100644 --- a/rust/kcl-lib/tests/sketch_on_face_start/ops.snap +++ b/rust/kcl-lib/tests/sketch_on_face_start/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed sketch_on_face_start.kcl --- [ @@ -83,8 +83,8 @@ description: Operations executed sketch_on_face_start.kcl } }, "sourceRange": [ - 0, - 0, + 231, + 251, 0 ] } @@ -163,8 +163,8 @@ description: Operations executed sketch_on_face_start.kcl } }, "sourceRange": [ - 0, - 0, + 424, + 443, 0 ] } diff --git a/rust/kcl-lib/tests/ssi_pattern/ops.snap b/rust/kcl-lib/tests/ssi_pattern/ops.snap index 2c1cafcdc..8e0b93216 100644 --- a/rust/kcl-lib/tests/ssi_pattern/ops.snap +++ b/rust/kcl-lib/tests/ssi_pattern/ops.snap @@ -234,8 +234,8 @@ description: Operations executed ssi_pattern.kcl ] }, "sourceRange": [ - 0, - 0, + 616, + 637, 0 ] } diff --git a/rust/kcl-lib/tests/tangential_arc/ops.snap b/rust/kcl-lib/tests/tangential_arc/ops.snap index f763ca488..fe9fb261f 100644 --- a/rust/kcl-lib/tests/tangential_arc/ops.snap +++ b/rust/kcl-lib/tests/tangential_arc/ops.snap @@ -64,8 +64,8 @@ description: Operations executed tangential_arc.kcl } }, "sourceRange": [ - 0, - 0, + 168, + 188, 0 ] } diff --git a/rust/kcl-lib/tests/xz_plane/ops.snap b/rust/kcl-lib/tests/xz_plane/ops.snap index cc09bc4be..6c1b99a37 100644 --- a/rust/kcl-lib/tests/xz_plane/ops.snap +++ b/rust/kcl-lib/tests/xz_plane/ops.snap @@ -1,5 +1,5 @@ --- -source: kcl/src/simulation_tests.rs +source: kcl-lib/src/simulation_tests.rs description: Operations executed xz_plane.kcl --- [ @@ -64,8 +64,8 @@ description: Operations executed xz_plane.kcl } }, "sourceRange": [ - 0, - 0, + 150, + 173, 0 ] } diff --git a/rust/kcl-python-bindings/Cargo.toml b/rust/kcl-python-bindings/Cargo.toml index 36866c284..6c6caade9 100644 --- a/rust/kcl-python-bindings/Cargo.toml +++ b/rust/kcl-python-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kcl-python-bindings" -version = "0.3.48" +version = "0.3.49" edition = "2021" repository = "https://github.com/kittycad/modeling-app" diff --git a/rust/kcl-test-server/Cargo.toml b/rust/kcl-test-server/Cargo.toml index 41ee5af57..41b57dc94 100644 --- a/rust/kcl-test-server/Cargo.toml +++ b/rust/kcl-test-server/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kcl-test-server" description = "A test server for KCL" -version = "0.1.48" +version = "0.1.49" edition = "2021" license = "MIT" diff --git a/rust/kcl-to-core/Cargo.toml b/rust/kcl-to-core/Cargo.toml index 6f7e616a8..050abce4e 100644 --- a/rust/kcl-to-core/Cargo.toml +++ b/rust/kcl-to-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kcl-to-core" description = "Utility methods to convert kcl to engine core executable tests" -version = "0.1.48" +version = "0.1.49" edition = "2021" license = "MIT" repository = "https://github.com/KittyCAD/modeling-app" diff --git a/rust/kcl-wasm-lib/Cargo.toml b/rust/kcl-wasm-lib/Cargo.toml index 2cc3b8d69..2f0d31331 100644 --- a/rust/kcl-wasm-lib/Cargo.toml +++ b/rust/kcl-wasm-lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kcl-wasm-lib" -version = "0.1.48" +version = "0.1.49" edition = "2021" repository = "https://github.com/KittyCAD/modeling-app" rust-version = "1.83" diff --git a/src/components/Gizmo.tsx b/src/components/Gizmo.tsx index b500b1332..06c681bb6 100644 --- a/src/components/Gizmo.tsx +++ b/src/components/Gizmo.tsx @@ -136,6 +136,7 @@ export default function Gizmo() {
diff --git a/src/lang/std/engineConnection.ts b/src/lang/std/engineConnection.ts index 44a92d073..e4ac5b247 100644 --- a/src/lang/std/engineConnection.ts +++ b/src/lang/std/engineConnection.ts @@ -1914,7 +1914,7 @@ export class EngineCommandManager extends EventTarget { this.engineConnection?.tearDown(opts) - // Our window.tearDown assignment causes this case to happen which is + // Our window.engineCommandManager.tearDown assignment causes this case to happen which is // only really for tests. // @ts-ignore } else if (this.engineCommandManager?.engineConnection) { diff --git a/src/lib/desktop.ts b/src/lib/desktop.ts index a646c15b2..5e252aaa8 100644 --- a/src/lib/desktop.ts +++ b/src/lib/desktop.ts @@ -405,6 +405,8 @@ export const getAppSettingsFilePath = async () => { const testSettingsPath = await window.electron.getAppTestProperty( 'TEST_SETTINGS_FILE_KEY' ) + if (isTestEnv && !testSettingsPath) return SETTINGS_FILE_NAME + const appConfig = await window.electron.getPath('appData') const fullPath = isTestEnv ? testSettingsPath diff --git a/src/lib/singletons.ts b/src/lib/singletons.ts index 4f9481b72..ca9796c95 100644 --- a/src/lib/singletons.ts +++ b/src/lib/singletons.ts @@ -10,9 +10,15 @@ export const codeManager = new CodeManager() export const engineCommandManager = new EngineCommandManager() +declare global { + interface Window { + editorManager: EditorManager + engineCommandManager: EngineCommandManager + } +} + // Accessible for tests mostly -// @ts-ignore -window.tearDown = engineCommandManager.tearDown +window.engineCommandManager = engineCommandManager // This needs to be after codeManager is created. export const kclManager = new KclManager(engineCommandManager) @@ -23,12 +29,6 @@ engineCommandManager.camControlsCameraChange = sceneInfra.onCameraChange export const sceneEntitiesManager = new SceneEntities(engineCommandManager) -declare global { - interface Window { - editorManager: EditorManager - } -} - // This needs to be after sceneInfra and engineCommandManager are is created. export const editorManager = new EditorManager() diff --git a/yarn.lock b/yarn.lock index 23235b0a6..222cf11c8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -33,6 +33,15 @@ "@babel/highlight" "^7.24.7" picocolors "^1.0.0" +"@babel/code-frame@^7.26.2": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" + integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + js-tokens "^4.0.0" + picocolors "^1.0.0" + "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.2", "@babel/compat-data@^7.25.4": version "7.25.4" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb" @@ -228,11 +237,21 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + "@babel/helper-validator-identifier@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + "@babel/helper-validator-option@^7.24.8": version "7.24.8" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" @@ -248,12 +267,12 @@ "@babel/types" "^7.25.0" "@babel/helpers@^7.25.0": - version "7.25.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.25.0.tgz#e69beb7841cb93a6505531ede34f34e6a073650a" - integrity sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw== + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.10.tgz#6baea3cd62ec2d0c1068778d63cb1314f6637384" + integrity sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g== dependencies: - "@babel/template" "^7.25.0" - "@babel/types" "^7.25.0" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.10" "@babel/highlight@^7.24.7": version "7.24.7" @@ -279,6 +298,13 @@ dependencies: "@babel/types" "^7.25.4" +"@babel/parser@^7.26.9": + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.10.tgz#e9bdb82f14b97df6569b0b038edd436839c57749" + integrity sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA== + dependencies: + "@babel/types" "^7.26.10" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.3": version "7.25.3" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz#dca427b45a6c0f5c095a1c639dfe2476a3daba7f" @@ -971,9 +997,9 @@ integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== "@babel/runtime@^7.12.5", "@babel/runtime@^7.20.13", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": - version "7.25.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb" - integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.10.tgz#a07b4d8fa27af131a633d7b3524db803eb4764c2" + integrity sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw== dependencies: regenerator-runtime "^0.14.0" @@ -986,6 +1012,15 @@ "@babel/parser" "^7.25.0" "@babel/types" "^7.25.0" +"@babel/template@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" + integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" + "@babel/traverse@^7.21.4", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3": version "7.25.3" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.3.tgz#f1b901951c83eda2f3e29450ce92743783373490" @@ -1030,6 +1065,14 @@ "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" +"@babel/types@^7.26.10", "@babel/types@^7.26.9": + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.10.tgz#396382f6335bd4feb65741eacfc808218f859259" + integrity sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.17.0": version "6.17.0" resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.17.0.tgz#24ff5fc37fd91f6439df6f4ff9c8e910cde1b053"