Only show "Edit sketch" button when code pane is focused with sketch selected (#5691)
* Only show "Edit sketch" button when code pane is focused with sketch selected Closes #4273. WIP until tests are updated, since this will impact many that look for the "Edit sketch" button. * Start removing "edit sketch" point-and-click from E2E * Update more E2E tests * Update more tests that assumed Edit Sketch button * A snapshot a day keeps the bugs away! 📷🐛 --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
import type { Page, Locator } from '@playwright/test'
|
import { type Page, type Locator, test } from '@playwright/test'
|
||||||
import { expect } from '../zoo-test'
|
import { expect } from '../zoo-test'
|
||||||
import {
|
import {
|
||||||
checkIfPaneIsOpen,
|
checkIfPaneIsOpen,
|
||||||
@ -76,10 +76,6 @@ export class ToolbarFixture {
|
|||||||
this.gizmoDisabled = page.getByTestId('gizmo-disabled')
|
this.gizmoDisabled = page.getByTestId('gizmo-disabled')
|
||||||
}
|
}
|
||||||
|
|
||||||
get editSketchBtn() {
|
|
||||||
return this.page.locator('[name="Edit Sketch"]')
|
|
||||||
}
|
|
||||||
|
|
||||||
get logoLink() {
|
get logoLink() {
|
||||||
return this.page.getByTestId('app-logo')
|
return this.page.getByTestId('app-logo')
|
||||||
}
|
}
|
||||||
@ -115,11 +111,20 @@ export class ToolbarFixture {
|
|||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
editSketch = async () => {
|
editSketch = async (operationIndex = 0) => {
|
||||||
await this.editSketchBtn.first().click()
|
await test.step(`Editing sketch`, async () => {
|
||||||
// One of the rare times we want to allow a arbitrary wait
|
await this.openFeatureTreePane()
|
||||||
// this is for the engine animation, as it takes 500ms to complete
|
const operation = await this.getFeatureTreeOperation(
|
||||||
await this.page.waitForTimeout(600)
|
'Sketch',
|
||||||
|
operationIndex
|
||||||
|
)
|
||||||
|
await operation.dblclick()
|
||||||
|
// One of the rare times we want to allow a arbitrary wait
|
||||||
|
// this is for the engine animation, as it takes 500ms to complete
|
||||||
|
await this.page.waitForTimeout(600)
|
||||||
|
await expect(this.exitSketchBtn).toBeEnabled()
|
||||||
|
await this.closeFeatureTreePane()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
private _getMode = () =>
|
private _getMode = () =>
|
||||||
this.page.locator('[data-current-mode]').getAttribute('data-current-mode')
|
this.page.locator('[data-current-mode]').getAttribute('data-current-mode')
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
} from './test-utils'
|
} from './test-utils'
|
||||||
import { uuidv4, roundOff } from 'lib/utils'
|
import { uuidv4, roundOff } from 'lib/utils'
|
||||||
import { SceneFixture } from './fixtures/sceneFixture'
|
import { SceneFixture } from './fixtures/sceneFixture'
|
||||||
|
import { ToolbarFixture } from './fixtures/toolbarFixture'
|
||||||
import { CmdBarFixture } from './fixtures/cmdBarFixture'
|
import { CmdBarFixture } from './fixtures/cmdBarFixture'
|
||||||
|
|
||||||
test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
||||||
@ -193,6 +194,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
homePage: HomePageFixture,
|
homePage: HomePageFixture,
|
||||||
openPanes: string[],
|
openPanes: string[],
|
||||||
scene: SceneFixture,
|
scene: SceneFixture,
|
||||||
|
toolbar: ToolbarFixture,
|
||||||
cmdBar: CmdBarFixture
|
cmdBar: CmdBarFixture
|
||||||
) => {
|
) => {
|
||||||
// Load the app with the code panes
|
// Load the app with the code panes
|
||||||
@ -282,11 +284,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
// Select the sketch
|
// Select the sketch
|
||||||
await page.mouse.click(700, 370)
|
await page.mouse.click(700, 370)
|
||||||
}
|
}
|
||||||
await expect(
|
await toolbar.editSketch()
|
||||||
page.getByRole('button', { name: 'Edit Sketch' })
|
|
||||||
).toBeVisible()
|
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
|
||||||
await page.waitForTimeout(400)
|
|
||||||
if (openPanes.includes('code')) {
|
if (openPanes.includes('code')) {
|
||||||
prevContent = await page.locator('.cm-content').innerText()
|
prevContent = await page.locator('.cm-content').innerText()
|
||||||
}
|
}
|
||||||
@ -417,7 +415,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
test(
|
test(
|
||||||
'code pane open at start-handles',
|
'code pane open at start-handles',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ page, homePage, scene, cmdBar }) => {
|
async ({ page, homePage, scene, toolbar, cmdBar }) => {
|
||||||
// Load the app with the code panes
|
// Load the app with the code panes
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -435,6 +433,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
homePage,
|
homePage,
|
||||||
['code'],
|
['code'],
|
||||||
scene,
|
scene,
|
||||||
|
toolbar,
|
||||||
cmdBar
|
cmdBar
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -443,7 +442,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
test(
|
test(
|
||||||
'code pane closed at start-handles',
|
'code pane closed at start-handles',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ page, homePage, scene, cmdBar }) => {
|
async ({ page, homePage, scene, toolbar, cmdBar }) => {
|
||||||
// Load the app with the code panes
|
// Load the app with the code panes
|
||||||
await page.addInitScript(async (persistModelingContext) => {
|
await page.addInitScript(async (persistModelingContext) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -451,7 +450,14 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
JSON.stringify({ openPanes: [] })
|
JSON.stringify({ openPanes: [] })
|
||||||
)
|
)
|
||||||
}, PERSIST_MODELING_CONTEXT)
|
}, PERSIST_MODELING_CONTEXT)
|
||||||
await doEditSegmentsByDraggingHandle(page, homePage, [], scene, cmdBar)
|
await doEditSegmentsByDraggingHandle(
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
[],
|
||||||
|
scene,
|
||||||
|
toolbar,
|
||||||
|
cmdBar
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -2545,7 +2551,7 @@ profile002 = startProfileAt([85.81, 52.55], sketch002)
|
|||||||
const [startProfileAt] = scene.makeMouseHelpers(606, 184)
|
const [startProfileAt] = scene.makeMouseHelpers(606, 184)
|
||||||
const [nextPoint] = scene.makeMouseHelpers(763, 130)
|
const [nextPoint] = scene.makeMouseHelpers(763, 130)
|
||||||
await page.getByText('startProfileAt([85.81, 52.55], sketch002)').click()
|
await page.getByText('startProfileAt([85.81, 52.55], sketch002)').click()
|
||||||
await toolbar.editSketch()
|
await toolbar.editSketch(1)
|
||||||
// timeout wait for engine animation is unavoidable
|
// timeout wait for engine animation is unavoidable
|
||||||
await page.waitForTimeout(600)
|
await page.waitForTimeout(600)
|
||||||
|
|
||||||
@ -2765,7 +2771,7 @@ extrude003 = extrude(profile011, length = 2.5)
|
|||||||
await test.step(title, async () => {
|
await test.step(title, async () => {
|
||||||
await camPositionForSelectingSketchOnWallProfiles()
|
await camPositionForSelectingSketchOnWallProfiles()
|
||||||
await selectClick()
|
await selectClick()
|
||||||
await toolbar.editSketch()
|
await toolbar.editSketch(1)
|
||||||
await page.waitForTimeout(600)
|
await page.waitForTimeout(600)
|
||||||
await verifyWallProfilesAreDrawn()
|
await verifyWallProfilesAreDrawn()
|
||||||
await toolbar.exitSketchBtn.click()
|
await toolbar.exitSketchBtn.click()
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 54 KiB |
Binary file not shown.
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
@ -83,7 +83,7 @@ test.fixme('Test network and connection issues', () => {
|
|||||||
test(
|
test(
|
||||||
'Engine disconnect & reconnect in sketch mode',
|
'Engine disconnect & reconnect in sketch mode',
|
||||||
{ tag: '@skipLocalEngine' },
|
{ tag: '@skipLocalEngine' },
|
||||||
async ({ page, homePage }) => {
|
async ({ page, homePage, toolbar }) => {
|
||||||
const networkToggle = page.getByTestId('network-toggle')
|
const networkToggle = page.getByTestId('network-toggle')
|
||||||
|
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
@ -173,11 +173,7 @@ test.fixme('Test network and connection issues', () => {
|
|||||||
.click()
|
.click()
|
||||||
|
|
||||||
// enter sketch again
|
// enter sketch again
|
||||||
await u.doAndWaitForCmd(
|
await toolbar.editSketch()
|
||||||
() => page.getByRole('button', { name: 'Edit Sketch' }).click(),
|
|
||||||
'default_camera_get_settings'
|
|
||||||
)
|
|
||||||
await page.waitForTimeout(150)
|
|
||||||
|
|
||||||
// Click the line tool
|
// Click the line tool
|
||||||
await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
||||||
@ -201,6 +197,7 @@ test.fixme('Test network and connection issues', () => {
|
|||||||
type: 'default_camera_get_settings',
|
type: 'default_camera_get_settings',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
await toolbar.openPane('debug')
|
||||||
await u.sendCustomCmd(camCommand)
|
await u.sendCustomCmd(camCommand)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await u.sendCustomCmd(updateCamCommand)
|
await u.sendCustomCmd(updateCamCommand)
|
||||||
|
@ -316,14 +316,11 @@ test.describe(`Testing gizmo, fixture-based`, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Gizmo should be disabled when in sketch mode`, async () => {
|
await test.step(`Gizmo should be disabled when in sketch mode`, async () => {
|
||||||
const sketchModeButton = page.getByRole('button', {
|
|
||||||
name: 'Edit sketch',
|
|
||||||
})
|
|
||||||
const exitSketchButton = page.getByRole('button', {
|
const exitSketchButton = page.getByRole('button', {
|
||||||
name: 'Exit sketch',
|
name: 'Exit sketch',
|
||||||
})
|
})
|
||||||
|
|
||||||
await sketchModeButton.click()
|
await toolbar.editSketch()
|
||||||
await expect(exitSketchButton).toBeVisible()
|
await expect(exitSketchButton).toBeVisible()
|
||||||
const gizmoPopoverButton = page.getByRole('button', {
|
const gizmoPopoverButton = page.getByRole('button', {
|
||||||
name: 'view settings',
|
name: 'view settings',
|
||||||
|
@ -10,6 +10,7 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
|
|||||||
test('Selections work on fresh and edited sketch', async ({
|
test('Selections work on fresh and edited sketch', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
toolbar,
|
||||||
}) => {
|
}) => {
|
||||||
// tests mapping works on fresh sketch and edited sketch
|
// tests mapping works on fresh sketch and edited sketch
|
||||||
// tests using hovers which is the same as selections, because if
|
// tests using hovers which is the same as selections, because if
|
||||||
@ -216,12 +217,7 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
|
|||||||
await emptySpaceHover()
|
await emptySpaceHover()
|
||||||
|
|
||||||
// enter sketch again
|
// enter sketch again
|
||||||
await u.doAndWaitForCmd(
|
await toolbar.editSketch()
|
||||||
() => page.getByRole('button', { name: 'Edit Sketch' }).click(),
|
|
||||||
'default_camera_get_settings'
|
|
||||||
)
|
|
||||||
|
|
||||||
await page.waitForTimeout(450) // wait for animation
|
|
||||||
|
|
||||||
await u.openAndClearDebugPanel()
|
await u.openAndClearDebugPanel()
|
||||||
await u.sendCustomCmd({
|
await u.sendCustomCmd({
|
||||||
|
@ -724,7 +724,14 @@ test.describe('Testing settings', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Changing theme in sketch mode', async ({ context, page, homePage }) => {
|
test('Changing theme in sketch mode', async ({
|
||||||
|
context,
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
toolbar,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
// TODO: fix this test on windows after the electron migration
|
// TODO: fix this test on windows after the electron migration
|
||||||
test.skip(process.platform === 'win32', 'Skip on windows')
|
test.skip(process.platform === 'win32', 'Skip on windows')
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
@ -744,11 +751,10 @@ test.describe('Testing settings', () => {
|
|||||||
})
|
})
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.settled(cmdBar)
|
||||||
await page.waitForTimeout(1000)
|
await page.waitForTimeout(1000)
|
||||||
|
|
||||||
// Selectors and constants
|
// Selectors and constants
|
||||||
const editSketchButton = page.getByRole('button', { name: 'Edit Sketch' })
|
|
||||||
const lineToolButton = page.getByTestId('line')
|
const lineToolButton = page.getByTestId('line')
|
||||||
const segmentOverlays = page.getByTestId('segment-overlay')
|
const segmentOverlays = page.getByTestId('segment-overlay')
|
||||||
const sketchOriginLocation = { x: 600, y: 250 }
|
const sketchOriginLocation = { x: 600, y: 250 }
|
||||||
@ -757,8 +763,7 @@ test.describe('Testing settings', () => {
|
|||||||
|
|
||||||
await test.step(`Get into sketch mode`, async () => {
|
await test.step(`Get into sketch mode`, async () => {
|
||||||
await page.mouse.click(700, 200)
|
await page.mouse.click(700, 200)
|
||||||
await expect(editSketchButton).toBeVisible()
|
await toolbar.editSketch()
|
||||||
await editSketchButton.click()
|
|
||||||
|
|
||||||
// We use the line tool as a proxy for sketch mode
|
// We use the line tool as a proxy for sketch mode
|
||||||
await expect(lineToolButton).toBeVisible()
|
await expect(lineToolButton).toBeVisible()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useRef, useMemo, memo, useCallback, useState } from 'react'
|
import { useRef, useMemo, memo, useCallback, useState } from 'react'
|
||||||
import { isCursorInSketchCommandRange } from 'lang/util'
|
import { isCursorInSketchCommandRange } from 'lang/util'
|
||||||
import { engineCommandManager, kclManager } from 'lib/singletons'
|
import { editorManager, engineCommandManager, kclManager } from 'lib/singletons'
|
||||||
import { useModelingContext } from 'hooks/useModelingContext'
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
import { useNetworkContext } from 'hooks/useNetworkContext'
|
import { useNetworkContext } from 'hooks/useNetworkContext'
|
||||||
import { NetworkHealthState } from 'hooks/useNetworkStatus'
|
import { NetworkHealthState } from 'hooks/useNetworkStatus'
|
||||||
@ -77,8 +77,15 @@ export function Toolbar({
|
|||||||
modelingState: state,
|
modelingState: state,
|
||||||
modelingSend: send,
|
modelingSend: send,
|
||||||
sketchPathId,
|
sketchPathId,
|
||||||
|
editorHasFocus: editorManager.editorView?.hasFocus,
|
||||||
}),
|
}),
|
||||||
[state, send, commandBarActor.send, sketchPathId]
|
[
|
||||||
|
state,
|
||||||
|
send,
|
||||||
|
commandBarActor.send,
|
||||||
|
sketchPathId,
|
||||||
|
editorManager.editorView?.hasFocus,
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
const tooltipContentClassName = !showRichContent
|
const tooltipContentClassName = !showRichContent
|
||||||
|
@ -20,6 +20,7 @@ export interface ToolbarItemCallbackProps {
|
|||||||
modelingState: StateFrom<typeof modelingMachine>
|
modelingState: StateFrom<typeof modelingMachine>
|
||||||
modelingSend: (event: EventFrom<typeof modelingMachine>) => void
|
modelingSend: (event: EventFrom<typeof modelingMachine>) => void
|
||||||
sketchPathId: string | false
|
sketchPathId: string | false
|
||||||
|
editorHasFocus: boolean | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ToolbarItem = {
|
export type ToolbarItem = {
|
||||||
@ -65,8 +66,8 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: 'sketch',
|
id: 'sketch',
|
||||||
onClick: ({ modelingSend, sketchPathId }) =>
|
onClick: ({ modelingSend, sketchPathId, editorHasFocus }) =>
|
||||||
!sketchPathId
|
!(editorHasFocus && sketchPathId)
|
||||||
? modelingSend({
|
? modelingSend({
|
||||||
type: 'Enter sketch',
|
type: 'Enter sketch',
|
||||||
data: { forceNewSketch: true },
|
data: { forceNewSketch: true },
|
||||||
@ -74,8 +75,8 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
|
|||||||
: modelingSend({ type: 'Enter sketch' }),
|
: modelingSend({ type: 'Enter sketch' }),
|
||||||
icon: 'sketch',
|
icon: 'sketch',
|
||||||
status: 'available',
|
status: 'available',
|
||||||
title: ({ sketchPathId }) =>
|
title: ({ editorHasFocus, sketchPathId }) =>
|
||||||
sketchPathId ? 'Edit Sketch' : 'Start Sketch',
|
editorHasFocus && sketchPathId ? 'Edit Sketch' : 'Start Sketch',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
hotkey: 'S',
|
hotkey: 'S',
|
||||||
description: 'Start drawing a 2D sketch',
|
description: 'Start drawing a 2D sketch',
|
||||||
|
Reference in New Issue
Block a user