Massive extinction event for waitForExecutionDone; try to stop projects view switching from crashing

This commit is contained in:
lee-at-zoo-corp
2025-03-21 19:33:59 -04:00
parent 4c9851efbf
commit fbefff490c
19 changed files with 113 additions and 106 deletions

View File

@ -15,6 +15,7 @@ test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
page, page,
homePage, homePage,
scene, scene,
cmdBar,
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
@ -36,7 +37,7 @@ extrude001 = extrude(sketch001, length = 5)`
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// Ensure no badge is present // Ensure no badge is present
const codePaneButtonHolder = page.locator('#code-button-holder') const codePaneButtonHolder = page.locator('#code-button-holder')
@ -171,6 +172,8 @@ extrude001 = extrude(sketch001, length = 5)`
context, context,
page, page,
homePage, homePage,
scene,
cmdBar,
}) => { }) => {
// Load the app with the working starter code // Load the app with the working starter code
await context.addInitScript((code) => { await context.addInitScript((code) => {
@ -180,9 +183,7 @@ extrude001 = extrude(sketch001, length = 5)`
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
// FIXME: await scene.waitForExecutionDone() does not work. It still fails. await scene.settled(cmdBar)
// I needed to increase this timeout to get this to pass.
await page.waitForTimeout(10000)
// Ensure badge is present // Ensure badge is present
const codePaneButtonHolder = page.locator('#code-button-holder') const codePaneButtonHolder = page.locator('#code-button-holder')

View File

@ -11,7 +11,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
test( test(
'export works on the first try', 'export works on the first try',
{ tag: ['@electron', '@skipLocalEngine'] }, { tag: ['@electron', '@skipLocalEngine'] },
async ({ page, context, scene, tronApp }, testInfo) => { async ({ page, context, scene, tronApp, cmdBar }, testInfo) => {
if (!tronApp) { if (!tronApp) {
fail() fail()
} }
@ -47,7 +47,8 @@ test(
const exportButton = page.getByTestId('export-pane-button') const exportButton = page.getByTestId('export-pane-button')
await expect(exportButton).toBeVisible() await expect(exportButton).toBeVisible()
await scene.waitForExecutionDone() // Wait for the model to finish loading
await scene.settled(cmdBar)
const gltfOption = page.getByText('glTF') const gltfOption = page.getByText('glTF')
const submitButton = page.getByText('Confirm Export') const submitButton = page.getByText('Confirm Export')
@ -120,8 +121,7 @@ test(
// Close the file pane // Close the file pane
await u.closeFilePanel() await u.closeFilePanel()
// FIXME: await scene.waitForExecutionDone() does not work. The modeling indicator stays in -receive-reliable and not execution done await scene.settled(cmdBar)
await page.waitForTimeout(10000)
// expect zero errors in guter // expect zero errors in guter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible() await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()

View File

@ -64,7 +64,7 @@ test.describe('Feature Tree pane', () => {
test( test(
'User can go to definition and go to function definition', 'User can go to definition and go to function definition',
{ tag: '@electron' }, { tag: '@electron' },
async ({ context, homePage, scene, editor, toolbar }) => { async ({ context, homePage, scene, editor, toolbar, cmdBar }) => {
await context.folderSetupFn(async (dir) => { await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'test-sample') const bracketDir = join(dir, 'test-sample')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
@ -86,7 +86,7 @@ test.describe('Feature Tree pane', () => {
sortBy: 'last-modified-desc', sortBy: 'last-modified-desc',
}) })
await homePage.openProject('test-sample') await homePage.openProject('test-sample')
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await editor.closePane() await editor.closePane()
await toolbar.openFeatureTreePane() await toolbar.openFeatureTreePane()
}) })
@ -254,7 +254,7 @@ test.describe('Feature Tree pane', () => {
sortBy: 'last-modified-desc', sortBy: 'last-modified-desc',
}) })
await homePage.openProject('test-sample') await homePage.openProject('test-sample')
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await toolbar.openFeatureTreePane() await toolbar.openFeatureTreePane()
}) })
@ -339,7 +339,7 @@ test.describe('Feature Tree pane', () => {
sortBy: 'last-modified-desc', sortBy: 'last-modified-desc',
}) })
await homePage.openProject('test-sample') await homePage.openProject('test-sample')
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await toolbar.openFeatureTreePane() await toolbar.openFeatureTreePane()
}) })
@ -414,8 +414,7 @@ profile003 = startProfileAt([0, -4.93], sketch001)
const planeColor: [number, number, number] = [74, 74, 74] const planeColor: [number, number, number] = [74, 74, 74]
await homePage.openProject('test-sample') await homePage.openProject('test-sample')
// FIXME: @lf94 has a better way to verify execution completion, in a PR rn await scene.settled(cmdBar)
await scene.waitForExecutionDone()
await test.step(`Verify we see the sketch`, async () => { await test.step(`Verify we see the sketch`, async () => {
await scene.expectPixelColor(sketchColor, testPoint, 10) await scene.expectPixelColor(sketchColor, testPoint, 10)

View File

@ -47,12 +47,6 @@ export class SceneFixture {
public networkToggleConnected!: Locator public networkToggleConnected!: Locator
public startEditSketchBtn!: Locator public startEditSketchBtn!: Locator
get exeIndicator() {
return this.page
.getByTestId('model-state-indicator-execution-done')
.or(this.page.getByTestId('model-state-indicator-receive-reliable'))
}
constructor(page: Page) { constructor(page: Page) {
this.page = page this.page = page
this.streamWrapper = page.getByTestId('stream') this.streamWrapper = page.getByTestId('stream')
@ -231,10 +225,6 @@ export class SceneFixture {
} }
} }
waitForExecutionDone = async () => {
await expect(this.exeIndicator).toBeVisible({ timeout: 30000 })
}
connectionEstablished = async () => { connectionEstablished = async () => {
const timeout = 30000 const timeout = 30000
await expect(this.networkToggleConnected).toBeVisible({ timeout }) await expect(this.networkToggleConnected).toBeVisible({ timeout })
@ -243,6 +233,9 @@ export class SceneFixture {
settled = async (cmdBar: CmdBarFixture) => { settled = async (cmdBar: CmdBarFixture) => {
const u = await getUtils(this.page) const u = await getUtils(this.page)
await expect(this.startEditSketchBtn).not.toBeDisabled()
await expect(this.startEditSketchBtn).toBeVisible()
await cmdBar.openCmdBar() await cmdBar.openCmdBar()
await cmdBar.chooseCommand('Settings · app · show debug panel') await cmdBar.chooseCommand('Settings · app · show debug panel')
await cmdBar.selectOption({ name: 'on' }).click() await cmdBar.selectOption({ name: 'on' }).click()
@ -250,10 +243,6 @@ export class SceneFixture {
await u.openDebugPanel() await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel() await u.closeDebugPanel()
await this.waitForExecutionDone()
await expect(this.startEditSketchBtn).not.toBeDisabled()
await expect(this.startEditSketchBtn).toBeVisible()
} }
expectPixelColor = async ( expectPixelColor = async (

View File

@ -84,12 +84,6 @@ export class ToolbarFixture {
return this.page.getByTestId('app-logo') return this.page.getByTestId('app-logo')
} }
get exeIndicator() {
return this.page
.getByTestId('model-state-indicator-receive-reliable')
.or(this.page.getByTestId('model-state-indicator-execution-done'))
}
startSketchPlaneSelection = async () => startSketchPlaneSelection = async () =>
doAndWaitForImageDiff(this.page, () => this.startSketchBtn.click(), 500) doAndWaitForImageDiff(this.page, () => this.startSketchBtn.click(), 500)
@ -173,7 +167,7 @@ export class ToolbarFixture {
) => { ) => {
await this.filePane.getByText(fileName).click() await this.filePane.getByText(fileName).click()
if (wait) { if (wait) {
await expect(this.exeIndicator).toBeVisible({ timeout: 15_000 }) await scene.settled(cmdBar)
} }
} }
selectCenterRectangle = async () => { selectCenterRectangle = async () => {

View File

@ -31,7 +31,7 @@ test.describe('Point-and-click tests', () => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217) const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217)
@ -186,6 +186,7 @@ test.describe('Point-and-click tests', () => {
editor, editor,
toolbar, toolbar,
scene, scene,
cmdBar
}) => { }) => {
const file = await fs.readFile( const file = await fs.readFile(
path.resolve( path.resolve(
@ -200,9 +201,7 @@ test.describe('Point-and-click tests', () => {
}, file) }, file)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await expect( await scene.settled(cmdBar)
page.getByTestId('model-state-indicator-receive-reliable')
).toBeVisible()
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene) const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
@ -377,6 +376,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
editor, editor,
toolbar, toolbar,
scene, scene,
cmdBar,
}) => { }) => {
const file = await fs.readFile( const file = await fs.readFile(
path.resolve( path.resolve(
@ -392,7 +392,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene) const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
@ -1579,6 +1579,7 @@ extrude001 = extrude(profile001, length = 100)
page, page,
homePage, homePage,
scene, scene,
cmdBar
}) => { }) => {
const initialCode = `sketch001 = startSketchOn(XZ) const initialCode = `sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 30) |> circle(center = [0, 0], radius = 30)
@ -1592,7 +1593,7 @@ loft001 = loft([sketch001, sketch002])
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
const testPoint = { x: 575, y: 200 } const testPoint = { x: 575, y: 200 }
@ -1687,7 +1688,7 @@ sketch002 = startSketchOn(XZ)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y) const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
@ -1826,7 +1827,7 @@ sketch002 = startSketchOn(XZ)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
const testPoint = { x: 700, y: 250 } const testPoint = { x: 700, y: 250 }
@ -2521,7 +2522,7 @@ extrude001 = extrude(sketch001, length = -12)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
}) })
// Test 1: Command bar flow with preselected edges // Test 1: Command bar flow with preselected edges
@ -2771,6 +2772,7 @@ extrude001 = extrude(sketch001, length = -12)
scene, scene,
editor, editor,
toolbar, toolbar,
cmdBar,
}) => { }) => {
// Code samples // Code samples
const initialCode = `@settings(defaultLengthUnit = in) const initialCode = `@settings(defaultLengthUnit = in)
@ -2814,7 +2816,7 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// verify modeling scene is loaded // verify modeling scene is loaded
await scene.expectPixelColor( await scene.expectPixelColor(
@ -2938,7 +2940,7 @@ extrude001 = extrude(sketch001, length = 30)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
const testPoint = { x: 575, y: 200 } const testPoint = { x: 575, y: 200 }
@ -3079,7 +3081,7 @@ extrude001 = extrude(sketch001, length = 40)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
const testPoint = { x: 580, y: 180 } const testPoint = { x: 580, y: 180 }
@ -3218,7 +3220,7 @@ extrude002 = extrude(sketch002, length = 50)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
const testPoint = { x: 580, y: 320 } const testPoint = { x: 580, y: 320 }
@ -3306,7 +3308,7 @@ profile001 = startProfileAt([-20, 20], sketch001)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await toolbar.openPane('feature-tree') await toolbar.openPane('feature-tree')
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
@ -3386,7 +3388,7 @@ sweep001 = sweep(sketch001, path = sketch002)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
const testPoint = { x: 500, y: 250 } const testPoint = { x: 500, y: 250 }
@ -3462,7 +3464,7 @@ segAng(rectangleSegmentA002),
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// select line of code // select line of code
const codeToSelecton = `segAng(rectangleSegmentA002) - 90,` const codeToSelecton = `segAng(rectangleSegmentA002) - 90,`
@ -3541,7 +3543,7 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// select line of code // select line of code
const codeToSelecton = `center = [-11.34, 10.0]` const codeToSelecton = `center = [-11.34, 10.0]`
@ -3628,7 +3630,7 @@ sketch003 = startSketchOn(extrude001, 'START')
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// select line of code // select line of code
const codeToSelecton = `center = [-0.69, 0.56]` const codeToSelecton = `center = [-0.69, 0.56]`
@ -3703,7 +3705,7 @@ extrude001 = extrude(profile001, length = 100)
}, initialCode) }, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
const testPoint = { x: 500, y: 250 } const testPoint = { x: 500, y: 250 }

View File

@ -443,7 +443,8 @@ test(
await expect(page.getByText('broken-code')).toBeVisible() await expect(page.getByText('broken-code')).toBeVisible()
await page.getByText('broken-code').click() await page.getByText('broken-code').click()
// Gotcha: You can not use scene.waitForExecutionDone() since the KCL code is going to fail // Gotcha: You can not use scene.settled() since the KCL code is going to fail
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({ await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000, timeout: 20_000,
}) })

View File

@ -63,7 +63,7 @@ test.describe('edit with AI example snapshots', () => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
const body1CapCoords = { x: 571, y: 351 } const body1CapCoords = { x: 571, y: 351 }
const [clickBody1Cap] = scene.makeMouseHelpers( const [clickBody1Cap] = scene.makeMouseHelpers(

View File

@ -61,7 +61,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
const body1CapCoords = { x: 571, y: 311 } const body1CapCoords = { x: 571, y: 311 }
const greenCheckCoords = { x: 565, y: 305 } const greenCheckCoords = { x: 565, y: 305 }
@ -156,7 +156,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
const body1CapCoords = { x: 571, y: 311 } const body1CapCoords = { x: 571, y: 311 }
const [clickBody1Cap] = scene.makeMouseHelpers( const [clickBody1Cap] = scene.makeMouseHelpers(
@ -212,7 +212,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
const submittingToast = page.getByText('Submitting to Text-to-CAD API...') const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
const successToast = page.getByText('Prompt to edit successful') const successToast = page.getByText('Prompt to edit successful')
@ -281,7 +281,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file) localStorage.setItem('persistCode', file)
}, file) }, file)
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
const submittingToast = page.getByText('Submitting to Text-to-CAD API...') const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
const successToast = page.getByText('Prompt to edit successful') const successToast = page.getByText('Prompt to edit successful')

View File

@ -762,7 +762,7 @@ plane002 = offsetPlane(XZ, offset = -2 * x)`
) )
}) })
await homePage.openProject('test-sample') await homePage.openProject('test-sample')
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 }) await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 })
const operationButton = await toolbar.getFeatureTreeOperation( const operationButton = await toolbar.getFeatureTreeOperation(
'Offset Plane', 'Offset Plane',

View File

@ -22,6 +22,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
context, context,
homePage, homePage,
scene, scene,
cmdBar,
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
const selectionsSnippets = { const selectionsSnippets = {
@ -82,7 +83,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
// wait for execution done // wait for execution done
await u.openDebugPanel() await u.openDebugPanel()
@ -108,6 +109,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
page, page,
scene, scene,
homePage, homePage,
cmdBar,
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
await page.addInitScript(async () => { await page.addInitScript(async () => {
@ -122,7 +124,7 @@ sketch001 = startSketchOn(XZ)
}) })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await scene.expectPixelColor(TEST_COLORS.WHITE, { x: 587, y: 270 }, 15) await scene.expectPixelColor(TEST_COLORS.WHITE, { x: 587, y: 270 }, 15)
@ -673,6 +675,7 @@ sketch001 = startSketchOn(XZ)
homePage, homePage,
scene, scene,
editor, editor,
cmdBar,
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
await page.addInitScript(async () => { await page.addInitScript(async () => {
@ -689,7 +692,7 @@ sketch001 = startSketchOn(XZ)
}) })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
@ -2359,7 +2362,7 @@ profile003 = circle(sketch001, center = [6.92, -4.2], radius = 3.16)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled() ).not.toBeDisabled()
@ -2965,6 +2968,7 @@ test.describe(`Click based selection don't brick the app when clicked out of ran
toolbar, toolbar,
editor, editor,
homePage, homePage,
cmdBar,
}) => { }) => {
// We seed the scene with a single offset plane // We seed the scene with a single offset plane
await context.addInitScript(() => { await context.addInitScript(() => {
@ -2982,7 +2986,7 @@ test.describe(`Click based selection don't brick the app when clicked out of ran
}) })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await test.step(`format the code`, async () => { await test.step(`format the code`, async () => {
// doesn't contain condensed version // doesn't contain condensed version
@ -3047,6 +3051,7 @@ test.describe('Redirecting to home page and back to the original file should cle
toolbar, toolbar,
editor, editor,
homePage, homePage,
cmdBar,
}) => { }) => {
// We seed the scene with a single offset plane // We seed the scene with a single offset plane
await context.addInitScript(() => { await context.addInitScript(() => {
@ -3059,7 +3064,7 @@ test.describe('Redirecting to home page and back to the original file should cle
) )
}) })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
const [objClick] = scene.makeMouseHelpers(634, 274) const [objClick] = scene.makeMouseHelpers(634, 274)
await objClick() await objClick()

View File

@ -1129,7 +1129,7 @@ test.describe('Electron constraint tests', () => {
sortBy: 'last-modified-desc', sortBy: 'last-modified-desc',
}) })
await homePage.openProject('test-sample') await homePage.openProject('test-sample')
await scene.waitForExecutionDone() await scene.settled(cmdBar)
}) })
async function clickOnFirstSegmentLabel() { async function clickOnFirstSegmentLabel() {

View File

@ -528,6 +528,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({ test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
page, page,
homePage, homePage,
scene,
cmdBar,
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => { await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
@ -779,11 +781,7 @@ part001 = startSketchOn(XZ)
) )
`) `)
await expect( await scene.settled(cmdBar)
page
.getByTestId('model-state-indicator-receive-reliable')
.or(page.getByTestId('model-state-indicator-execution-done'))
).toBeVisible()
await u.openAndClearDebugPanel() await u.openAndClearDebugPanel()
await u.sendCustomCmd({ await u.sendCustomCmd({
@ -953,6 +951,7 @@ part001 = startSketchOn(XZ)
page, page,
homePage, homePage,
scene, scene,
cmdBar,
}) => { }) => {
const cases = [ const cases = [
{ {
@ -989,7 +988,7 @@ part001 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await u.openAndClearDebugPanel() await u.openAndClearDebugPanel()
await u.sendCustomCmd({ await u.sendCustomCmd({
@ -1024,6 +1023,7 @@ part001 = startSketchOn(XZ)
page, page,
homePage, homePage,
scene, scene,
cmdBar,
}) => { }) => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
@ -1043,7 +1043,7 @@ part001 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await scene.waitForExecutionDone() await scene.settled(cmdBar)
await u.openAndClearDebugPanel() await u.openAndClearDebugPanel()
await u.sendCustomCmd({ await u.sendCustomCmd({

View File

@ -145,6 +145,14 @@ export function App() {
} }
}, [lastCommandType]) }, [lastCommandType])
useEffect(() => {
// When leaving the modeling scene, cut the engine stream.
return () => {
engineStreamActor.send({ type: EngineStreamTransition.Pause })
console.log('engineStreamActor cleanup')
}
}, [])
return ( return (
<div className="relative h-full flex flex-col" ref={ref}> <div className="relative h-full flex flex-col" ref={ref}>
<AppHeader <AppHeader

View File

@ -26,7 +26,7 @@ export const ModelStateIndicator = () => {
className += 'text-secondary' className += 'text-secondary'
icon = ( icon = (
<FontAwesomeIcon <FontAwesomeIcon
data-testid={dataTestId + '-execution-done'} data-testid={dataTestId + '-playing'}
icon={faPlay} icon={faPlay}
width="20" width="20"
height="20" height="20"

View File

@ -90,6 +90,7 @@ export const KclEditorPane = () => {
return () => { return () => {
kclEditorActor.send({ type: 'setKclEditorMounted', data: false }) kclEditorActor.send({ type: 'setKclEditorMounted', data: false })
kclEditorActor.send({ type: 'setLastSelectionEvent', data: undefined }) kclEditorActor.send({ type: 'setLastSelectionEvent', data: undefined })
console.log('kclEditorActor cleanup')
} }
}, []) }, [])

View File

@ -305,6 +305,8 @@ class EngineConnection extends EventTarget {
) )
isUsingConnectionLite: boolean = false isUsingConnectionLite: boolean = false
timeoutToForceConnectId: ReturnType<typeof setTimeout> = setTimeout(() => {}, 3000)
constructor({ constructor({
engineCommandManager, engineCommandManager,
url, url,
@ -595,7 +597,7 @@ class EngineConnection extends EventTarget {
// Sometimes the remote end doesn't report the end of candidates. // Sometimes the remote end doesn't report the end of candidates.
// They have 3 seconds to. // They have 3 seconds to.
setTimeout(() => { this.timeoutToForceConnectId = setTimeout(() => {
if (that.initiateConnectionExclusive()) { if (that.initiateConnectionExclusive()) {
console.warn('connected after 3 second delay') console.warn('connected after 3 second delay')
} }
@ -1192,6 +1194,8 @@ class EngineConnection extends EventTarget {
) )
} }
disconnectAll() { disconnectAll() {
clearTimeout(this.timeoutToForceConnectId)
if (this.websocket?.readyState === 1) { if (this.websocket?.readyState === 1) {
this.websocket?.close() this.websocket?.close()
} }

View File

@ -213,7 +213,7 @@ export function createSettings() {
streamIdleMode: new Setting<number | undefined>({ streamIdleMode: new Setting<number | undefined>({
defaultValue: undefined, defaultValue: undefined,
hideOnLevel: 'project', hideOnLevel: 'project',
description: 'Toggle stream idling, saving bandwidth and battery', description: 'Save bandwidth & battery',
validate: (v) => validate: (v) =>
v === undefined || v === undefined ||
(typeof v === 'number' && (typeof v === 'number' &&
@ -239,34 +239,32 @@ export function createSettings() {
} }
return ( return (
<div className="flex item-center gap-4 px-2 m-0 py-0"> <div className="flex item-center gap-4 m-0 py-0">
<div className="flex flex-col"> <Toggle
<input offLabel="Off"
type="checkbox" onLabel="On"
checked={settingValueInStorage !== undefined} checked={settingValueInStorage !== undefined}
onChange={(event) => { onChange={(event) => {
if (timeoutId) { if (timeoutId) {
return return
} }
const isChecked = event.currentTarget.checked const isChecked = event.currentTarget.checked
clearTimeout(timeoutId) clearTimeout(timeoutId)
setTimeoutId( setTimeoutId(
setTimeout(() => { setTimeout(() => {
const requested = !isChecked ? undefined : 5 const requested = !isChecked ? undefined : 5
setPreview(requested) setPreview(requested)
writeSettingValueToStorage( writeSettingValueToStorage(
requested === undefined requested === undefined
? undefined ? undefined
: Number(requested) * MS_IN_MINUTE : Number(requested) * MS_IN_MINUTE
) )
setTimeoutId(undefined) setTimeoutId(undefined)
}, 100) }, 100)
) )
}} }}
className="block w-4 h-4" className="block w-4 h-4"
/> />
<div></div>
</div>
<div className="flex flex-col grow"> <div className="flex flex-col grow">
<input <input
type="range" type="range"

View File

@ -297,11 +297,16 @@ export const engineStreamMachine = setup({
}, },
}, },
[EngineStreamState.Resuming]: { [EngineStreamState.Resuming]: {
reenter: true,
invoke: { invoke: {
src: EngineStreamTransition.StartOrReconfigureEngine, src: EngineStreamTransition.StartOrReconfigureEngine,
input: (args) => args, input: (args) => args,
}, },
on: { on: {
// The stream can be paused as it's resuming.
[EngineStreamTransition.Pause]: {
target: EngineStreamState.Paused,
},
[EngineStreamTransition.SetMediaStream]: { [EngineStreamTransition.SetMediaStream]: {
actions: [ actions: [
assign({ mediaStream: ({ context, event }) => event.mediaStream }), assign({ mediaStream: ({ context, event }) => event.mediaStream }),