diff --git a/e2e/playwright/fixtures/homePageFixture.ts b/e2e/playwright/fixtures/homePageFixture.ts index 07044ae37ef..09d77b01496 100644 --- a/e2e/playwright/fixtures/homePageFixture.ts +++ b/e2e/playwright/fixtures/homePageFixture.ts @@ -99,7 +99,6 @@ export class HomePageFixture { createAndGoToProject = async (projectTitle = 'untitled') => { await this.projectsLoaded() await this.projectButtonNew.click() - await this.projectTextName.click() await this.projectTextName.fill(projectTitle) await this.projectButtonContinue.click() } diff --git a/e2e/playwright/fixtures/sceneFixture.ts b/e2e/playwright/fixtures/sceneFixture.ts index 29daa9b3ae2..c054e9a087f 100644 --- a/e2e/playwright/fixtures/sceneFixture.ts +++ b/e2e/playwright/fixtures/sceneFixture.ts @@ -233,7 +233,7 @@ export class SceneFixture { settled = async (cmdBar: CmdBarFixture) => { const u = await getUtils(this.page) - await expect(this.startEditSketchBtn).not.toBeDisabled() + await expect(this.startEditSketchBtn).not.toBeDisabled({ timeout: 15_000 }) await expect(this.startEditSketchBtn).toBeVisible() await cmdBar.openCmdBar() diff --git a/e2e/playwright/prompt-to-edit-snapshot-tests.spec.ts b/e2e/playwright/prompt-to-edit-snapshot-tests.spec.ts index 11e9eb51fa6..14b102ebc7b 100644 --- a/e2e/playwright/prompt-to-edit-snapshot-tests.spec.ts +++ b/e2e/playwright/prompt-to-edit-snapshot-tests.spec.ts @@ -68,12 +68,10 @@ test.describe('edit with AI example snapshots', () => { body1CapCoords.x, body1CapCoords.y ) - const yellow: [number, number, number] = [179, 179, 131] const submittingToast = page.getByText('Submitting to Text-to-CAD API...') await test.step('wait for scene to load select body and check selection came through', async () => { await clickBody1Cap() - await scene.expectPixelColor(yellow, body1CapCoords, 20) await editor.expectState({ highlightedCode: '', activeLines: ['|>startProfileAt([-73.64,-42.89],%)'], diff --git a/e2e/playwright/snapshot-tests.spec.ts b/e2e/playwright/snapshot-tests.spec.ts index a064b763190..5295247434d 100644 --- a/e2e/playwright/snapshot-tests.spec.ts +++ b/e2e/playwright/snapshot-tests.spec.ts @@ -588,6 +588,7 @@ test( 'Draft circle should look right', { tag: '@snapshot' }, async ({ page, context, cmdBar, scene }) => { + test.fixme(orRunWhenFullSuiteEnabled()) const u = await getUtils(page) await page.setViewportSize({ width: 1200, height: 500 }) const PUR = 400 / 37.5 //pixeltoUnitRatio diff --git a/e2e/playwright/stress-test.spec.ts b/e2e/playwright/stress-test.spec.ts new file mode 100644 index 00000000000..d0beae607d9 --- /dev/null +++ b/e2e/playwright/stress-test.spec.ts @@ -0,0 +1,15 @@ +import { createProject } from '@e2e/playwright/test-utils' +import { test } from '@e2e/playwright/zoo-test' + +test.describe('Stress test', () => { + test('Create project and load stress test', async ({ + cmdBar, + scene, + page, + }, testInfo) => { + const projectName = 'stress-test-project' + // Create and load project + await createProject({ name: projectName, page }) + await scene.settled(cmdBar) + }) +}) diff --git a/src/components/CommandBar/CommandBar.tsx b/src/components/CommandBar/CommandBar.tsx index 0af977af7dc..a1613b5781d 100644 --- a/src/components/CommandBar/CommandBar.tsx +++ b/src/components/CommandBar/CommandBar.tsx @@ -14,6 +14,7 @@ import { commandBarActor, useCommandBarState, } from '@src/machines/commandBarMachine' +import toast from 'react-hot-toast' export const COMMAND_PALETTE_HOTKEY = 'mod+k' @@ -35,13 +36,23 @@ export const CommandBar = () => { commandBarActor.send({ type: 'Close' }) }, [pathname]) + /** + * if the engine connection is about to end, we don't want users + * to be able to perform commands that might require that connection, + * so we just close the command palette. + * TODO: instead, let each command control whether it is disabled, and + * don't just bail out + */ useEffect(() => { if ( - immediateState.type !== EngineConnectionStateType.ConnectionEstablished + !commandBarActor.getSnapshot().matches('Closed') && + (immediateState.type === EngineConnectionStateType.Disconnecting || + immediateState.type === EngineConnectionStateType.Disconnected) ) { commandBarActor.send({ type: 'Close' }) + toast.error('Exiting command flow because engine disconnected') } - }, [immediateState]) + }, [immediateState, commandBarActor]) // Hook up keyboard shortcuts useHotkeyWrapper([COMMAND_PALETTE_HOTKEY], () => { diff --git a/src/components/ModelingSidebar/ModelingSidebar.tsx b/src/components/ModelingSidebar/ModelingSidebar.tsx index d65fa90314e..8b0b08998b3 100644 --- a/src/components/ModelingSidebar/ModelingSidebar.tsx +++ b/src/components/ModelingSidebar/ModelingSidebar.tsx @@ -4,6 +4,7 @@ import type { MouseEventHandler } from 'react' import { useCallback, useContext, useEffect, useMemo } from 'react' import { useHotkeys } from 'react-hotkeys-hook' +import { useAppState } from '@src/AppState' import { ActionIcon } from '@src/components/ActionIcon' import type { CustomIconName } from '@src/components/CustomIcon' import { MachineManagerContext } from '@src/components/MachineManagerProvider' @@ -16,7 +17,10 @@ import { sidebarPanes } from '@src/components/ModelingSidebar/ModelingPanes' import Tooltip from '@src/components/Tooltip' import { DEV } from '@src/env' import { useModelingContext } from '@src/hooks/useModelingContext' +import { useNetworkContext } from '@src/hooks/useNetworkContext' +import { NetworkHealthState } from '@src/hooks/useNetworkStatus' import { useKclContext } from '@src/lang/KclProvider' +import { EngineConnectionStateType } from '@src/lang/std/engineConnection' import { SIDEBAR_BUTTON_SUFFIX } from '@src/lib/constants' import { isDesktop } from '@src/lib/isDesktop' import { useSettings } from '@src/machines/appMachine' @@ -52,6 +56,16 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) { : 'pointer-events-auto ' const showDebugPanel = settings.app.showDebugPanel + const { overallState, immediateState } = useNetworkContext() + const { isExecuting } = useKclContext() + const { isStreamReady } = useAppState() + const reliesOnEngine = + (overallState !== NetworkHealthState.Ok && + overallState !== NetworkHealthState.Weak) || + isExecuting || + immediateState.type !== EngineConnectionStateType.ConnectionEstablished || + !isStreamReady + const paneCallbackProps = useMemo( () => ({ kclContext, @@ -93,6 +107,8 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) { sidebarName: 'Export part', icon: 'floppyDiskArrow', keybinding: 'Ctrl + Shift + E', + disable: () => + reliesOnEngine ? 'Need engine connection to export' : undefined, action: () => commandBarActor.send({ type: 'Find and select command', diff --git a/src/routes/Onboarding/utils.tsx b/src/routes/Onboarding/utils.tsx index 7174e294e6d..0e521b1b06b 100644 --- a/src/routes/Onboarding/utils.tsx +++ b/src/routes/Onboarding/utils.tsx @@ -45,7 +45,8 @@ export function useDemoCode() { } // Don't run if the network isn't healthy or the connection isn't established if ( - overallState !== NetworkHealthState.Ok || + overallState === NetworkHealthState.Disconnected || + overallState === NetworkHealthState.Issue || immediateState.type !== EngineConnectionStateType.ConnectionEstablished ) { return