* Submit selection to command on unmount of selection arg input This fixes #7024 by saving the user's selection to the command even if they click another argument in the command palette's header. It does no harm to save the selection to the argument, even if it's being torn down because the user dismissed it has no negative effect. * Refactor to not auto-submit before selection is cleared on mount Thanks E2E test suite * Update failing E2E tests with new behavior, which allows skip with preselection --------- Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
4838 lines
160 KiB
TypeScript
4838 lines
160 KiB
TypeScript
import fs from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import type { Locator, Page } from '@playwright/test'
|
|
|
|
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
|
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
|
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
|
import { bracket } from '@e2e/playwright/fixtures/bracket'
|
|
|
|
// test file is for testing point an click code gen functionality that's not sketch mode related
|
|
|
|
test.describe('Point-and-click tests', () => {
|
|
test('verify extruding circle works', async ({
|
|
page,
|
|
context,
|
|
homePage,
|
|
cmdBar,
|
|
editor,
|
|
toolbar,
|
|
scene,
|
|
}) => {
|
|
const file = await fs.readFile(
|
|
path.resolve(
|
|
__dirname,
|
|
'../../',
|
|
'./rust/kcl-lib/e2e/executor/inputs/test-circle-extrude.kcl'
|
|
),
|
|
'utf-8'
|
|
)
|
|
await context.addInitScript((file) => {
|
|
localStorage.setItem('persistCode', file)
|
|
}, file)
|
|
|
|
await homePage.goToModelingScene()
|
|
await scene.connectionEstablished()
|
|
|
|
const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217)
|
|
|
|
await test.step('because there is sweepable geometry, verify extrude is enable when nothing is selected', async () => {
|
|
// FIXME: Do not click, clicking removes the activeLines in future checks
|
|
// await scene.clickNoWhere()
|
|
await expect(toolbar.extrudeButton).toBeEnabled()
|
|
})
|
|
|
|
await test.step('check code model connection works and that button is still enable once circle is selected ', async () => {
|
|
await moveToCircle()
|
|
const circleSnippet = 'circle(center = [318.33, 168.1], radius = 182.8)'
|
|
await editor.expectState({
|
|
activeLines: ['sketch002=startSketchOn(XZ)'],
|
|
highlightedCode: circleSnippet,
|
|
diagnostics: [],
|
|
})
|
|
|
|
await test.step('check code model connection works and that button is still enable once circle is selected ', async () => {
|
|
await moveToCircle()
|
|
const circleSnippet = 'circle(center = [318.33, 168.1], radius = 182.8)'
|
|
await editor.expectState({
|
|
activeLines: ['sketch002=startSketchOn(XZ)'],
|
|
highlightedCode: circleSnippet,
|
|
diagnostics: [],
|
|
})
|
|
|
|
await clickCircle()
|
|
await editor.expectState({
|
|
activeLines: ['|>' + circleSnippet],
|
|
highlightedCode: circleSnippet,
|
|
diagnostics: [],
|
|
})
|
|
await expect(toolbar.extrudeButton).toBeEnabled()
|
|
})
|
|
await expect(toolbar.extrudeButton).toBeEnabled()
|
|
})
|
|
|
|
await test.step('do extrude flow and check extrude code is added to editor', async () => {
|
|
await toolbar.extrudeButton.click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'length',
|
|
currentArgValue: '5',
|
|
headerArguments: { Profiles: '1 profile', Length: '' },
|
|
highlightedHeaderArg: 'length',
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
|
|
const expectString = 'extrude001 = extrude(sketch001, length = 5)'
|
|
await editor.expectEditor.not.toContain(expectString)
|
|
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: { Profiles: '1 profile', Length: '5' },
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await editor.expectEditor.toContain(expectString)
|
|
})
|
|
})
|
|
|
|
test('Verify in-pipe extrudes in bracket can be edited', async ({
|
|
tronApp,
|
|
context,
|
|
editor,
|
|
homePage,
|
|
page,
|
|
scene,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, bracket)
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
await test.step(`Edit first extrude via feature tree`, async () => {
|
|
await (await toolbar.getFeatureTreeOperation('Extrude', 0)).dblclick()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'length',
|
|
currentArgValue: 'width',
|
|
headerArguments: {
|
|
Length: '5',
|
|
},
|
|
highlightedHeaderArg: 'length',
|
|
commandName: 'Extrude',
|
|
})
|
|
await page.keyboard.insertText('width - 0.001')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Length: '4.999',
|
|
},
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await editor.expectEditor.toContain('extrude(length = width - 0.001)')
|
|
})
|
|
|
|
await test.step(`Edit second extrude via feature tree`, async () => {
|
|
await (await toolbar.getFeatureTreeOperation('Extrude', 1)).dblclick()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'length',
|
|
currentArgValue: '-thickness - .01',
|
|
headerArguments: {
|
|
Length: '-0.3949',
|
|
},
|
|
highlightedHeaderArg: 'length',
|
|
commandName: 'Extrude',
|
|
})
|
|
await page.keyboard.insertText('-thickness - .01 - 0.001')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Length: '-0.3959',
|
|
},
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await editor.expectEditor.toContain(
|
|
'extrude(length = -thickness - .01 - 0.001)'
|
|
)
|
|
})
|
|
|
|
await test.step(`Edit third extrude via feature tree`, async () => {
|
|
await (await toolbar.getFeatureTreeOperation('Extrude', 2)).dblclick()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'length',
|
|
currentArgValue: '-thickness - 0.1',
|
|
headerArguments: {
|
|
Length: '-0.4849',
|
|
},
|
|
highlightedHeaderArg: 'length',
|
|
commandName: 'Extrude',
|
|
})
|
|
await page.keyboard.insertText('-thickness - 0.1 - 0.001')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Length: '-0.4859',
|
|
},
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await editor.expectEditor.toContain(
|
|
'extrude(length = -thickness - 0.1 - 0.001)'
|
|
)
|
|
})
|
|
})
|
|
|
|
test.describe('verify sketch on chamfer works', () => {
|
|
const _sketchOnAChamfer =
|
|
(
|
|
page: Page,
|
|
editor: EditorFixture,
|
|
toolbar: ToolbarFixture,
|
|
scene: SceneFixture
|
|
) =>
|
|
async ({
|
|
clickCoords,
|
|
cameraPos,
|
|
cameraTarget,
|
|
beforeChamferSnippet,
|
|
afterChamferSelectSnippet,
|
|
afterRectangle1stClickSnippet,
|
|
afterRectangle2ndClickSnippet,
|
|
beforeChamferSnippetEnd,
|
|
}: {
|
|
clickCoords: { x: number; y: number }
|
|
cameraPos: { x: number; y: number; z: number }
|
|
cameraTarget: { x: number; y: number; z: number }
|
|
beforeChamferSnippet: string
|
|
afterChamferSelectSnippet: string
|
|
afterRectangle1stClickSnippet: string
|
|
afterRectangle2ndClickSnippet: string
|
|
beforeChamferSnippetEnd?: string
|
|
}) => {
|
|
const [clickChamfer] = scene.makeMouseHelpers(
|
|
clickCoords.x,
|
|
clickCoords.y
|
|
)
|
|
const [rectangle1stClick] = scene.makeMouseHelpers(573, 149)
|
|
const [rectangle2ndClick, rectangle2ndMove] = scene.makeMouseHelpers(
|
|
598,
|
|
380,
|
|
{ steps: 5 }
|
|
)
|
|
|
|
await scene.moveCameraTo(cameraPos, cameraTarget)
|
|
|
|
await test.step('check chamfer selection changes cursor position', async () => {
|
|
await toolbar.waitForFeatureTreeToBeBuilt()
|
|
await expect(async () => {
|
|
// sometimes initial click doesn't register
|
|
await clickChamfer()
|
|
// await editor.expectActiveLinesToBe([beforeChamferSnippet.slice(-5)])
|
|
await editor.expectActiveLinesToBe([
|
|
beforeChamferSnippetEnd || beforeChamferSnippet.slice(-5),
|
|
])
|
|
}).toPass({ timeout: 15_000, intervals: [500] })
|
|
})
|
|
|
|
await test.step('starting a new and selecting a chamfer should animate to the new sketch and possible break up the initial chamfer if it had one than more tag', async () => {
|
|
await toolbar.startSketchPlaneSelection()
|
|
await clickChamfer()
|
|
// timeout wait for engine animation is unavoidable
|
|
await page.waitForTimeout(1000)
|
|
await editor.expectEditor.toContain(afterChamferSelectSnippet)
|
|
})
|
|
await test.step('make sure a basic sketch can be added', async () => {
|
|
await toolbar.rectangleBtn.click()
|
|
await rectangle1stClick()
|
|
await editor.expectEditor.toContain(afterRectangle1stClickSnippet)
|
|
await rectangle2ndMove({
|
|
pixelDiff: 50,
|
|
})
|
|
await rectangle2ndClick()
|
|
await editor.expectEditor.toContain(afterRectangle2ndClickSnippet, {
|
|
shouldNormalise: true,
|
|
})
|
|
})
|
|
|
|
await test.step('Clean up so that `_sketchOnAChamfer` util can be called again', async () => {
|
|
await toolbar.exitSketch()
|
|
})
|
|
await test.step('Check there is no errors after code created in previous steps executes', async () => {
|
|
await editor.expectState({
|
|
activeLines: ['@settings(defaultLengthUnit = in)'],
|
|
highlightedCode: '',
|
|
diagnostics: [],
|
|
})
|
|
await toolbar.waitForFeatureTreeToBeBuilt()
|
|
})
|
|
}
|
|
test('works on all edge selections and can break up multi edges in a chamfer array', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
editor,
|
|
toolbar,
|
|
scene,
|
|
cmdBar,
|
|
}) => {
|
|
const file = await fs.readFile(
|
|
path.resolve(
|
|
__dirname,
|
|
'../../',
|
|
'./rust/kcl-lib/e2e/executor/inputs/e2e-can-sketch-on-chamfer.kcl'
|
|
),
|
|
'utf-8'
|
|
)
|
|
await context.addInitScript((file) => {
|
|
localStorage.setItem('persistCode', file)
|
|
}, file)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
|
|
|
|
await sketchOnAChamfer({
|
|
clickCoords: { x: 570, y: 220 },
|
|
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
|
cameraTarget: { x: -150, y: -4500, z: -80 },
|
|
beforeChamferSnippet: `angledLine(angle=segAng(rectangleSegmentA001)-90,length=217.26,tag=$seg01)
|
|
chamfer(length = 30,tags = [
|
|
seg01,
|
|
getNextAdjacentEdge(yo),
|
|
getNextAdjacentEdge(seg02),
|
|
getOppositeEdge(seg01)
|
|
],
|
|
)`,
|
|
|
|
afterChamferSelectSnippet:
|
|
'sketch002 = startSketchOn(extrude001, face = seg03)',
|
|
afterRectangle1stClickSnippet:
|
|
'startProfile(sketch002, at = [205.96, 254.59])',
|
|
afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.39,tag=$rectangleSegmentA002)
|
|
|>angledLine(angle=segAng(rectangleSegmentA002)-90,length=105.26)
|
|
|>angledLine(angle=segAng(rectangleSegmentA002),length=-segLen(rectangleSegmentA002))
|
|
|>line(endAbsolute=[profileStartX(%),profileStartY(%)])
|
|
|>close()`,
|
|
})
|
|
|
|
await sketchOnAChamfer({
|
|
clickCoords: { x: 690, y: 250 },
|
|
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
|
cameraTarget: { x: -150, y: -4500, z: -80 },
|
|
beforeChamferSnippet: `angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 217.26, tag = $seg01)chamfer(
|
|
length = 30,
|
|
tags = [
|
|
seg01,
|
|
getNextAdjacentEdge(yo),
|
|
getNextAdjacentEdge(seg02)
|
|
]
|
|
)`,
|
|
|
|
afterChamferSelectSnippet:
|
|
'sketch003 = startSketchOn(extrude001, face = seg04)',
|
|
afterRectangle1stClickSnippet:
|
|
'startProfile(sketch003, at = [-209.64, 255.28])',
|
|
afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.56,tag=$rectangleSegmentA003)
|
|
|>angledLine(angle=segAng(rectangleSegmentA003)-90,length=106.84)
|
|
|>angledLine(angle=segAng(rectangleSegmentA003),length=-segLen(rectangleSegmentA003))
|
|
|>line(endAbsolute=[profileStartX(%),profileStartY(%)])
|
|
|>close()`,
|
|
})
|
|
|
|
await sketchOnAChamfer({
|
|
clickCoords: { x: 677, y: 87 },
|
|
cameraPos: { x: -6200, y: 1500, z: 6200 },
|
|
cameraTarget: { x: 8300, y: 1100, z: 4800 },
|
|
beforeChamferSnippet: `angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001)chamfer(
|
|
length = 30,
|
|
tags = [
|
|
getNextAdjacentEdge(yo),
|
|
getNextAdjacentEdge(seg02)
|
|
]
|
|
)`,
|
|
afterChamferSelectSnippet:
|
|
'sketch004 = startSketchOn(extrude001, face = seg05)',
|
|
afterRectangle1stClickSnippet:
|
|
'startProfile(sketch004, at = [82.57, 322.96])',
|
|
afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.16,tag=$rectangleSegmentA004)
|
|
|>angledLine(angle=segAng(rectangleSegmentA004)-90,length=103.07)
|
|
|>angledLine(angle=segAng(rectangleSegmentA004),length=-segLen(rectangleSegmentA004))
|
|
|>line(endAbsolute=[profileStartX(%),profileStartY(%)])
|
|
|>close()`,
|
|
})
|
|
/// last one
|
|
await sketchOnAChamfer({
|
|
clickCoords: { x: 620, y: 300 },
|
|
cameraPos: { x: -1100, y: -7700, z: 1600 },
|
|
cameraTarget: { x: 1450, y: 670, z: 4000 },
|
|
beforeChamferSnippet: `chamfer(length = 30, tags = [getNextAdjacentEdge(yo)])`,
|
|
beforeChamferSnippetEnd:
|
|
'|> chamfer(length = 30, tags = [getNextAdjacentEdge(yo)])',
|
|
afterChamferSelectSnippet:
|
|
'sketch005 = startSketchOn(extrude001, face = seg06)',
|
|
afterRectangle1stClickSnippet:
|
|
'startProfile(sketch005, at = [-23.43, 19.69])',
|
|
afterRectangle2ndClickSnippet: `angledLine(angle=0,length=9.1,tag=$rectangleSegmentA005)
|
|
|>angledLine(angle=segAng(rectangleSegmentA005)-90,length=84.07)
|
|
|>angledLine(angle=segAng(rectangleSegmentA005),length=-segLen(rectangleSegmentA005))
|
|
|>line(endAbsolute=[profileStartX(%),profileStartY(%)])
|
|
|>close()`,
|
|
})
|
|
|
|
await test.step('verify at the end of the test that final code is what is expected', async () => {
|
|
await editor.expectEditor.toContain(
|
|
`@settings(defaultLengthUnit = in)
|
|
|
|
sketch001 = startSketchOn(XZ)
|
|
|> startProfile(at = [75.8, 317.2]) // [$startCapTag, $EndCapTag]
|
|
|> angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 217.26, tag = $seg01)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $yo)
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|
|
|> close()
|
|
extrude001 = extrude(sketch001, length = 100)
|
|
|> chamfer(length = 30, tags = [getOppositeEdge(seg01)], tag = $seg03)
|
|
|> chamfer(length = 30, tags = [seg01], tag = $seg04)
|
|
|> chamfer(length = 30, tags = [getNextAdjacentEdge(seg02)], tag = $seg05)
|
|
|> chamfer(length = 30, tags = [getNextAdjacentEdge(yo)], tag = $seg06)
|
|
sketch002 = startSketchOn(extrude001, face = seg03)
|
|
profile001 = startProfile(sketch002, at = [205.96, 254.59])
|
|
|> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002)
|
|
|> angledLine(angle = segAng(rectangleSegmentA002) - 90, length = 105.26)
|
|
|> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002))
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
sketch003 = startSketchOn(extrude001, face = seg04)
|
|
profile002 = startProfile(sketch003, at = [-209.64, 255.28])
|
|
|> angledLine(angle = 0, length = 11.56, tag = $rectangleSegmentA003)
|
|
|> angledLine(angle = segAng(rectangleSegmentA003) - 90, length = 106.84)
|
|
|> angledLine(angle = segAng(rectangleSegmentA003), length = -segLen(rectangleSegmentA003))
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
sketch004 = startSketchOn(extrude001, face = seg05)
|
|
profile003 = startProfile(sketch004, at = [82.57, 322.96])
|
|
|> angledLine(angle = 0, length = 11.16, tag = $rectangleSegmentA004)
|
|
|> angledLine(angle = segAng(rectangleSegmentA004) - 90, length = 103.07)
|
|
|> angledLine(angle = segAng(rectangleSegmentA004), length = -segLen(rectangleSegmentA004))
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
sketch005 = startSketchOn(extrude001, face = seg06)
|
|
profile004 = startProfile(sketch005, at = [-23.43, 19.69])
|
|
|> angledLine(angle = 0, length = 9.1, tag = $rectangleSegmentA005)
|
|
|> angledLine(angle = segAng(rectangleSegmentA005) - 90, length = 84.07)
|
|
|> angledLine(angle = segAng(rectangleSegmentA005), length = -segLen(rectangleSegmentA005))
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
})
|
|
})
|
|
|
|
test('Works on chamfers that are not in a pipeExpression can break up multi edges in a chamfer array', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
editor,
|
|
toolbar,
|
|
scene,
|
|
cmdBar,
|
|
}) => {
|
|
const file = await fs.readFile(
|
|
path.resolve(
|
|
__dirname,
|
|
'../../',
|
|
'./rust/kcl-lib/e2e/executor/inputs/e2e-can-sketch-on-chamfer-no-pipeExpr.kcl'
|
|
),
|
|
'utf-8'
|
|
)
|
|
await context.addInitScript((file) => {
|
|
localStorage.setItem('persistCode', file)
|
|
}, file)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
|
|
|
|
await sketchOnAChamfer({
|
|
clickCoords: { x: 570, y: 220 },
|
|
cameraPos: { x: 16020, y: -2000, z: 10500 },
|
|
cameraTarget: { x: -150, y: -4500, z: -80 },
|
|
beforeChamferSnippet: `angledLine(angle=segAng(rectangleSegmentA001)-90,length=217.26,tag=$seg01)
|
|
chamfer(extrude001,length=30,tags=[
|
|
seg01,
|
|
getNextAdjacentEdge(yo),
|
|
getNextAdjacentEdge(seg02),
|
|
getOppositeEdge(seg01),
|
|
])`,
|
|
beforeChamferSnippetEnd: ')',
|
|
afterChamferSelectSnippet:
|
|
'sketch002 = startSketchOn(extrude001, face = seg03)',
|
|
afterRectangle1stClickSnippet:
|
|
'startProfile(sketch002, at = [205.96, 254.59])',
|
|
afterRectangle2ndClickSnippet: `angledLine(angle=0,length=11.39,tag=$rectangleSegmentA002)
|
|
|>angledLine(angle=segAng(rectangleSegmentA002)-90,length=105.26)
|
|
|>angledLine(angle=segAng(rectangleSegmentA002),length=-segLen(rectangleSegmentA002))
|
|
|>line(endAbsolute=[profileStartX(%),profileStartY(%)])
|
|
|>close()`,
|
|
})
|
|
await editor.expectEditor.toContain(
|
|
`@settings(defaultLengthUnit = in)
|
|
sketch001 = startSketchOn(XZ)
|
|
|> startProfile(at = [75.8, 317.2])
|
|
|> angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 217.26, tag = $seg01)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $yo)
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|
|
|> close()
|
|
extrude001 = extrude(sketch001, length = 100)
|
|
chamf = chamfer(
|
|
extrude001,
|
|
length = 30,
|
|
tags = [getOppositeEdge(seg01)],
|
|
tag = $seg03,
|
|
)
|
|
|> chamfer(
|
|
length = 30,
|
|
tags = [
|
|
seg01,
|
|
getNextAdjacentEdge(yo),
|
|
getNextAdjacentEdge(seg02)
|
|
],
|
|
)
|
|
sketch002 = startSketchOn(extrude001, face = seg03)
|
|
profile001 = startProfile(sketch002, at = [205.96, 254.59])
|
|
|> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002)
|
|
|> angledLine(angle = segAng(rectangleSegmentA002) - 90, length = 105.26)
|
|
|> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002))
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
})
|
|
})
|
|
|
|
test(`Verify axis, origin, and horizontal snapping`, async ({
|
|
page,
|
|
homePage,
|
|
editor,
|
|
toolbar,
|
|
scene,
|
|
}) => {
|
|
const viewPortSize = { width: 1200, height: 500 }
|
|
|
|
await page.setBodyDimensions(viewPortSize)
|
|
|
|
await homePage.goToModelingScene()
|
|
await scene.connectionEstablished()
|
|
|
|
// Constants and locators
|
|
// These are mappings from screenspace to KCL coordinates,
|
|
// until we merge in our coordinate system helpers
|
|
const xzPlane = [
|
|
viewPortSize.width * 0.65,
|
|
viewPortSize.height * 0.3,
|
|
] as const
|
|
const originSloppy = {
|
|
screen: [
|
|
viewPortSize.width / 2 + 3, // 3px off the center of the screen
|
|
viewPortSize.height / 2,
|
|
],
|
|
kcl: [0, 0],
|
|
} as const
|
|
const xAxisSloppy = {
|
|
screen: [
|
|
viewPortSize.width * 0.75,
|
|
viewPortSize.height / 2 - 3, // 3px off the X-axis
|
|
],
|
|
kcl: [20.34, 0],
|
|
} as const
|
|
const offYAxis = {
|
|
screen: [
|
|
viewPortSize.width * 0.6, // Well off the Y-axis, out of snapping range
|
|
viewPortSize.height * 0.3,
|
|
],
|
|
kcl: [8.14, 6.78],
|
|
} as const
|
|
const yAxisSloppy = {
|
|
screen: [
|
|
viewPortSize.width / 2 + 5, // 5px off the Y-axis
|
|
viewPortSize.height * 0.3,
|
|
],
|
|
kcl: [0, 6.78],
|
|
} as const
|
|
const [clickOnXzPlane, moveToXzPlane] = scene.makeMouseHelpers(...xzPlane)
|
|
const [clickOriginSloppy] = scene.makeMouseHelpers(...originSloppy.screen)
|
|
const [clickXAxisSloppy, moveXAxisSloppy] = scene.makeMouseHelpers(
|
|
...xAxisSloppy.screen
|
|
)
|
|
const [dragToOffYAxis, dragFromOffAxis] = scene.makeDragHelpers(
|
|
...offYAxis.screen
|
|
)
|
|
|
|
const expectedCodeSnippets = {
|
|
sketchOnXzPlane: `sketch001 = startSketchOn(XZ)`,
|
|
pointAtOrigin: `startProfile(sketch001, at = [${originSloppy.kcl[0]}, ${originSloppy.kcl[1]}])`,
|
|
segmentOnXAxis: `xLine(length = ${xAxisSloppy.kcl[0]})`,
|
|
afterSegmentDraggedOffYAxis: `startProfile(sketch001, at = [${offYAxis.kcl[0]}, ${offYAxis.kcl[1]}])`,
|
|
afterSegmentDraggedOnYAxis: `startProfile(sketch001, at = [${yAxisSloppy.kcl[0]}, ${yAxisSloppy.kcl[1]}])`,
|
|
}
|
|
|
|
await test.step(`Start a sketch on the XZ plane`, async () => {
|
|
await editor.closePane()
|
|
await toolbar.startSketchPlaneSelection()
|
|
await moveToXzPlane()
|
|
await clickOnXzPlane()
|
|
await toolbar.waitUntilSketchingReady()
|
|
await editor.expectEditor.toContain(expectedCodeSnippets.sketchOnXzPlane)
|
|
})
|
|
await test.step(`Place a point a few pixels off the middle, verify it still snaps to 0,0`, async () => {
|
|
await clickOriginSloppy()
|
|
await editor.expectEditor.toContain(expectedCodeSnippets.pointAtOrigin)
|
|
})
|
|
await test.step(`Add a segment on x-axis after moving the mouse a bit, verify it snaps`, async () => {
|
|
await moveXAxisSloppy()
|
|
await clickXAxisSloppy()
|
|
await editor.expectEditor.toContain(expectedCodeSnippets.segmentOnXAxis)
|
|
})
|
|
await test.step(`Unequip line tool`, async () => {
|
|
await toolbar.lineBtn.click()
|
|
await expect(toolbar.lineBtn).not.toHaveAttribute('aria-pressed', 'true')
|
|
})
|
|
await test.step(`Drag the origin point up and to the right, verify it's past snapping`, async () => {
|
|
await dragToOffYAxis({
|
|
fromPoint: { x: originSloppy.screen[0], y: originSloppy.screen[1] },
|
|
})
|
|
await editor.expectEditor.toContain(
|
|
expectedCodeSnippets.afterSegmentDraggedOffYAxis
|
|
)
|
|
})
|
|
await test.step(`Drag the origin point left to the y-axis, verify it snaps back`, async () => {
|
|
await dragFromOffAxis({
|
|
toPoint: { x: yAxisSloppy.screen[0], y: yAxisSloppy.screen[1] },
|
|
})
|
|
await editor.expectEditor.toContain(
|
|
expectedCodeSnippets.afterSegmentDraggedOnYAxis
|
|
)
|
|
})
|
|
await editor.page.waitForTimeout(1000)
|
|
})
|
|
|
|
test(`Verify user can double-click to edit a sketch`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
editor,
|
|
toolbar,
|
|
scene,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `closedSketch = startSketchOn(XZ)
|
|
|> circle(center = [8, 5], radius = 2)
|
|
openSketch = startSketchOn(XY)
|
|
|> startProfile(at = [-5, 0])
|
|
|> line(endAbsolute = [0, 5])
|
|
|> xLine(length = 5)
|
|
|> tangentialArc(endAbsolute = [10, 0])
|
|
`
|
|
const viewPortSize = { width: 1000, height: 500 }
|
|
await page.setBodyDimensions(viewPortSize)
|
|
|
|
await context.addInitScript((code) => {
|
|
localStorage.setItem('persistCode', code)
|
|
}, initialCode)
|
|
|
|
await homePage.goToModelingScene()
|
|
|
|
const pointInsideCircle = {
|
|
x: viewPortSize.width * 0.63,
|
|
y: viewPortSize.height * 0.5,
|
|
}
|
|
const pointOnPathAfterSketching = {
|
|
x: viewPortSize.width * 0.65,
|
|
y: viewPortSize.height * 0.5,
|
|
}
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
const [_clickOpenPath, moveToOpenPath, dblClickOpenPath] =
|
|
scene.makeMouseHelpers(
|
|
pointOnPathAfterSketching.x,
|
|
pointOnPathAfterSketching.y
|
|
)
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
const [_clickCircle, moveToCircle, dblClickCircle] = scene.makeMouseHelpers(
|
|
pointInsideCircle.x,
|
|
pointInsideCircle.y
|
|
)
|
|
|
|
const exitSketch = async () => {
|
|
await test.step(`Exit sketch mode`, async () => {
|
|
await toolbar.exitSketchBtn.click()
|
|
await expect(toolbar.startSketchBtn).toBeEnabled()
|
|
})
|
|
}
|
|
|
|
await test.step(`Double-click on the closed sketch`, async () => {
|
|
await scene.settled(cmdBar)
|
|
await moveToCircle()
|
|
await page.waitForTimeout(1000)
|
|
await dblClickCircle()
|
|
await page.waitForTimeout(1000)
|
|
await expect(toolbar.exitSketchBtn).toBeVisible()
|
|
await editor.expectState({
|
|
activeLines: [`|>circle(center=[8,5],radius=2)`],
|
|
highlightedCode: 'circle(center=[8,5],radius=2)',
|
|
diagnostics: [],
|
|
})
|
|
})
|
|
await page.waitForTimeout(1000)
|
|
|
|
await exitSketch()
|
|
await page.waitForTimeout(1000)
|
|
|
|
// Drag the sketch line out of the axis view which blocks the click
|
|
await page.dragAndDrop('#stream', '#stream', {
|
|
sourcePosition: {
|
|
x: viewPortSize.width * 0.7,
|
|
y: viewPortSize.height * 0.5,
|
|
},
|
|
targetPosition: {
|
|
x: viewPortSize.width * 0.7,
|
|
y: viewPortSize.height * 0.4,
|
|
},
|
|
})
|
|
|
|
await page.waitForTimeout(500)
|
|
|
|
await test.step(`Double-click on the open sketch`, async () => {
|
|
await moveToOpenPath()
|
|
await scene.expectPixelColor(
|
|
[250, 250, 250],
|
|
pointOnPathAfterSketching,
|
|
15
|
|
)
|
|
// There is a full execution after exiting sketch that clears the scene.
|
|
await page.waitForTimeout(500)
|
|
await dblClickOpenPath()
|
|
await expect(toolbar.exitSketchBtn).toBeVisible()
|
|
// Wait for enter sketch mode to complete
|
|
await page.waitForTimeout(500)
|
|
await editor.expectState({
|
|
activeLines: [`|>tangentialArc(endAbsolute=[10,0])`],
|
|
highlightedCode: 'tangentialArc(endAbsolute=[10,0])',
|
|
diagnostics: [],
|
|
})
|
|
})
|
|
})
|
|
|
|
test(`Shift-click to select and deselect edges and faces`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
}) => {
|
|
// Code samples
|
|
const initialCode = `sketch001 = startSketchOn(XY)
|
|
|> startProfile(at = [-12, -6])
|
|
|> line(end = [0, 12])
|
|
|> line(end = [24, 0])
|
|
|> line(end = [0, -12])
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
|> extrude(%, length = -12)`
|
|
|
|
// Locators
|
|
const upperEdgeLocation = { x: 600, y: 192 }
|
|
const lowerEdgeLocation = { x: 600, y: 383 }
|
|
const faceLocation = { x: 630, y: 290 }
|
|
|
|
// Click helpers
|
|
const [clickOnUpperEdge] = scene.makeMouseHelpers(
|
|
upperEdgeLocation.x,
|
|
upperEdgeLocation.y
|
|
)
|
|
const [clickOnLowerEdge] = scene.makeMouseHelpers(
|
|
lowerEdgeLocation.x,
|
|
lowerEdgeLocation.y
|
|
)
|
|
const [clickOnFace] = scene.makeMouseHelpers(faceLocation.x, faceLocation.y)
|
|
|
|
// Colors
|
|
const edgeColorWhite: [number, number, number] = [220, 220, 220] // varies from 192 to 255
|
|
const edgeColorYellow: [number, number, number] = [251, 251, 40] // vaies from 12 to 67
|
|
const faceColorGray: [number, number, number] = [168, 168, 168]
|
|
const faceColorYellow: [number, number, number] = [155, 155, 155]
|
|
const tolerance = 40
|
|
const timeout = 150
|
|
|
|
// Setup
|
|
await test.step(`Initial test setup`, async () => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
|
|
// Wait for the scene and stream to load
|
|
await scene.expectPixelColor(faceColorGray, faceLocation, tolerance)
|
|
})
|
|
|
|
await test.step('Select and deselect a single edge', async () => {
|
|
await test.step('Click the edge', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
upperEdgeLocation,
|
|
tolerance
|
|
)
|
|
await clickOnUpperEdge()
|
|
await scene.expectPixelColor(
|
|
edgeColorYellow,
|
|
upperEdgeLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
await test.step('Shift-click the same edge to deselect', async () => {
|
|
await page.keyboard.down('Shift')
|
|
await page.waitForTimeout(timeout)
|
|
await clickOnUpperEdge()
|
|
await page.waitForTimeout(timeout)
|
|
await page.keyboard.up('Shift')
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
upperEdgeLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
})
|
|
|
|
await test.step('Select and deselect multiple objects', async () => {
|
|
await test.step('Select both edges and the face', async () => {
|
|
await test.step('Select the upper edge', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
upperEdgeLocation,
|
|
tolerance
|
|
)
|
|
await clickOnUpperEdge()
|
|
await scene.expectPixelColor(
|
|
edgeColorYellow,
|
|
upperEdgeLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
await test.step('Select the lower edge (Shift-click)', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
lowerEdgeLocation,
|
|
tolerance
|
|
)
|
|
await page.keyboard.down('Shift')
|
|
await page.waitForTimeout(timeout)
|
|
await clickOnLowerEdge()
|
|
await page.waitForTimeout(timeout)
|
|
await page.keyboard.up('Shift')
|
|
await scene.expectPixelColor(
|
|
edgeColorYellow,
|
|
lowerEdgeLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
await test.step('Select the face (Shift-click)', async () => {
|
|
await scene.expectPixelColor(faceColorGray, faceLocation, tolerance)
|
|
await page.keyboard.down('Shift')
|
|
await page.waitForTimeout(timeout)
|
|
await clickOnFace()
|
|
await page.waitForTimeout(timeout)
|
|
await page.keyboard.up('Shift')
|
|
await scene.expectPixelColor(faceColorYellow, faceLocation, tolerance)
|
|
})
|
|
})
|
|
await test.step('Deselect them one by one', async () => {
|
|
await test.step('Deselect the face (Shift-click)', async () => {
|
|
await scene.expectPixelColor(faceColorYellow, faceLocation, tolerance)
|
|
await page.keyboard.down('Shift')
|
|
await page.waitForTimeout(timeout)
|
|
await clickOnFace()
|
|
await page.waitForTimeout(timeout)
|
|
await page.keyboard.up('Shift')
|
|
await scene.expectPixelColor(faceColorGray, faceLocation, tolerance)
|
|
})
|
|
await test.step('Deselect the lower edge (Shift-click)', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorYellow,
|
|
lowerEdgeLocation,
|
|
tolerance
|
|
)
|
|
await page.keyboard.down('Shift')
|
|
await page.waitForTimeout(timeout)
|
|
await clickOnLowerEdge()
|
|
await page.waitForTimeout(timeout)
|
|
await page.keyboard.up('Shift')
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
lowerEdgeLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
await test.step('Deselect the upper edge (Shift-click)', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorYellow,
|
|
upperEdgeLocation,
|
|
tolerance
|
|
)
|
|
await page.keyboard.down('Shift')
|
|
await page.waitForTimeout(timeout)
|
|
await clickOnUpperEdge()
|
|
await page.waitForTimeout(timeout)
|
|
await page.keyboard.up('Shift')
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
upperEdgeLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
test(`Shift-click to select and deselect sketch segments`, async ({
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
}) => {
|
|
// Locators
|
|
const firstPointLocation = { x: 200, y: 100 }
|
|
const secondPointLocation = { x: 800, y: 100 }
|
|
const thirdPointLocation = { x: 800, y: 400 }
|
|
const firstSegmentLocation = { x: 750, y: 100 }
|
|
const secondSegmentLocation = { x: 800, y: 150 }
|
|
const planeLocation = { x: 700, y: 200 }
|
|
|
|
// Click helpers
|
|
const [clickFirstPoint] = scene.makeMouseHelpers(
|
|
firstPointLocation.x,
|
|
firstPointLocation.y
|
|
)
|
|
const [clickSecondPoint] = scene.makeMouseHelpers(
|
|
secondPointLocation.x,
|
|
secondPointLocation.y
|
|
)
|
|
const [clickThirdPoint] = scene.makeMouseHelpers(
|
|
thirdPointLocation.x,
|
|
thirdPointLocation.y
|
|
)
|
|
const [clickFirstSegment] = scene.makeMouseHelpers(
|
|
firstSegmentLocation.x,
|
|
firstSegmentLocation.y
|
|
)
|
|
const [clickSecondSegment] = scene.makeMouseHelpers(
|
|
secondSegmentLocation.x,
|
|
secondSegmentLocation.y
|
|
)
|
|
const [clickPlane] = scene.makeMouseHelpers(
|
|
planeLocation.x,
|
|
planeLocation.y
|
|
)
|
|
|
|
// Colors
|
|
const edgeColorWhite: [number, number, number] = [220, 220, 220]
|
|
const edgeColorBlue: [number, number, number] = [20, 20, 200]
|
|
const backgroundColor: [number, number, number] = [30, 30, 30]
|
|
const tolerance = 40
|
|
const timeout = 150
|
|
|
|
// Setup
|
|
await test.step(`Initial test setup`, async () => {
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
|
|
// Wait for the scene and stream to load
|
|
await scene.expectPixelColor(
|
|
backgroundColor,
|
|
secondPointLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
|
|
await test.step('Select and deselect a single sketch segment', async () => {
|
|
await test.step('Get into sketch mode', async () => {
|
|
await editor.closePane()
|
|
await page.waitForTimeout(timeout)
|
|
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
|
await page.waitForTimeout(timeout)
|
|
await clickPlane()
|
|
await page.waitForTimeout(1000)
|
|
})
|
|
await test.step('Draw sketch', async () => {
|
|
await clickFirstPoint()
|
|
await page.waitForTimeout(timeout)
|
|
await clickSecondPoint()
|
|
await page.waitForTimeout(timeout)
|
|
await clickThirdPoint()
|
|
await page.waitForTimeout(timeout)
|
|
})
|
|
await test.step('Deselect line tool', async () => {
|
|
const btnLine = page.getByTestId('line')
|
|
const btnLineAriaPressed = await btnLine.getAttribute('aria-pressed')
|
|
if (btnLineAriaPressed === 'true') {
|
|
await btnLine.click()
|
|
}
|
|
await page.waitForTimeout(timeout)
|
|
})
|
|
await test.step('Select the first segment', async () => {
|
|
await page.waitForTimeout(timeout)
|
|
await clickFirstSegment()
|
|
await page.waitForTimeout(timeout)
|
|
await scene.expectPixelColor(
|
|
edgeColorBlue,
|
|
firstSegmentLocation,
|
|
tolerance
|
|
)
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
secondSegmentLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
await test.step('Select the second segment (Shift-click)', async () => {
|
|
await page.keyboard.down('Shift')
|
|
await page.waitForTimeout(timeout)
|
|
await clickSecondSegment()
|
|
await page.waitForTimeout(timeout)
|
|
await page.keyboard.up('Shift')
|
|
await scene.expectPixelColor(
|
|
edgeColorBlue,
|
|
firstSegmentLocation,
|
|
tolerance
|
|
)
|
|
await scene.expectPixelColor(
|
|
edgeColorBlue,
|
|
secondSegmentLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
await test.step('Deselect the first segment', async () => {
|
|
await page.keyboard.down('Shift')
|
|
await page.waitForTimeout(timeout)
|
|
await clickFirstSegment()
|
|
await page.waitForTimeout(timeout)
|
|
await page.keyboard.up('Shift')
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
firstSegmentLocation,
|
|
tolerance
|
|
)
|
|
await scene.expectPixelColor(
|
|
edgeColorBlue,
|
|
secondSegmentLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
await test.step('Deselect the second segment', async () => {
|
|
await page.keyboard.down('Shift')
|
|
await page.waitForTimeout(timeout)
|
|
await clickSecondSegment()
|
|
await page.waitForTimeout(timeout)
|
|
await page.keyboard.up('Shift')
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
firstSegmentLocation,
|
|
tolerance
|
|
)
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
secondSegmentLocation,
|
|
tolerance
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
test(`Offset plane point-and-click`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
// One dumb hardcoded screen pixel value
|
|
const testPoint = { x: 700, y: 150 }
|
|
const [clickOnXzPlane] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
const expectedOutput = `plane001 = offsetPlane(XZ, offset = 5)`
|
|
|
|
await homePage.goToModelingScene()
|
|
// FIXME: Since there is no KCL code loaded. We need to wait for the scene to load before we continue.
|
|
// The engine may not be connected
|
|
await page.waitForTimeout(15000)
|
|
|
|
await test.step(`Look for the blue of the XZ plane`, async () => {
|
|
//await scene.expectPixelColor([50, 51, 96], testPoint, 15) // FIXME
|
|
})
|
|
await test.step(`Go through the command bar flow`, async () => {
|
|
await toolbar.offsetPlaneButton.click()
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'plane',
|
|
currentArgValue: '',
|
|
headerArguments: { Plane: '', Distance: '' },
|
|
highlightedHeaderArg: 'plane',
|
|
commandName: 'Offset plane',
|
|
})
|
|
await clickOnXzPlane()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'distance',
|
|
currentArgValue: '5',
|
|
headerArguments: { Plane: '1 plane', Distance: '' },
|
|
highlightedHeaderArg: 'distance',
|
|
commandName: 'Offset plane',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await editor.expectEditor.toContain(expectedOutput)
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [expectedOutput],
|
|
highlightedCode: '',
|
|
})
|
|
await scene.expectPixelColor([74, 74, 74], testPoint, 15)
|
|
})
|
|
|
|
await test.step('Delete offset plane via feature tree selection', async () => {
|
|
await editor.closePane()
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Offset Plane',
|
|
0
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
//await scene.expectPixelColor([50, 51, 96], testPoint, 15) // FIXME
|
|
})
|
|
})
|
|
|
|
test('Helix point-and-click on default axis', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
// One dumb hardcoded screen pixel value
|
|
const testPoint = { x: 620, y: 257 }
|
|
const expectedOutput = `helix001 = helix( axis = X, radius = 5, length = 5, revolutions = 1, angleStart = 270, ccw = false,)`
|
|
const expectedLine = `axis=X,`
|
|
|
|
await homePage.goToModelingScene()
|
|
await scene.connectionEstablished()
|
|
|
|
await test.step(`Go through the command bar flow`, async () => {
|
|
await toolbar.helixButton.click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'mode',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Mode: '',
|
|
AngleStart: '',
|
|
Revolutions: '',
|
|
Radius: '',
|
|
CounterClockWise: '',
|
|
},
|
|
highlightedHeaderArg: 'mode',
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await expect.poll(() => page.getByText('Axis').count()).toBe(6)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'angleStart',
|
|
highlightedHeaderArg: 'angleStart',
|
|
currentArgValue: '360',
|
|
headerArguments: {
|
|
Mode: 'Axis',
|
|
Axis: 'X',
|
|
Revolutions: '1',
|
|
AngleStart: '',
|
|
Length: '',
|
|
Radius: '',
|
|
CounterClockWise: '',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.currentArgumentInput.locator('.cm-content').fill('270')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Mode: 'Axis',
|
|
Axis: 'X',
|
|
AngleStart: '270',
|
|
Revolutions: '1',
|
|
Length: '5',
|
|
Radius: '5',
|
|
CounterClockWise: '',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await editor.expectEditor.toContain(expectedOutput)
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [expectedLine],
|
|
highlightedCode: '',
|
|
})
|
|
// Red plane is now gone, white helix is there
|
|
await scene.expectPixelColor([250, 250, 250], testPoint, 15)
|
|
})
|
|
|
|
await test.step(`Edit helix through the feature tree`, async () => {
|
|
await editor.closePane()
|
|
const operationButton = await toolbar.getFeatureTreeOperation('Helix', 0)
|
|
await operationButton.dblclick()
|
|
const initialInput = '5'
|
|
const newInput = '50'
|
|
await cmdBar.expectState({
|
|
commandName: 'Helix',
|
|
stage: 'arguments',
|
|
currentArgKey: 'CounterClockWise',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Axis: 'X',
|
|
AngleStart: '270',
|
|
Revolutions: '1',
|
|
Radius: '5',
|
|
Length: initialInput,
|
|
CounterClockWise: '',
|
|
},
|
|
highlightedHeaderArg: 'CounterClockWise',
|
|
})
|
|
await page.keyboard.press('Shift+Backspace')
|
|
await expect(cmdBar.currentArgumentInput).toBeVisible()
|
|
await cmdBar.currentArgumentInput.locator('.cm-content').fill(newInput)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Axis: 'X',
|
|
AngleStart: '270',
|
|
Revolutions: '1',
|
|
Radius: '5',
|
|
Length: newInput,
|
|
CounterClockWise: '',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closeFeatureTreePane()
|
|
await editor.openPane()
|
|
await editor.expectEditor.toContain('length = ' + newInput)
|
|
})
|
|
|
|
await test.step('Delete helix via feature tree selection', async () => {
|
|
await editor.closePane()
|
|
const operationButton = await toolbar.getFeatureTreeOperation('Helix', 0)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
// Red plane is back
|
|
await scene.expectPixelColor([96, 52, 52], testPoint, 15)
|
|
})
|
|
})
|
|
|
|
const helixCases = [
|
|
{
|
|
selectionType: 'segment',
|
|
testPoint: { x: 513, y: 221 },
|
|
expectedOutput: `helix001 = helix( axis = seg01, radius = 1, revolutions = 20, angleStart = 0, ccw = false,)`,
|
|
expectedEditedOutput: `helix001 = helix( axis = seg01, radius = 5, revolutions = 20, angleStart = 0, ccw = false,)`,
|
|
},
|
|
{
|
|
selectionType: 'sweepEdge',
|
|
testPoint: { x: 564, y: 364 },
|
|
expectedOutput: `helix001 = helix( axis = getOppositeEdge(seg01), radius = 1, revolutions = 20, angleStart = 0, ccw = false,)`,
|
|
expectedEditedOutput: `helix001 = helix( axis = getOppositeEdge(seg01), radius = 5, revolutions = 20, angleStart = 0, ccw = false,)`,
|
|
},
|
|
]
|
|
helixCases.map(
|
|
({ selectionType, testPoint, expectedOutput, expectedEditedOutput }) => {
|
|
test(`Helix point-and-click around ${selectionType}`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
page.on('console', console.log)
|
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
|
profile001 = startProfile(sketch001, at = [0, 0])
|
|
|> yLine(length = 100)
|
|
|> line(endAbsolute = [100, 0])
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
extrude001 = extrude(profile001, length = 100)`
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const [clickOnEdge] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
await test.step(`Go through the command bar flow`, async () => {
|
|
await toolbar.closePane('code')
|
|
await toolbar.helixButton.click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'mode',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
AngleStart: '',
|
|
Mode: '',
|
|
CounterClockWise: '',
|
|
Radius: '',
|
|
Revolutions: '',
|
|
},
|
|
highlightedHeaderArg: 'mode',
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.selectOption({ name: 'Edge' }).click()
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await clickOnEdge()
|
|
await page.waitForTimeout(1000)
|
|
await cmdBar.progressCmdBar()
|
|
await page.waitForTimeout(1000)
|
|
await cmdBar.argumentInput.focus()
|
|
await page.waitForTimeout(1000)
|
|
await page.keyboard.insertText('20')
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('0')
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('1')
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('100')
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Mode: 'Edge',
|
|
Edge: `1 ${selectionType}`,
|
|
AngleStart: '0',
|
|
Revolutions: '20',
|
|
Radius: '1',
|
|
CounterClockWise: '',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await page.waitForTimeout(1000)
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(expectedOutput)
|
|
await toolbar.closePane('code')
|
|
})
|
|
|
|
await test.step(`Edit helix through the feature tree`, async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Helix',
|
|
0
|
|
)
|
|
await operationButton.dblclick()
|
|
const initialInput = '1'
|
|
const newInput = '5'
|
|
await cmdBar.expectState({
|
|
commandName: 'Helix',
|
|
stage: 'arguments',
|
|
currentArgKey: 'CounterClockWise',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
AngleStart: '0',
|
|
Revolutions: '20',
|
|
Radius: initialInput,
|
|
CounterClockWise: '',
|
|
},
|
|
highlightedHeaderArg: 'CounterClockWise',
|
|
})
|
|
await page
|
|
.getByRole('button', { name: 'radius', exact: false })
|
|
.click()
|
|
await expect(cmdBar.currentArgumentInput).toBeVisible()
|
|
await cmdBar.currentArgumentInput
|
|
.locator('.cm-content')
|
|
.fill(newInput)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
AngleStart: '0',
|
|
Revolutions: '20',
|
|
Radius: newInput,
|
|
CounterClockWise: '',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(expectedEditedOutput)
|
|
await toolbar.closePane('code')
|
|
})
|
|
|
|
await test.step('Delete helix via feature tree selection', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Helix',
|
|
0
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await editor.expectEditor.not.toContain(expectedEditedOutput)
|
|
await expect(
|
|
await toolbar.getFeatureTreeOperation('Helix', 0)
|
|
).not.toBeVisible()
|
|
})
|
|
})
|
|
}
|
|
)
|
|
|
|
test('Helix point-and-click on cylinder', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `sketch001 = startSketchOn(XY)
|
|
profile001 = circle(
|
|
sketch001,
|
|
center = [0, 0],
|
|
radius = 100,
|
|
tag = $seg01,
|
|
)
|
|
extrude001 = extrude(profile001, length = 100)
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const testPoint = { x: 620, y: 257 }
|
|
const [clickOnWall] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
const expectedOutput = `helix001 = helix( cylinder = extrude001, revolutions = 1, angleStart = 360, ccw = false,)`
|
|
const expectedLine = `cylinder = extrude001,`
|
|
const expectedEditedOutput = `helix001 = helix( cylinder = extrude001, revolutions = 1, angleStart = 360, ccw = true,)`
|
|
|
|
await test.step(`Go through the command bar flow`, async () => {
|
|
await toolbar.helixButton.click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'mode',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Mode: '',
|
|
AngleStart: '',
|
|
Revolutions: '',
|
|
Radius: '',
|
|
CounterClockWise: '',
|
|
},
|
|
highlightedHeaderArg: 'mode',
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.selectOption({ name: 'Cylinder' }).click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'cylinder',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Mode: 'Cylinder',
|
|
Cylinder: '',
|
|
AngleStart: '',
|
|
Revolutions: '',
|
|
CounterClockWise: '',
|
|
},
|
|
highlightedHeaderArg: 'cylinder',
|
|
commandName: 'Helix',
|
|
})
|
|
await clickOnWall()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Mode: 'Cylinder',
|
|
Cylinder: '1 face',
|
|
AngleStart: '360',
|
|
Revolutions: '1',
|
|
CounterClockWise: '',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await editor.expectEditor.toContain(expectedOutput)
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [expectedLine],
|
|
highlightedCode: '',
|
|
})
|
|
})
|
|
|
|
await test.step(`Edit helix through the feature tree`, async () => {
|
|
await editor.closePane()
|
|
const operationButton = await toolbar.getFeatureTreeOperation('Helix', 0)
|
|
await operationButton.dblclick()
|
|
await cmdBar.expectState({
|
|
commandName: 'Helix',
|
|
stage: 'arguments',
|
|
currentArgKey: 'CounterClockWise',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
AngleStart: '360',
|
|
Revolutions: '1',
|
|
CounterClockWise: '',
|
|
},
|
|
highlightedHeaderArg: 'CounterClockWise',
|
|
})
|
|
await cmdBar.selectOption({ name: 'True' }).click()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
AngleStart: '360',
|
|
Revolutions: '1',
|
|
CounterClockWise: 'true',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(expectedEditedOutput)
|
|
await editor.closePane()
|
|
})
|
|
|
|
await test.step('Delete helix via feature tree selection', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const operationButton = await toolbar.getFeatureTreeOperation('Helix', 0)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await toolbar.closePane('feature-tree')
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.not.toContain(expectedEditedOutput)
|
|
})
|
|
})
|
|
|
|
const loftPointAndClickCases = [
|
|
{ shouldPreselect: true },
|
|
{ shouldPreselect: false },
|
|
]
|
|
loftPointAndClickCases.forEach(({ shouldPreselect }) => {
|
|
test(`Loft point-and-click (preselected sketches: ${shouldPreselect})`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
|
|> circle(center = [0, 0], radius = 30)
|
|
plane001 = offsetPlane(XZ, offset = 50)
|
|
sketch002 = startSketchOn(plane001)
|
|
|> circle(center = [0, 0], radius = 20)
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const testPoint = { x: 575, y: 200 }
|
|
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
const [clickOnSketch2] = scene.makeMouseHelpers(
|
|
testPoint.x,
|
|
testPoint.y + 80
|
|
)
|
|
const loftDeclaration = 'loft001 = loft([sketch001, sketch002])'
|
|
|
|
await test.step(`Look for the white of the sketch001 shape`, async () => {
|
|
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
|
})
|
|
|
|
async function selectSketches() {
|
|
await clickOnSketch1()
|
|
await page.keyboard.down('Shift')
|
|
await clickOnSketch2()
|
|
await page.waitForTimeout(500)
|
|
await page.keyboard.up('Shift')
|
|
}
|
|
|
|
if (!shouldPreselect) {
|
|
await test.step(`Go through the command bar flow without preselected sketches`, async () => {
|
|
await toolbar.loftButton.click()
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'sketches',
|
|
currentArgValue: '',
|
|
headerArguments: { Profiles: '' },
|
|
highlightedHeaderArg: 'Profiles',
|
|
commandName: 'Loft',
|
|
})
|
|
await selectSketches()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: { Profiles: '2 profiles' },
|
|
commandName: 'Loft',
|
|
})
|
|
await cmdBar.submit()
|
|
})
|
|
} else {
|
|
await test.step(`Preselect the two sketches`, async () => {
|
|
await selectSketches()
|
|
})
|
|
|
|
await test.step(`Go through the command bar flow with preselected sketches`, async () => {
|
|
await toolbar.loftButton.click()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: { Profiles: '2 profiles' },
|
|
commandName: 'Loft',
|
|
})
|
|
await cmdBar.submit()
|
|
})
|
|
}
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await editor.expectEditor.toContain(loftDeclaration)
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [loftDeclaration],
|
|
highlightedCode: '',
|
|
})
|
|
await scene.expectPixelColor([89, 89, 89], testPoint, 15)
|
|
})
|
|
|
|
await test.step('Delete loft via feature tree selection', async () => {
|
|
await editor.closePane()
|
|
const operationButton = await toolbar.getFeatureTreeOperation('Loft', 0)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
|
})
|
|
})
|
|
})
|
|
|
|
// TODO: merge with above test. Right now we're not able to delete a loft
|
|
// right after creation via selection for some reason, so we go with a new instance
|
|
test('Loft and offset plane deletion via selection', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
|
|> circle(center = [0, 0], radius = 30)
|
|
plane001 = offsetPlane(XZ, offset = 50)
|
|
sketch002 = startSketchOn(plane001)
|
|
|> circle(center = [0, 0], radius = 20)
|
|
loft001 = loft([sketch001, sketch002])
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const testPoint = { x: 575, y: 200 }
|
|
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
const [clickOnSketch2] = scene.makeMouseHelpers(
|
|
testPoint.x,
|
|
testPoint.y + 80
|
|
)
|
|
|
|
await test.step(`Delete loft`, async () => {
|
|
// Check for loft
|
|
await scene.expectPixelColor([89, 89, 89], testPoint, 15)
|
|
await clickOnSketch1()
|
|
await expect(page.locator('.cm-activeLine')).toHaveText(`
|
|
|> circle(center = [0, 0], radius = 30)
|
|
`)
|
|
await page.keyboard.press('Delete')
|
|
// Check for sketch 1
|
|
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
|
})
|
|
|
|
await test.step('Delete sketch002', async () => {
|
|
await page.waitForTimeout(1000)
|
|
await clickOnSketch2()
|
|
await expect(page.locator('.cm-activeLine')).toHaveText(`
|
|
|> circle(center = [0, 0], radius = 20)
|
|
`)
|
|
await page.keyboard.press('Delete')
|
|
// Check for plane001
|
|
await scene.expectPixelColor([228, 228, 228], testPoint, 15)
|
|
})
|
|
|
|
await test.step('Delete plane001', async () => {
|
|
await page.waitForTimeout(1000)
|
|
await clickOnSketch2()
|
|
await expect(page.locator('.cm-activeLine')).toHaveText(`
|
|
plane001 = offsetPlane(XZ, offset = 50)
|
|
`)
|
|
await page.keyboard.press('Delete')
|
|
// Check for sketch 1
|
|
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
|
|
})
|
|
})
|
|
|
|
const sweepCases = [
|
|
{
|
|
targetType: 'circle',
|
|
testPoint: { x: 700, y: 250 },
|
|
initialCode: `@settings(defaultLengthUnit = in)
|
|
sketch001 = startSketchOn(YZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 500)
|
|
sketch002 = startSketchOn(XZ)
|
|
|> startProfile(at = [0, 0])
|
|
|> xLine(length = -500)
|
|
|> tangentialArc(endAbsolute = [-2000, 500])`,
|
|
},
|
|
{
|
|
targetType: 'rectangle',
|
|
testPoint: { x: 710, y: 255 },
|
|
initialCode: `@settings(defaultLengthUnit = in)
|
|
sketch001 = startSketchOn(YZ)
|
|
profile001 = startProfile(sketch001, at = [-400, -400])
|
|
|> angledLine(angle = 0, length = 800, tag = $rectangleSegmentA001)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = 800)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
sketch002 = startSketchOn(XZ)
|
|
|> startProfile(at = [0, 0])
|
|
|> xLine(length = -500)
|
|
|> tangentialArc(endAbsolute = [-2000, 500])`,
|
|
},
|
|
]
|
|
sweepCases.map(({ initialCode, targetType, testPoint }) => {
|
|
test(`Sweep point-and-click ${targetType}`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
const [clickOnSketch2] = scene.makeMouseHelpers(
|
|
testPoint.x - 50,
|
|
testPoint.y
|
|
)
|
|
const sweepDeclaration = 'sweep001 = sweep(profile001, path = sketch002)'
|
|
const editedSweepDeclaration =
|
|
'sweep001 = sweep(profile001, path = sketch002, sectional = true)'
|
|
|
|
await test.step(`Look for sketch001`, async () => {
|
|
await toolbar.closePane('code')
|
|
await scene.expectPixelColor([53, 53, 53], testPoint, 15)
|
|
})
|
|
|
|
await test.step(`Go through the command bar flow`, async () => {
|
|
await toolbar.sweepButton.click()
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
currentArgKey: 'sketches',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Sectional: '',
|
|
Profiles: '',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'Profiles',
|
|
stage: 'arguments',
|
|
})
|
|
await clickOnSketch1()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
currentArgKey: 'path',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Sectional: '',
|
|
Profiles: '1 profile',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'path',
|
|
stage: 'arguments',
|
|
})
|
|
await clickOnSketch2()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
currentArgKey: 'path',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Sectional: '',
|
|
Profiles: '1 profile',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'path',
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
headerArguments: {
|
|
Profiles: '1 profile',
|
|
Path: '1 segment',
|
|
Sectional: '',
|
|
},
|
|
stage: 'review',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(sweepDeclaration)
|
|
await scene.expectPixelColor([120, 120, 120], testPoint, 40)
|
|
await toolbar.closePane('code')
|
|
})
|
|
|
|
await test.step('Edit sweep via feature tree selection works', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Sweep',
|
|
0
|
|
)
|
|
await operationButton.dblclick({ button: 'left' })
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
currentArgKey: 'sectional',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Sectional: '',
|
|
},
|
|
highlightedHeaderArg: 'sectional',
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.selectOption({ name: 'True' }).click()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
headerArguments: {
|
|
Sectional: '',
|
|
},
|
|
stage: 'review',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(editedSweepDeclaration)
|
|
await toolbar.closePane('code')
|
|
})
|
|
|
|
await test.step('Delete sweep via feature tree selection', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
await page.waitForTimeout(500)
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Sweep',
|
|
0
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await page.waitForTimeout(500)
|
|
await toolbar.closePane('feature-tree')
|
|
await scene.expectPixelColor([53, 53, 53], testPoint, 15)
|
|
})
|
|
})
|
|
})
|
|
|
|
test(`Sweep point-and-click helix`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const circleCode = `circle(sketch001, center = [0, -1], radius = .1)`
|
|
const initialCode = `helix001 = helix(
|
|
axis = X,
|
|
radius = 1,
|
|
length = 10,
|
|
revolutions = 10,
|
|
angleStart = 0,
|
|
ccw = false,
|
|
)
|
|
sketch001 = startSketchOn(XZ)
|
|
profile001 = ${circleCode}`
|
|
const sweepDeclaration = 'sweep001 = sweep(profile001, path = helix001)'
|
|
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
await test.step(`Add sweep through the command bar flow`, async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
await toolbar.sweepButton.click()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
currentArgKey: 'sketches',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Sectional: '',
|
|
Profiles: '',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'Profiles',
|
|
stage: 'arguments',
|
|
})
|
|
await editor.scrollToText(circleCode)
|
|
await page.getByText(circleCode).click()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
currentArgKey: 'path',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Sectional: '',
|
|
Profiles: '1 profile',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'path',
|
|
stage: 'arguments',
|
|
})
|
|
const helix = await toolbar.getFeatureTreeOperation('Helix', 0)
|
|
await helix.click()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
currentArgKey: 'path',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Sectional: '',
|
|
Profiles: '1 profile',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'path',
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
headerArguments: {
|
|
Profiles: '1 profile',
|
|
Path: '1 helix',
|
|
Sectional: '',
|
|
},
|
|
stage: 'review',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await editor.expectEditor.toContain(sweepDeclaration)
|
|
})
|
|
|
|
await test.step('Delete sweep via feature tree selection', async () => {
|
|
const sweep = await toolbar.getFeatureTreeOperation('Sweep', 0)
|
|
await sweep.click()
|
|
await page.keyboard.press('Delete')
|
|
await editor.expectEditor.not.toContain(sweepDeclaration)
|
|
})
|
|
})
|
|
|
|
test(`Fillet point-and-click`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
// Code samples
|
|
const initialCode = `sketch001 = startSketchOn(XY)
|
|
|> startProfile(at = [-12, -6])
|
|
|> line(end = [0, 12])
|
|
|> line(end = [24, 0])
|
|
|> line(end = [0, -12])
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
extrude001 = extrude(sketch001, length = -12)
|
|
`
|
|
const firstFilletDeclaration = `fillet(radius=5,tags=[getCommonEdge(faces=[seg01,capEnd001])],)`
|
|
const secondFilletDeclaration = `fillet(radius=5,tags=[getCommonEdge(faces=[seg01,capStart001])],)`
|
|
|
|
// Locators
|
|
const firstEdgeLocation = { x: 600, y: 193 }
|
|
const secondEdgeLocation = { x: 600, y: 383 }
|
|
const bodyLocation = { x: 630, y: 290 }
|
|
const [clickOnFirstEdge] = scene.makeMouseHelpers(
|
|
firstEdgeLocation.x,
|
|
firstEdgeLocation.y
|
|
)
|
|
const [clickOnSecondEdge] = scene.makeMouseHelpers(
|
|
secondEdgeLocation.x,
|
|
secondEdgeLocation.y
|
|
)
|
|
|
|
// Colors
|
|
const edgeColorWhite: [number, number, number] = [248, 248, 248]
|
|
const edgeColorYellow: [number, number, number] = [251, 251, 40] // Mac:B=67 Ubuntu:B=12
|
|
const bodyColor: [number, number, number] = [155, 155, 155]
|
|
const filletColor: [number, number, number] = [127, 127, 127]
|
|
const backgroundColor: [number, number, number] = [30, 30, 30]
|
|
const lowTolerance = 20
|
|
const highTolerance = 70 // TODO: understand why I needed that for edgeColorYellow on macos (local)
|
|
|
|
// Setup
|
|
await test.step(`Initial test setup`, async () => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
|
|
// verify modeling scene is loaded
|
|
await scene.expectPixelColor(
|
|
backgroundColor,
|
|
secondEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
|
|
// wait for stream to load
|
|
await scene.expectPixelColor(bodyColor, bodyLocation, highTolerance)
|
|
})
|
|
|
|
// Test 1: Command bar flow with preselected edges
|
|
await test.step(`Select first edge`, async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
firstEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
await clickOnFirstEdge()
|
|
await scene.expectPixelColor(
|
|
edgeColorYellow,
|
|
firstEdgeLocation,
|
|
highTolerance // Ubuntu color mismatch can require high tolerance
|
|
)
|
|
})
|
|
|
|
await test.step(`Apply fillet to the preselected edge`, async () => {
|
|
await page.waitForTimeout(100)
|
|
await toolbar.filletButton.click()
|
|
await cmdBar.expectState({
|
|
commandName: 'Fillet',
|
|
highlightedHeaderArg: 'radius',
|
|
currentArgKey: 'radius',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Selection: '1 segment',
|
|
Radius: '',
|
|
},
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Fillet',
|
|
headerArguments: {
|
|
Selection: '1 segment',
|
|
Radius: '5',
|
|
},
|
|
stage: 'review',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor`, async () => {
|
|
await editor.expectEditor.toContain(firstFilletDeclaration, {
|
|
shouldNormalise: true,
|
|
})
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [')'],
|
|
highlightedCode: '',
|
|
})
|
|
})
|
|
|
|
await test.step(`Confirm scene has changed`, async () => {
|
|
await scene.expectPixelColor(filletColor, firstEdgeLocation, lowTolerance)
|
|
})
|
|
|
|
// Test 1.1: Edit fillet (segment type)
|
|
async function editFillet(
|
|
featureTreeIndex: number,
|
|
oldValue: string,
|
|
newValue: string
|
|
) {
|
|
await toolbar.openPane('feature-tree')
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Fillet',
|
|
featureTreeIndex
|
|
)
|
|
await operationButton.dblclick({ button: 'left' })
|
|
await cmdBar.expectState({
|
|
commandName: 'Fillet',
|
|
currentArgKey: 'radius',
|
|
currentArgValue: oldValue,
|
|
headerArguments: {
|
|
Radius: oldValue,
|
|
},
|
|
highlightedHeaderArg: 'radius',
|
|
stage: 'arguments',
|
|
})
|
|
await page.keyboard.insertText(newValue)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Radius: newValue,
|
|
},
|
|
commandName: 'Fillet',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
}
|
|
|
|
await test.step('Edit fillet via feature tree selection works', async () => {
|
|
const firstFilletFeatureTreeIndex = 0
|
|
const editedRadius = '1'
|
|
await editFillet(firstFilletFeatureTreeIndex, '5', editedRadius)
|
|
await editor.expectEditor.toContain(
|
|
firstFilletDeclaration.replace('radius=5', 'radius=' + editedRadius),
|
|
{ shouldNormalise: true }
|
|
)
|
|
|
|
// Edit back to original radius
|
|
await editFillet(firstFilletFeatureTreeIndex, editedRadius, '5')
|
|
await editor.expectEditor.toContain(firstFilletDeclaration, {
|
|
shouldNormalise: true,
|
|
})
|
|
})
|
|
|
|
// Test 2: Command bar flow without preselected edges
|
|
await test.step(`Open fillet UI without selecting edges`, async () => {
|
|
await page.waitForTimeout(100)
|
|
await toolbar.filletButton.click()
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
Radius: '',
|
|
},
|
|
highlightedHeaderArg: 'selection',
|
|
commandName: 'Fillet',
|
|
})
|
|
})
|
|
|
|
await test.step(`Select second edge`, async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
secondEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
await clickOnSecondEdge()
|
|
await scene.expectPixelColor(
|
|
edgeColorYellow,
|
|
secondEdgeLocation,
|
|
highTolerance // Ubuntu color mismatch can require high tolerance
|
|
)
|
|
})
|
|
|
|
await test.step(`Apply fillet to the second edge`, async () => {
|
|
await cmdBar.expectState({
|
|
commandName: 'Fillet',
|
|
highlightedHeaderArg: 'selection',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
Radius: '',
|
|
},
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Fillet',
|
|
highlightedHeaderArg: 'radius',
|
|
currentArgKey: 'radius',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Selection: '1 sweepEdge',
|
|
Radius: '',
|
|
},
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Fillet',
|
|
headerArguments: {
|
|
Selection: '1 sweepEdge',
|
|
Radius: '5',
|
|
},
|
|
stage: 'review',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor`, async () => {
|
|
await editor.expectEditor.toContain(secondFilletDeclaration, {
|
|
shouldNormalise: true,
|
|
})
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [')'],
|
|
highlightedCode: '',
|
|
})
|
|
})
|
|
|
|
await test.step(`Confirm scene has changed`, async () => {
|
|
await scene.expectPixelColor(
|
|
backgroundColor,
|
|
secondEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
|
|
// Test 2.1: Edit fillet (edgeSweep type)
|
|
await test.step('Edit fillet via feature tree selection works', async () => {
|
|
const secondFilletFeatureTreeIndex = 1
|
|
const editedRadius = '2'
|
|
await editFillet(secondFilletFeatureTreeIndex, '5', editedRadius)
|
|
await editor.expectEditor.toContain(
|
|
secondFilletDeclaration.replace('radius=5', 'radius=' + editedRadius),
|
|
{ shouldNormalise: true }
|
|
)
|
|
|
|
// Edit back to original radius
|
|
await editFillet(secondFilletFeatureTreeIndex, editedRadius, '5')
|
|
await editor.expectEditor.toContain(secondFilletDeclaration, {
|
|
shouldNormalise: true,
|
|
})
|
|
})
|
|
|
|
// Test 3: Delete fillets
|
|
await test.step('Delete fillet via feature tree selection', async () => {
|
|
await test.step('Open Feature Tree Pane', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
await page.waitForTimeout(500)
|
|
})
|
|
await test.step('Delete fillet via feature tree selection', async () => {
|
|
await editor.expectEditor.toContain(secondFilletDeclaration, {
|
|
shouldNormalise: true,
|
|
})
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Fillet',
|
|
1
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await page.waitForTimeout(500)
|
|
await scene.expectPixelColor(edgeColorWhite, secondEdgeLocation, 15) // deleted
|
|
await editor.expectEditor.not.toContain(secondFilletDeclaration)
|
|
await scene.expectPixelColor(filletColor, firstEdgeLocation, 15) // stayed
|
|
})
|
|
})
|
|
})
|
|
|
|
test(`Fillet point-and-click edit standalone expression`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `sketch001 = startSketchOn(XY)
|
|
profile001 = circle(
|
|
sketch001,
|
|
center = [0, 0],
|
|
radius = 100,
|
|
tag = $seg01,
|
|
)
|
|
extrude001 = extrude(profile001, length = 100)
|
|
fillet001 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])
|
|
`
|
|
await test.step(`Initial test setup`, async () => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
})
|
|
await test.step('Edit fillet', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
await toolbar.closePane('code')
|
|
const operationButton = await toolbar.getFeatureTreeOperation('Fillet', 0)
|
|
await operationButton.dblclick({ button: 'left' })
|
|
await cmdBar.expectState({
|
|
commandName: 'Fillet',
|
|
currentArgKey: 'radius',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Radius: '5',
|
|
},
|
|
highlightedHeaderArg: 'radius',
|
|
stage: 'arguments',
|
|
})
|
|
await page.keyboard.insertText('20')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Radius: '20',
|
|
},
|
|
commandName: 'Fillet',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
await test.step('Confirm changes', async () => {
|
|
await toolbar.openPane('code')
|
|
await toolbar.closePane('feature-tree')
|
|
await editor.expectEditor.toContain('radius = 20')
|
|
})
|
|
})
|
|
|
|
test(`Fillet point-and-click delete`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
// Code samples
|
|
const initialCode = `sketch001 = startSketchOn(XY)
|
|
|> startProfile(at = [-12, -6])
|
|
|> line(end = [0, 12])
|
|
|> line(end = [24, 0], tag = $seg02)
|
|
|> line(end = [0, -12])
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg01)
|
|
|> close()
|
|
extrude001 = extrude(sketch001, length = -12)
|
|
|> fillet(radius = 5, tags = [seg01]) // fillet01
|
|
|> fillet(radius = 5, tags = [seg02]) // fillet02
|
|
fillet03 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])
|
|
fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])
|
|
`
|
|
const firstPipedFilletDeclaration = 'fillet(radius = 5, tags = [seg01])'
|
|
const secondPipedFilletDeclaration = 'fillet(radius = 5, tags = [seg02])'
|
|
const standaloneAssignedFilletDeclaration =
|
|
'fillet03 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])'
|
|
const standaloneUnassignedFilletDeclaration =
|
|
'fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])'
|
|
|
|
// Locators
|
|
const pipedFilletEdgeLocation = { x: 600, y: 193 }
|
|
const standaloneFilletEdgeLocation = { x: 600, y: 383 }
|
|
const bodyLocation = { x: 630, y: 290 }
|
|
|
|
// Colors
|
|
const edgeColorWhite: [number, number, number] = [248, 248, 248]
|
|
const bodyColor: [number, number, number] = [155, 155, 155]
|
|
const filletColor: [number, number, number] = [127, 127, 127]
|
|
const backgroundColor: [number, number, number] = [30, 30, 30]
|
|
const lowTolerance = 20
|
|
const highTolerance = 40
|
|
|
|
// Setup
|
|
await test.step(`Initial test setup`, async () => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// verify modeling scene is loaded
|
|
await scene.expectPixelColor(
|
|
backgroundColor,
|
|
standaloneFilletEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
|
|
// wait for stream to load
|
|
await scene.expectPixelColor(bodyColor, bodyLocation, highTolerance)
|
|
})
|
|
|
|
// Test
|
|
await test.step('Delete fillet via feature tree selection', async () => {
|
|
await test.step('Open Feature Tree Pane', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
await scene.settled(cmdBar)
|
|
})
|
|
|
|
await test.step('Delete piped fillet via feature tree selection', async () => {
|
|
await test.step('Verify all fillets are present in the editor', async () => {
|
|
await editor.expectEditor.toContain(firstPipedFilletDeclaration)
|
|
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
|
await editor.expectEditor.toContain(
|
|
standaloneAssignedFilletDeclaration
|
|
)
|
|
await editor.expectEditor.toContain(
|
|
standaloneUnassignedFilletDeclaration
|
|
)
|
|
})
|
|
await test.step('Verify test fillets are present in the scene', async () => {
|
|
await scene.expectPixelColor(
|
|
filletColor,
|
|
pipedFilletEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
await scene.expectPixelColor(
|
|
backgroundColor,
|
|
standaloneFilletEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
await test.step('Delete piped fillet', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Fillet',
|
|
0
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await scene.settled(cmdBar)
|
|
})
|
|
await test.step('Verify piped fillet is deleted but other fillets are not (in the editor)', async () => {
|
|
await editor.expectEditor.not.toContain(firstPipedFilletDeclaration)
|
|
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
|
await editor.expectEditor.toContain(
|
|
standaloneAssignedFilletDeclaration
|
|
)
|
|
await editor.expectEditor.toContain(
|
|
standaloneUnassignedFilletDeclaration
|
|
)
|
|
})
|
|
await test.step('Verify piped fillet is deleted but non-piped is not (in the scene)', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite, // you see edge because fillet is deleted
|
|
pipedFilletEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
await scene.expectPixelColor(
|
|
backgroundColor, // you see background because fillet is not deleted
|
|
standaloneFilletEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
})
|
|
|
|
await test.step('Delete standalone assigned fillet via feature tree selection', async () => {
|
|
await test.step('Delete standalone assigned fillet', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Fillet',
|
|
1
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await scene.settled(cmdBar)
|
|
})
|
|
await test.step('Verify standalone assigned fillet is deleted but other two fillets are not (in the editor)', async () => {
|
|
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
|
await editor.expectEditor.not.toContain(
|
|
standaloneAssignedFilletDeclaration
|
|
)
|
|
await editor.expectEditor.toContain(
|
|
standaloneUnassignedFilletDeclaration
|
|
)
|
|
})
|
|
await test.step('Verify standalone assigned fillet is deleted but piped is not (in the scene)', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
standaloneFilletEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
})
|
|
|
|
await test.step('Delete standalone unassigned fillet via feature tree selection', async () => {
|
|
await test.step('Delete standalone unassigned fillet', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Fillet',
|
|
1
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await scene.settled(cmdBar)
|
|
})
|
|
await test.step('Verify standalone unassigned fillet is deleted but other fillet is not (in the editor)', async () => {
|
|
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
|
await editor.expectEditor.not.toContain(
|
|
standaloneUnassignedFilletDeclaration
|
|
)
|
|
})
|
|
await test.step('Verify standalone unassigned fillet is deleted but piped is not (in the scene)', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
standaloneFilletEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
test(`Fillet with large radius should update code even if engine fails`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
// Create a cube with small edges that will cause some fillets to fail
|
|
const initialCode = `sketch001 = startSketchOn(XY)
|
|
profile001 = startProfile(sketch001, at = [0, 0])
|
|
|> yLine(length = -1)
|
|
|> xLine(length = -10)
|
|
|> yLine(length = 10)
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
extrude001 = extrude(profile001, length = 5)
|
|
`
|
|
const taggedSegment1 = `xLine(length = -10, tag = $seg01)`
|
|
const taggedSegment2 = `yLine(length = -1, tag = $seg02)`
|
|
const filletExpression = `fillet(radius = 1000, tags = [getCommonEdge(faces = [seg01, seg02])])`
|
|
|
|
// Locators
|
|
const edgeLocation = { x: 659, y: 313 }
|
|
const bodyLocation = { x: 594, y: 313 }
|
|
|
|
// Colors
|
|
const edgeColorWhite: [number, number, number] = [248, 248, 248]
|
|
const edgeColorYellow: [number, number, number] = [251, 251, 120] // Mac:B=251,251,90 Ubuntu:240,241,180, Windows:240,241,180
|
|
const backgroundColor: [number, number, number] = [30, 30, 30]
|
|
const bodyColor: [number, number, number] = [155, 155, 155]
|
|
const lowTolerance = 20
|
|
const highTolerance = 70
|
|
|
|
// Setup
|
|
await test.step(`Initial test setup`, async () => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
|
|
// verify modeling scene is loaded
|
|
await scene.expectPixelColor(backgroundColor, edgeLocation, lowTolerance)
|
|
|
|
// wait for stream to load
|
|
await scene.expectPixelColor(bodyColor, bodyLocation, highTolerance)
|
|
})
|
|
|
|
// Test
|
|
await test.step('Select edges and apply oversized fillet', async () => {
|
|
await test.step(`Select the edge`, async () => {
|
|
await scene.expectPixelColor(edgeColorWhite, edgeLocation, lowTolerance)
|
|
const [clickOnTheEdge] = scene.makeMouseHelpers(
|
|
edgeLocation.x,
|
|
edgeLocation.y
|
|
)
|
|
await clickOnTheEdge()
|
|
await scene.expectPixelColor(
|
|
edgeColorYellow,
|
|
edgeLocation,
|
|
highTolerance // Ubuntu color mismatch can require high tolerance
|
|
)
|
|
})
|
|
|
|
await test.step(`Apply fillet`, async () => {
|
|
await page.waitForTimeout(100)
|
|
await toolbar.filletButton.click()
|
|
await cmdBar.expectState({
|
|
commandName: 'Fillet',
|
|
highlightedHeaderArg: 'radius',
|
|
currentArgKey: 'radius',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Selection: '1 sweepEdge',
|
|
Radius: '',
|
|
},
|
|
stage: 'arguments',
|
|
})
|
|
// Set a large radius (1000)
|
|
await cmdBar.currentArgumentInput.locator('.cm-content').fill('1000')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Fillet',
|
|
headerArguments: {
|
|
Selection: '1 sweepEdge',
|
|
Radius: '1000',
|
|
},
|
|
stage: 'review',
|
|
})
|
|
// Apply fillet with large radius
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
})
|
|
|
|
await test.step('Verify code is updated regardless of execution errors', async () => {
|
|
await editor.expectEditor.toContain(taggedSegment1)
|
|
await editor.expectEditor.toContain(taggedSegment2)
|
|
await editor.expectEditor.toContain(filletExpression)
|
|
})
|
|
})
|
|
|
|
test(`Chamfer point-and-click`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
// Code samples
|
|
const initialCode = `@settings(defaultLengthUnit = in)
|
|
sketch001 = startSketchOn(XY)
|
|
|> startProfile(at = [-12, -6])
|
|
|> line(end = [0, 12])
|
|
|> line(end = [24, 0])
|
|
|> line(end = [0, -12])
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
extrude001 = extrude(sketch001, length = -12)
|
|
`
|
|
const firstChamferDeclaration = `chamfer(length=5,tags=[getCommonEdge(faces=[seg01,capEnd001])],)`
|
|
const secondChamferDeclaration = `chamfer(length=5,tags=[getCommonEdge(faces=[seg01,capStart001])],)`
|
|
|
|
// Locators
|
|
const firstEdgeLocation = { x: 600, y: 193 }
|
|
const secondEdgeLocation = { x: 600, y: 383 }
|
|
const [clickOnFirstEdge] = scene.makeMouseHelpers(
|
|
firstEdgeLocation.x,
|
|
firstEdgeLocation.y
|
|
)
|
|
const [clickOnSecondEdge] = scene.makeMouseHelpers(
|
|
secondEdgeLocation.x,
|
|
secondEdgeLocation.y
|
|
)
|
|
|
|
// Colors
|
|
const edgeColorWhite: [number, number, number] = [248, 248, 248]
|
|
const edgeColorYellow: [number, number, number] = [251, 251, 40] // Mac:B=67 Ubuntu:B=12
|
|
const chamferColor: [number, number, number] = [168, 168, 168]
|
|
const backgroundColor: [number, number, number] = [30, 30, 30]
|
|
const lowTolerance = 20
|
|
const highTolerance = 70 // TODO: understand why I needed that for edgeColorYellow on macos (local)
|
|
|
|
// Setup
|
|
await test.step(`Initial test setup`, async () => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
})
|
|
|
|
// Test 1: Command bar flow with preselected edges
|
|
await test.step(`Select first edge`, async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
firstEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
await clickOnFirstEdge()
|
|
await scene.expectPixelColor(
|
|
edgeColorYellow,
|
|
firstEdgeLocation,
|
|
highTolerance // Ubuntu color mismatch can require high tolerance
|
|
)
|
|
})
|
|
|
|
await test.step(`Apply chamfer to the preselected edge`, async () => {
|
|
await page.waitForTimeout(100)
|
|
await toolbar.chamferButton.click()
|
|
await cmdBar.expectState({
|
|
commandName: 'Chamfer',
|
|
highlightedHeaderArg: 'length',
|
|
currentArgKey: 'length',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Selection: '1 segment',
|
|
Length: '',
|
|
},
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.argumentInput.focus()
|
|
await page.waitForTimeout(1000)
|
|
await cmdBar.progressCmdBar()
|
|
await page.waitForTimeout(1000)
|
|
await cmdBar.expectState({
|
|
commandName: 'Chamfer',
|
|
headerArguments: {
|
|
Selection: '1 segment',
|
|
Length: '5',
|
|
},
|
|
stage: 'review',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor`, async () => {
|
|
await editor.expectEditor.toContain(firstChamferDeclaration, {
|
|
shouldNormalise: true,
|
|
})
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [')'],
|
|
highlightedCode: '',
|
|
})
|
|
})
|
|
|
|
await test.step(`Confirm scene has changed`, async () => {
|
|
await scene.expectPixelColor(
|
|
chamferColor,
|
|
firstEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
|
|
// Test 1.1: Edit sweep
|
|
async function editChamfer(
|
|
featureTreeIndex: number,
|
|
oldValue: string,
|
|
newValue: string
|
|
) {
|
|
await toolbar.openPane('feature-tree')
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Chamfer',
|
|
featureTreeIndex
|
|
)
|
|
await operationButton.dblclick({ button: 'left' })
|
|
await cmdBar.expectState({
|
|
commandName: 'Chamfer',
|
|
currentArgKey: 'length',
|
|
currentArgValue: oldValue,
|
|
headerArguments: {
|
|
Length: oldValue,
|
|
},
|
|
highlightedHeaderArg: 'length',
|
|
stage: 'arguments',
|
|
})
|
|
await page.keyboard.insertText(newValue)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Length: newValue,
|
|
},
|
|
commandName: 'Chamfer',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
}
|
|
|
|
await test.step('Edit chamfer via feature tree selection works', async () => {
|
|
const firstChamferFeatureTreeIndex = 0
|
|
const editedLength = '1'
|
|
await editChamfer(firstChamferFeatureTreeIndex, '5', editedLength)
|
|
await editor.expectEditor.toContain(
|
|
firstChamferDeclaration.replace('length=5', 'length=' + editedLength),
|
|
{ shouldNormalise: true }
|
|
)
|
|
|
|
// Edit back to original radius
|
|
await editChamfer(firstChamferFeatureTreeIndex, editedLength, '5')
|
|
await editor.expectEditor.toContain(firstChamferDeclaration, {
|
|
shouldNormalise: true,
|
|
})
|
|
})
|
|
|
|
// Test 2: Command bar flow without preselected edges
|
|
await test.step(`Open chamfer UI without selecting edges`, async () => {
|
|
await page.waitForTimeout(100)
|
|
await toolbar.chamferButton.click()
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
Length: '',
|
|
},
|
|
highlightedHeaderArg: 'selection',
|
|
commandName: 'Chamfer',
|
|
})
|
|
})
|
|
|
|
await test.step(`Select second edge`, async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
secondEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
await clickOnSecondEdge()
|
|
await scene.expectPixelColor(
|
|
edgeColorYellow,
|
|
secondEdgeLocation,
|
|
highTolerance // Ubuntu color mismatch can require high tolerance
|
|
)
|
|
})
|
|
|
|
await test.step(`Apply chamfer to the second edge`, async () => {
|
|
await cmdBar.expectState({
|
|
commandName: 'Chamfer',
|
|
highlightedHeaderArg: 'selection',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
Length: '',
|
|
},
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Chamfer',
|
|
highlightedHeaderArg: 'length',
|
|
currentArgKey: 'length',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Selection: '1 sweepEdge',
|
|
Length: '',
|
|
},
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Chamfer',
|
|
headerArguments: {
|
|
Selection: '1 sweepEdge',
|
|
Length: '5',
|
|
},
|
|
stage: 'review',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor`, async () => {
|
|
await editor.expectEditor.toContain(secondChamferDeclaration, {
|
|
shouldNormalise: true,
|
|
})
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [')'],
|
|
highlightedCode: '',
|
|
})
|
|
})
|
|
|
|
await test.step(`Confirm scene has changed`, async () => {
|
|
await scene.expectPixelColor(
|
|
backgroundColor,
|
|
secondEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
|
|
// Test 2.1: Edit chamfer (edgeSweep type)
|
|
await test.step('Edit chamfer via feature tree selection works', async () => {
|
|
const secondChamferFeatureTreeIndex = 1
|
|
const editedLength = '2'
|
|
await editChamfer(secondChamferFeatureTreeIndex, '5', editedLength)
|
|
await editor.expectEditor.toContain(
|
|
secondChamferDeclaration.replace('length=5', 'length=' + editedLength),
|
|
{ shouldNormalise: true }
|
|
)
|
|
|
|
// Edit back to original length
|
|
await editChamfer(secondChamferFeatureTreeIndex, editedLength, '5')
|
|
await editor.expectEditor.toContain(secondChamferDeclaration, {
|
|
shouldNormalise: true,
|
|
})
|
|
})
|
|
|
|
// Test 3: Delete chamfer via feature tree selection
|
|
await test.step('Open Feature Tree Pane', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
await page.waitForTimeout(500)
|
|
})
|
|
await test.step('Delete chamfer via feature tree selection', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Chamfer',
|
|
1
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await page.waitForTimeout(500)
|
|
await scene.expectPixelColor(edgeColorWhite, secondEdgeLocation, 15) // deleted
|
|
await scene.expectPixelColor(chamferColor, firstEdgeLocation, 15) // stayed
|
|
})
|
|
})
|
|
|
|
test(`Chamfer point-and-click delete`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
// Code samples
|
|
const initialCode = `@settings(defaultLengthUnit = in)
|
|
sketch001 = startSketchOn(XY)
|
|
|> startProfile(at = [-12, -6])
|
|
|> line(end = [0, 12])
|
|
|> line(end = [24, 0], tag = $seg02)
|
|
|> line(end = [0, -12])
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg01)
|
|
|> close()
|
|
extrude001 = extrude(sketch001, length = -12)
|
|
|> chamfer(length = 5, tags = [seg01]) // chamfer01
|
|
|> chamfer(length = 5, tags = [seg02]) // chamfer02
|
|
chamfer03 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg01)])
|
|
chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|
`
|
|
const firstPipedChamferDeclaration = 'chamfer(length = 5, tags = [seg01])'
|
|
const secondPipedChamferDeclaration = 'chamfer(length = 5, tags = [seg02])'
|
|
const standaloneAssignedChamferDeclaration =
|
|
'chamfer03 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg01)])'
|
|
const standaloneUnassignedChamferDeclaration =
|
|
'chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])'
|
|
|
|
// Locators
|
|
const pipedChamferEdgeLocation = { x: 600, y: 193 }
|
|
const standaloneChamferEdgeLocation = { x: 600, y: 383 }
|
|
const bodyLocation = { x: 630, y: 290 }
|
|
|
|
// Colors
|
|
const edgeColorWhite: [number, number, number] = [248, 248, 248]
|
|
const bodyColor: [number, number, number] = [155, 155, 155]
|
|
const chamferColor: [number, number, number] = [168, 168, 168]
|
|
const backgroundColor: [number, number, number] = [30, 30, 30]
|
|
const lowTolerance = 20
|
|
const highTolerance = 40
|
|
|
|
// Setup
|
|
await test.step(`Initial test setup`, async () => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// verify modeling scene is loaded
|
|
await scene.expectPixelColor(
|
|
backgroundColor,
|
|
standaloneChamferEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
|
|
// wait for stream to load
|
|
await scene.expectPixelColor(bodyColor, bodyLocation, highTolerance)
|
|
})
|
|
|
|
// Test
|
|
await test.step('Delete chamfer via feature tree selection', async () => {
|
|
await test.step('Open Feature Tree Pane', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
await scene.settled(cmdBar)
|
|
})
|
|
|
|
await test.step('Delete piped chamfer via feature tree selection', async () => {
|
|
await test.step('Verify all chamfers are present in the editor', async () => {
|
|
await editor.expectEditor.toContain(firstPipedChamferDeclaration)
|
|
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
|
await editor.expectEditor.toContain(
|
|
standaloneAssignedChamferDeclaration
|
|
)
|
|
await editor.expectEditor.toContain(
|
|
standaloneUnassignedChamferDeclaration
|
|
)
|
|
})
|
|
await test.step('Verify test chamfers are present in the scene', async () => {
|
|
await scene.expectPixelColor(
|
|
chamferColor,
|
|
pipedChamferEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
await scene.expectPixelColor(
|
|
backgroundColor,
|
|
standaloneChamferEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
await test.step('Delete piped chamfer', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Chamfer',
|
|
0
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await scene.settled(cmdBar)
|
|
})
|
|
await test.step('Verify piped chamfer is deleted but other chamfers are not (in the editor)', async () => {
|
|
await editor.expectEditor.not.toContain(firstPipedChamferDeclaration)
|
|
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
|
await editor.expectEditor.toContain(
|
|
standaloneAssignedChamferDeclaration
|
|
)
|
|
await editor.expectEditor.toContain(
|
|
standaloneUnassignedChamferDeclaration
|
|
)
|
|
})
|
|
await test.step('Verify piped chamfer is deleted but non-piped is not (in the scene)', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite, // you see edge color because chamfer is deleted
|
|
pipedChamferEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
await scene.expectPixelColor(
|
|
backgroundColor, // you see background color instead of edge because it's chamfered
|
|
standaloneChamferEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
})
|
|
|
|
await test.step('Delete standalone assigned chamfer via feature tree selection', async () => {
|
|
await test.step('Delete standalone assigned chamfer', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Chamfer',
|
|
1
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await scene.settled(cmdBar)
|
|
})
|
|
await test.step('Verify standalone assigned chamfer is deleted but other two chamfers are not (in the editor)', async () => {
|
|
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
|
await editor.expectEditor.not.toContain(
|
|
standaloneAssignedChamferDeclaration
|
|
)
|
|
await editor.expectEditor.toContain(
|
|
standaloneUnassignedChamferDeclaration
|
|
)
|
|
})
|
|
await test.step('Verify standalone assigned chamfer is deleted but piped is not (in the scene)', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
standaloneChamferEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
})
|
|
|
|
await test.step('Delete standalone unassigned chamfer via feature tree selection', async () => {
|
|
await test.step('Delete standalone unassigned chamfer', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Chamfer',
|
|
1
|
|
)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await scene.settled(cmdBar)
|
|
})
|
|
await test.step('Verify standalone unassigned chamfer is deleted but piped chamfer is not (in the editor)', async () => {
|
|
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
|
await editor.expectEditor.not.toContain(
|
|
standaloneUnassignedChamferDeclaration
|
|
)
|
|
})
|
|
await test.step('Verify standalone unassigned chamfer is deleted but piped is not (in the scene)', async () => {
|
|
await scene.expectPixelColor(
|
|
edgeColorWhite,
|
|
standaloneChamferEdgeLocation,
|
|
lowTolerance
|
|
)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
const shellPointAndClickCapCases = [
|
|
{ shouldPreselect: true },
|
|
{ shouldPreselect: false },
|
|
]
|
|
shellPointAndClickCapCases.forEach(({ shouldPreselect }) => {
|
|
test(`Shell point-and-click cap (preselected sketches: ${shouldPreselect})`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `@settings(defaultLengthUnit = in)
|
|
sketch001 = startSketchOn(XZ)
|
|
|> circle(center = [0, 0], radius = 30)
|
|
extrude001 = extrude(sketch001, length = 30)
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
|
|
await homePage.goToModelingScene()
|
|
await scene.connectionEstablished()
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const testPoint = { x: 575, y: 200 }
|
|
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
const shellDeclaration =
|
|
'shell001 = shell(extrude001, faces = [END], thickness = 5)'
|
|
const editedShellDeclaration =
|
|
'shell001 = shell(extrude001, faces = [END], thickness = 2)'
|
|
|
|
await test.step(`Look for the grey of the shape`, async () => {
|
|
await scene.expectPixelColor([127, 127, 127], testPoint, 15)
|
|
})
|
|
|
|
if (!shouldPreselect) {
|
|
await test.step(`Go through the command bar flow without preselected faces`, async () => {
|
|
await toolbar.shellButton.click()
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
Thickness: '',
|
|
},
|
|
highlightedHeaderArg: 'selection',
|
|
commandName: 'Shell',
|
|
})
|
|
await clickOnCap()
|
|
await page.waitForTimeout(500)
|
|
await cmdBar.progressCmdBar()
|
|
await page.waitForTimeout(500)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Selection: '1 cap',
|
|
Thickness: '5',
|
|
},
|
|
commandName: 'Shell',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
} else {
|
|
await test.step(`Preselect the cap`, async () => {
|
|
await clickOnCap()
|
|
await page.waitForTimeout(500)
|
|
})
|
|
|
|
await test.step(`Go through the command bar flow with a preselected face (cap)`, async () => {
|
|
await toolbar.shellButton.click()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Selection: '1 cap',
|
|
Thickness: '5',
|
|
},
|
|
commandName: 'Shell',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
}
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await editor.expectEditor.toContain(shellDeclaration)
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [shellDeclaration],
|
|
highlightedCode: '',
|
|
})
|
|
await scene.expectPixelColor([146, 146, 146], testPoint, 15)
|
|
})
|
|
|
|
await test.step('Edit shell via feature tree selection works', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Shell',
|
|
0
|
|
)
|
|
await operationButton.dblclick()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'thickness',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Thickness: '5',
|
|
},
|
|
highlightedHeaderArg: 'thickness',
|
|
commandName: 'Shell',
|
|
})
|
|
await page.keyboard.insertText('2')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Thickness: '2',
|
|
},
|
|
commandName: 'Shell',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
|
|
await editor.expectEditor.toContain(editedShellDeclaration)
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [editedShellDeclaration],
|
|
highlightedCode: '',
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
test('Shell point-and-click wall', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `@settings(defaultLengthUnit = in)
|
|
sketch001 = startSketchOn(XY)
|
|
|> startProfile(at = [-20, 20])
|
|
|> xLine(length = 40)
|
|
|> yLine(length = -60)
|
|
|> xLine(length = -40)
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
extrude001 = extrude(sketch001, length = 40)
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const testPoint = { x: 580, y: 180 }
|
|
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
const [clickOnWall] = scene.makeMouseHelpers(testPoint.x, testPoint.y + 70)
|
|
const mutatedCode = 'xLine(length = -40, tag = $seg01)'
|
|
const shellDeclaration =
|
|
'shell001 = shell(extrude001, faces = [END, seg01], thickness = 5)'
|
|
const editedShellDeclaration =
|
|
'shell001 = shell(extrude001, faces = [END, seg01], thickness = 1)'
|
|
|
|
await test.step(`Look for the grey of the shape`, async () => {
|
|
await scene.expectPixelColor([99, 99, 99], testPoint, 15)
|
|
})
|
|
|
|
await test.step(`Go through the command bar flow, selecting a wall and keeping default thickness`, async () => {
|
|
await toolbar.shellButton.click()
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
Thickness: '',
|
|
},
|
|
highlightedHeaderArg: 'selection',
|
|
commandName: 'Shell',
|
|
})
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await clickOnCap()
|
|
await page.keyboard.down('Shift')
|
|
await clickOnWall()
|
|
await page.waitForTimeout(500)
|
|
await page.keyboard.up('Shift')
|
|
await cmdBar.progressCmdBar()
|
|
await page.waitForTimeout(500)
|
|
await cmdBar.progressCmdBar()
|
|
await page.waitForTimeout(500)
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Selection: '1 cap, 1 face',
|
|
Thickness: '5',
|
|
},
|
|
commandName: 'Shell',
|
|
})
|
|
await page.waitForTimeout(500)
|
|
await cmdBar.progressCmdBar()
|
|
await page.waitForTimeout(500)
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await editor.expectEditor.toContain(mutatedCode)
|
|
await editor.expectEditor.toContain(shellDeclaration)
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [shellDeclaration],
|
|
highlightedCode: '',
|
|
})
|
|
await scene.expectPixelColor([49, 49, 49], testPoint, 15)
|
|
})
|
|
|
|
await test.step('Edit shell via feature tree selection works', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
|
|
await operationButton.dblclick({ button: 'left' })
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'thickness',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Thickness: '5',
|
|
},
|
|
highlightedHeaderArg: 'thickness',
|
|
commandName: 'Shell',
|
|
})
|
|
await page.keyboard.insertText('1')
|
|
await cmdBar.progressCmdBar()
|
|
await page.waitForTimeout(500)
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Thickness: '1',
|
|
},
|
|
commandName: 'Shell',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
|
|
await editor.expectEditor.toContain(editedShellDeclaration)
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [editedShellDeclaration],
|
|
highlightedCode: '',
|
|
})
|
|
})
|
|
|
|
await test.step('Delete shell via feature tree selection', async () => {
|
|
await editor.closePane()
|
|
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
await scene.expectPixelColor([99, 99, 99], testPoint, 15)
|
|
})
|
|
})
|
|
|
|
const shellSketchOnFacesCases = [
|
|
`@settings(defaultLengthUnit = in)
|
|
sketch001 = startSketchOn(XZ)
|
|
|> circle(center = [0, 0], radius = 100)
|
|
|> extrude(length = 100)
|
|
|
|
sketch002 = startSketchOn(sketch001, face = 'END')
|
|
|> circle(center = [0, 0], radius = 50)
|
|
|> extrude(length = 50)
|
|
`,
|
|
`@settings(defaultLengthUnit = in)
|
|
sketch001 = startSketchOn(XZ)
|
|
|> circle(center = [0, 0], radius = 100)
|
|
extrude001 = extrude(sketch001, length = 100)
|
|
|
|
sketch002 = startSketchOn(extrude001, face = 'END')
|
|
|> circle(center = [0, 0], radius = 50)
|
|
extrude002 = extrude(sketch002, length = 50)
|
|
`,
|
|
]
|
|
shellSketchOnFacesCases.forEach((initialCode, index) => {
|
|
const hasExtrudesInPipe = index === 0
|
|
test(`Shell point-and-click sketch on face (extrudes in pipes: ${hasExtrudesInPipe})`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const testPoint = { x: 580, y: 320 }
|
|
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
const shellTarget = hasExtrudesInPipe ? 'sketch002' : 'extrude002'
|
|
const shellDeclaration = `shell001 = shell(${shellTarget}, faces = [END], thickness = 5)`
|
|
|
|
await test.step(`Look for the grey of the shape`, async () => {
|
|
await scene.expectPixelColor([113, 113, 113], testPoint, 15)
|
|
})
|
|
|
|
await test.step(`Go through the command bar flow, selecting a cap and keeping default thickness`, async () => {
|
|
await toolbar.shellButton.click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
Thickness: '',
|
|
},
|
|
highlightedHeaderArg: 'selection',
|
|
commandName: 'Shell',
|
|
})
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await clickOnCap()
|
|
await page.waitForTimeout(1000)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Selection: '1 cap',
|
|
Thickness: '5',
|
|
},
|
|
commandName: 'Shell',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(shellDeclaration)
|
|
await editor.expectState({
|
|
diagnostics: [],
|
|
activeLines: [shellDeclaration],
|
|
highlightedCode: '',
|
|
})
|
|
await toolbar.closePane('code')
|
|
await scene.expectPixelColor([80, 80, 80], testPoint, 15)
|
|
})
|
|
})
|
|
})
|
|
|
|
const shellPointAndClickDeletionCases = [
|
|
{ shouldUseKeyboard: true },
|
|
{ shouldUseKeyboard: false },
|
|
]
|
|
shellPointAndClickDeletionCases.forEach(({ shouldUseKeyboard }) => {
|
|
test(`Shell point-and-click deletion (shouldUseKeyboard: ${shouldUseKeyboard})`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const sketchCode = `sketch001 = startSketchOn(XY)
|
|
profile001 = startProfile(sketch001, at = [-20, 20])
|
|
|> xLine(length = 40)
|
|
|> yLine(length = -60)
|
|
|> xLine(length = -40)
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
`
|
|
const extrudeCode = `extrude001 = extrude(profile001, length = 40)
|
|
`
|
|
const shellCode = `shell001 = shell(extrude001, faces = [END], thickness = 5)
|
|
`
|
|
const initialCode = sketchCode + extrudeCode + shellCode
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const testPoint = { x: 590, y: 400 }
|
|
const extrudeColor: [number, number, number] = [100, 100, 100]
|
|
const sketchColor: [number, number, number] = [140, 140, 140]
|
|
const defaultPlaneColor: [number, number, number] = [88, 44, 45]
|
|
|
|
const deleteOperation = async (operationButton: Locator) => {
|
|
if (shouldUseKeyboard) {
|
|
await operationButton.click({ button: 'left' })
|
|
await page.keyboard.press('Delete')
|
|
} else {
|
|
await operationButton.click({ button: 'right' })
|
|
const editButton = page.getByTestId('context-menu-delete')
|
|
await editButton.click()
|
|
}
|
|
}
|
|
|
|
await test.step(`Look for the grey of the extrude shape`, async () => {
|
|
await scene.expectPixelColor(extrudeColor, testPoint, 20)
|
|
})
|
|
|
|
await test.step('Delete shell and confirm deletion', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Shell',
|
|
0
|
|
)
|
|
await deleteOperation(operationButton)
|
|
await scene.expectPixelColor(extrudeColor, testPoint, 20)
|
|
await editor.expectEditor.not.toContain(shellCode)
|
|
})
|
|
|
|
await test.step('Delete extrude and confirm deletion', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Extrude',
|
|
0
|
|
)
|
|
await deleteOperation(operationButton)
|
|
await editor.expectEditor.not.toContain(extrudeCode)
|
|
await scene.expectPixelColor(sketchColor, testPoint, 20)
|
|
})
|
|
|
|
await test.step('Delete sketch and confirm empty scene', async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Sketch',
|
|
0
|
|
)
|
|
await deleteOperation(operationButton)
|
|
await editor.expectEditor.toContain('')
|
|
// Cannot use test point anymore because the camera's position has been
|
|
// reset and the rest of the test doesn't need to change just to check
|
|
// if the scene is cleared.
|
|
// Check that the scene is cleared
|
|
await scene.expectPixelColor(defaultPlaneColor, { x: 574, y: 342 }, 20)
|
|
})
|
|
})
|
|
})
|
|
|
|
test.describe('Revolve point and click workflows', () => {
|
|
test('Base case workflow, auto spam continue in command bar', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `
|
|
sketch001 = startSketchOn(XZ)
|
|
|> startProfile(at = [-100.0, 100.0])
|
|
|> angledLine(angle = 0, length = 200.0, tag = $rectangleSegmentA001)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 200, tag = $rectangleSegmentB001)
|
|
|> angledLine(
|
|
angle=segAng(rectangleSegmentA001),
|
|
length=-segLen(rectangleSegmentA001),
|
|
tag=$rectangleSegmentC001,
|
|
)
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
extrude001 = extrude(sketch001, length = 200)
|
|
sketch002 = startSketchOn(extrude001, face = rectangleSegmentA001)
|
|
|> startProfile(at = [-66.77, 84.81])
|
|
|> angledLine(angle = 180, length = 27.08, tag = $rectangleSegmentA002)
|
|
|> angledLine(
|
|
angle=segAng(rectangleSegmentA002) - 90,
|
|
length=27.8,
|
|
tag=$rectangleSegmentB002,
|
|
)
|
|
|> angledLine(
|
|
angle=segAng(rectangleSegmentA002),
|
|
length=-segLen(rectangleSegmentA002),
|
|
tag=$rectangleSegmentC002,
|
|
)
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
`
|
|
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// select line of code
|
|
const codeToSelection = `startProfile(at = [-66.77, 84.81])`
|
|
// revolve
|
|
await editor.scrollToText(codeToSelection)
|
|
await page.getByText(codeToSelection).click()
|
|
// Wait for the selection to register (TODO: we need a definitive way to wait for this)
|
|
await page.waitForTimeout(200)
|
|
await toolbar.revolveButton.click()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
|
|
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = X)`
|
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
|
|
|
// Edit flow
|
|
const newAngle = '90'
|
|
await toolbar.openPane('feature-tree')
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Revolve',
|
|
0
|
|
)
|
|
await operationButton.dblclick({ button: 'left' })
|
|
await cmdBar.expectState({
|
|
commandName: 'Revolve',
|
|
currentArgKey: 'angle',
|
|
currentArgValue: '360',
|
|
headerArguments: {
|
|
Angle: '360',
|
|
},
|
|
highlightedHeaderArg: 'angle',
|
|
stage: 'arguments',
|
|
})
|
|
await page.keyboard.insertText(newAngle)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Angle: newAngle,
|
|
},
|
|
commandName: 'Revolve',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
await editor.expectEditor.toContain(
|
|
newCodeToFind.replace('angle = 360', 'angle = ' + newAngle)
|
|
)
|
|
})
|
|
test('revolve surface around edge from an extruded solid2d', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
|
|> startProfile(at = [-102.57, 101.72])
|
|
|> angledLine(angle = 0, length = 202.6, tag = $rectangleSegmentA001)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 202.6, tag = $rectangleSegmentB001)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001)
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
extrude001 = extrude(sketch001, length = 50)
|
|
sketch002 = startSketchOn(extrude001, face = rectangleSegmentA001)
|
|
|> circle(center = [-11.34, 10.0], radius = 8.69)
|
|
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.connectionEstablished()
|
|
await scene.settled(cmdBar)
|
|
|
|
// select line of code
|
|
const codeToSelection = `center = [-11.34, 10.0]`
|
|
// revolve
|
|
await editor.scrollToText(codeToSelection)
|
|
await page.getByText(codeToSelection).click()
|
|
await toolbar.revolveButton.click()
|
|
await cmdBar.progressCmdBar()
|
|
await page.getByText('Edge', { exact: true }).click()
|
|
const lineCodeToSelection = `angledLine(angle = 0, length = 202.6, tag = $rectangleSegmentA001)`
|
|
await page.getByText(lineCodeToSelection).click()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
|
|
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = rectangleSegmentA001)`
|
|
await editor.expectEditor.toContain(newCodeToFind)
|
|
|
|
// Edit flow
|
|
const newAngle = '180'
|
|
await toolbar.openPane('feature-tree')
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Revolve',
|
|
0
|
|
)
|
|
await operationButton.dblclick({ button: 'left' })
|
|
await cmdBar.expectState({
|
|
commandName: 'Revolve',
|
|
currentArgKey: 'angle',
|
|
currentArgValue: '360',
|
|
headerArguments: {
|
|
Angle: '360',
|
|
},
|
|
highlightedHeaderArg: 'angle',
|
|
stage: 'arguments',
|
|
})
|
|
await page.keyboard.insertText(newAngle)
|
|
await page.getByRole('button', { name: 'Create new variable' }).click()
|
|
await expect(page.getByPlaceholder('Variable name')).toHaveValue(
|
|
'angle001'
|
|
)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Angle: newAngle,
|
|
},
|
|
commandName: 'Revolve',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
await editor.expectEditor.toContain('angle001 = ' + newAngle)
|
|
await editor.expectEditor.toContain(
|
|
newCodeToFind.replace('angle = 360', 'angle = angle001')
|
|
)
|
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
|
})
|
|
test('revolve sketch circle around line segment from startProfileAt sketch', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `
|
|
sketch002 = startSketchOn(XY)
|
|
|> startProfile(at = [-2.02, 1.79])
|
|
|> xLine(length = 2.6)
|
|
sketch001 = startSketchOn(-XY)
|
|
|> startProfile(at = [-0.48, 1.25])
|
|
|> angledLine(angle = 0, length = 2.38, tag = $rectangleSegmentA001)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 2.4, tag = $rectangleSegmentB001)
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001)
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
extrude001 = extrude(sketch001, length = 5)
|
|
sketch003 = startSketchOn(extrude001, face = 'START')
|
|
|> circle(
|
|
center = [-0.69, 0.56],
|
|
radius = 0.28
|
|
)
|
|
`
|
|
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.connectionEstablished()
|
|
await scene.settled(cmdBar)
|
|
|
|
// select line of code
|
|
const codeToSelection = `center = [-0.69, 0.56]`
|
|
// revolve
|
|
await toolbar.revolveButton.click()
|
|
await page.waitForTimeout(1000)
|
|
await editor.scrollToText(codeToSelection)
|
|
await page.getByText(codeToSelection).click()
|
|
await cmdBar.progressCmdBar()
|
|
await expect.poll(() => page.getByText('AxisOrEdge').count()).toBe(2)
|
|
await page.getByText('Edge', { exact: true }).click()
|
|
const lineCodeToSelection = `length = 2.6`
|
|
await editor.scrollToText(lineCodeToSelection)
|
|
await page.getByText(lineCodeToSelection).click()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
|
|
const newCodeToFind = `revolve001 = revolve(sketch003, angle = 360, axis = seg01)`
|
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
|
|
|
// Edit flow
|
|
const newAngle = '270'
|
|
await toolbar.openPane('feature-tree')
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Revolve',
|
|
0
|
|
)
|
|
await operationButton.dblclick({ button: 'left' })
|
|
await cmdBar.expectState({
|
|
commandName: 'Revolve',
|
|
currentArgKey: 'angle',
|
|
currentArgValue: '360',
|
|
headerArguments: {
|
|
Angle: '360',
|
|
},
|
|
highlightedHeaderArg: 'angle',
|
|
stage: 'arguments',
|
|
})
|
|
await page.keyboard.insertText(newAngle)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Angle: newAngle,
|
|
},
|
|
commandName: 'Revolve',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
await editor.expectEditor.toContain(
|
|
newCodeToFind.replace('angle = 360', 'angle = ' + newAngle)
|
|
)
|
|
})
|
|
})
|
|
|
|
test(`Set appearance`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `@settings(defaultLengthUnit = in)
|
|
sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(
|
|
sketch001,
|
|
center = [0, 0],
|
|
radius = 100
|
|
)
|
|
extrude001 = extrude(profile001, length = 100)
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const testPoint = { x: 500, y: 250 }
|
|
const initialColor: [number, number, number] = [123, 123, 123]
|
|
const tolerance = 50
|
|
|
|
await test.step(`Confirm extrude exists with default appearance`, async () => {
|
|
await toolbar.closePane('code')
|
|
await scene.expectPixelColor(initialColor, testPoint, tolerance)
|
|
})
|
|
|
|
async function setAppearanceAndCheck(
|
|
option: string,
|
|
hex: string,
|
|
shapeColor?: [number, number, number]
|
|
) {
|
|
await toolbar.openPane('feature-tree')
|
|
const enterAppearanceFlow = async (stepName: string) =>
|
|
test.step(stepName, async () => {
|
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
|
'Extrude',
|
|
0
|
|
)
|
|
await operationButton.click({ button: 'right' })
|
|
const menuButton = page.getByTestId('context-menu-set-appearance')
|
|
await menuButton.click()
|
|
await cmdBar.expectState({
|
|
commandName: 'Appearance',
|
|
currentArgKey: 'color',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Color: '',
|
|
},
|
|
highlightedHeaderArg: 'color',
|
|
stage: 'arguments',
|
|
})
|
|
})
|
|
|
|
await enterAppearanceFlow(`Open Set Appearance flow`)
|
|
|
|
await test.step(`Validate hidden argument "nodeToEdit" can't be reached with Backspace`, async () => {
|
|
await page.keyboard.press('Shift+Backspace')
|
|
await cmdBar.expectState({
|
|
stage: 'pickCommand',
|
|
})
|
|
await page.keyboard.press('Escape')
|
|
await cmdBar.expectState({
|
|
stage: 'commandBarClosed',
|
|
})
|
|
})
|
|
|
|
await enterAppearanceFlow(`Restart Appearance flow`)
|
|
const item = page.getByText(option, { exact: true })
|
|
await item.click()
|
|
await cmdBar.expectState({
|
|
commandName: 'Appearance',
|
|
headerArguments: {
|
|
Color: hex,
|
|
},
|
|
stage: 'review',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
if (shapeColor) {
|
|
await scene.expectPixelColor(shapeColor, testPoint, tolerance)
|
|
}
|
|
await toolbar.openPane('code')
|
|
if (hex === 'default') {
|
|
const anyAppearanceDeclaration = `|> appearance(`
|
|
await editor.expectEditor.not.toContain(anyAppearanceDeclaration)
|
|
} else {
|
|
const declaration = `|> appearance(%, color = '${hex}')`
|
|
await editor.expectEditor.toContain(declaration)
|
|
// TODO: fix selection range after appearance update
|
|
// await editor.expectState({
|
|
// diagnostics: [],
|
|
// activeLines: [declaration],
|
|
// highlightedCode: '',
|
|
// })
|
|
}
|
|
await toolbar.closePane('code')
|
|
}
|
|
|
|
await test.step(`Go through the Set Appearance flow for all options`, async () => {
|
|
await setAppearanceAndCheck('Red', '#FF0000', [180, 30, 30])
|
|
// Not checking the scene color every time cause that's not really deterministic. Red seems reliable though
|
|
await setAppearanceAndCheck('Green', '#00FF00')
|
|
await setAppearanceAndCheck('Blue', '#0000FF')
|
|
await setAppearanceAndCheck('Turquoise', '#00FFFF')
|
|
await setAppearanceAndCheck('Purple', '#FF00FF')
|
|
await setAppearanceAndCheck('Yellow', '#FFFF00')
|
|
await setAppearanceAndCheck('Black', '#000000')
|
|
await setAppearanceAndCheck('Dark Grey', '#080808')
|
|
await setAppearanceAndCheck('Light Grey', '#D3D3D3')
|
|
await setAppearanceAndCheck('White', '#FFFFFF')
|
|
await setAppearanceAndCheck(
|
|
'Default (clear appearance)',
|
|
'default',
|
|
initialColor
|
|
)
|
|
})
|
|
})
|
|
|
|
const translateExtrudeCases: { variables: boolean }[] = [
|
|
{
|
|
variables: false,
|
|
},
|
|
{
|
|
variables: true,
|
|
},
|
|
]
|
|
translateExtrudeCases.map(({ variables }) => {
|
|
test(`Set translate on extrude through right-click menu (variables: ${variables})`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const midPoint = { x: 500, y: 250 }
|
|
const moreToTheRightPoint = { x: 800, y: 250 }
|
|
const bgColor: [number, number, number] = [50, 50, 50]
|
|
const partColor: [number, number, number] = [150, 150, 150]
|
|
const tolerance = 50
|
|
|
|
await test.step('Confirm extrude exists with default appearance', async () => {
|
|
await toolbar.closePane('code')
|
|
await scene.expectPixelColor(partColor, midPoint, tolerance)
|
|
await scene.expectPixelColor(bgColor, moreToTheRightPoint, tolerance)
|
|
})
|
|
|
|
await test.step('Set translate through command bar flow', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const op = await toolbar.getFeatureTreeOperation('Extrude', 0)
|
|
await op.click({ button: 'right' })
|
|
await page.getByTestId('context-menu-set-translate').click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'x',
|
|
currentArgValue: '0',
|
|
headerArguments: {
|
|
X: '',
|
|
Y: '',
|
|
Z: '',
|
|
},
|
|
highlightedHeaderArg: 'x',
|
|
commandName: 'Translate',
|
|
})
|
|
await page.keyboard.insertText('3')
|
|
if (variables) {
|
|
await cmdBar.createNewVariable()
|
|
}
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('0.1')
|
|
if (variables) {
|
|
await cmdBar.createNewVariable()
|
|
}
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('0.2')
|
|
if (variables) {
|
|
await cmdBar.createNewVariable()
|
|
}
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
X: '3',
|
|
Y: '0.1',
|
|
Z: '0.2',
|
|
},
|
|
commandName: 'Translate',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
})
|
|
|
|
await test.step('Confirm code and scene have changed', async () => {
|
|
await toolbar.openPane('code')
|
|
if (variables) {
|
|
await editor.expectEditor.toContain(
|
|
`
|
|
z001 = 0.2
|
|
y001 = 0.1
|
|
x001 = 3
|
|
sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
|> translate(x = x001, y = y001, z = z001)
|
|
`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
} else {
|
|
await editor.expectEditor.toContain(
|
|
`
|
|
sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
|> translate(x = 3, y = 0.1, z = 0.2)
|
|
`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
}
|
|
await scene.expectPixelColor(bgColor, midPoint, tolerance)
|
|
await scene.expectPixelColor(partColor, moreToTheRightPoint, tolerance)
|
|
})
|
|
|
|
await test.step('Edit translate', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const op = await toolbar.getFeatureTreeOperation('Extrude', 0)
|
|
await op.click({ button: 'right' })
|
|
await page.getByTestId('context-menu-set-translate').click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'z',
|
|
currentArgValue: variables ? 'z001' : '0.2',
|
|
headerArguments: {
|
|
X: '3',
|
|
Y: '0.1',
|
|
Z: '0.2',
|
|
},
|
|
highlightedHeaderArg: 'z',
|
|
commandName: 'Translate',
|
|
})
|
|
await page.keyboard.insertText('0.3')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
X: '3',
|
|
Y: '0.1',
|
|
Z: '0.3',
|
|
},
|
|
commandName: 'Translate',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(`z = 0.3`)
|
|
// Expect almost no change in scene
|
|
await scene.expectPixelColor(bgColor, midPoint, tolerance)
|
|
await scene.expectPixelColor(partColor, moreToTheRightPoint, tolerance)
|
|
})
|
|
})
|
|
})
|
|
|
|
const rotateExtrudeCases: { variables: boolean }[] = [
|
|
{
|
|
variables: false,
|
|
},
|
|
{
|
|
variables: true,
|
|
},
|
|
]
|
|
rotateExtrudeCases.map(({ variables }) => {
|
|
test(`Set rotate on extrude through right-click menu (variables: ${variables})`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
await test.step('Set rotate through command bar flow', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const op = await toolbar.getFeatureTreeOperation('Extrude', 0)
|
|
await op.click({ button: 'right' })
|
|
await page.getByTestId('context-menu-set-rotate').click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'roll',
|
|
currentArgValue: '0',
|
|
headerArguments: {
|
|
Roll: '',
|
|
Pitch: '',
|
|
Yaw: '',
|
|
},
|
|
highlightedHeaderArg: 'roll',
|
|
commandName: 'Rotate',
|
|
})
|
|
await page.keyboard.insertText('1.1')
|
|
if (variables) {
|
|
await cmdBar.createNewVariable()
|
|
}
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('1.2')
|
|
if (variables) {
|
|
await cmdBar.createNewVariable()
|
|
}
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('1.3')
|
|
if (variables) {
|
|
await cmdBar.createNewVariable()
|
|
}
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Roll: '1.1',
|
|
Pitch: '1.2',
|
|
Yaw: '1.3',
|
|
},
|
|
commandName: 'Rotate',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
})
|
|
|
|
await test.step('Confirm code and scene have changed', async () => {
|
|
await toolbar.openPane('code')
|
|
if (variables) {
|
|
await editor.expectEditor.toContain(
|
|
`
|
|
yaw001 = 1.3
|
|
pitch001 = 1.2
|
|
roll001 = 1.1
|
|
sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
|> rotate(roll = roll001, pitch = pitch001, yaw = yaw001)
|
|
`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
} else {
|
|
await editor.expectEditor.toContain(
|
|
`
|
|
sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
|> rotate(roll = 1.1, pitch = 1.2, yaw = 1.3)
|
|
`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
}
|
|
})
|
|
|
|
await test.step('Edit rotate', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const op = await toolbar.getFeatureTreeOperation('Extrude', 0)
|
|
await op.click({ button: 'right' })
|
|
await page.getByTestId('context-menu-set-rotate').click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'yaw',
|
|
currentArgValue: variables ? 'yaw001' : '1.3',
|
|
headerArguments: {
|
|
Roll: '1.1',
|
|
Pitch: '1.2',
|
|
Yaw: '1.3',
|
|
},
|
|
highlightedHeaderArg: 'yaw',
|
|
commandName: 'Rotate',
|
|
})
|
|
await page.keyboard.insertText('13')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Roll: '1.1',
|
|
Pitch: '1.2',
|
|
Yaw: '13',
|
|
},
|
|
commandName: 'Rotate',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await toolbar.closePane('feature-tree')
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(`yaw = 13`)
|
|
})
|
|
})
|
|
})
|
|
|
|
test(`Set translate and rotate on extrude through selection`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const midPoint = { x: 500, y: 250 }
|
|
const moreToTheRightPoint = { x: 800, y: 250 }
|
|
const bgColor: [number, number, number] = [50, 50, 50]
|
|
const partColor: [number, number, number] = [150, 150, 150]
|
|
const tolerance = 50
|
|
const [clickMidPoint] = scene.makeMouseHelpers(midPoint.x, midPoint.y)
|
|
const [clickMoreToTheRightPoint] = scene.makeMouseHelpers(
|
|
moreToTheRightPoint.x,
|
|
moreToTheRightPoint.y
|
|
)
|
|
|
|
await test.step('Confirm extrude exists with default appearance', async () => {
|
|
await toolbar.closePane('code')
|
|
await scene.expectPixelColor(partColor, midPoint, tolerance)
|
|
await scene.expectPixelColor(bgColor, moreToTheRightPoint, tolerance)
|
|
})
|
|
|
|
await test.step('Set translate through command bar flow', async () => {
|
|
await cmdBar.openCmdBar()
|
|
await cmdBar.chooseCommand('Translate')
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
X: '',
|
|
Y: '',
|
|
Z: '',
|
|
},
|
|
highlightedHeaderArg: 'selection',
|
|
commandName: 'Translate',
|
|
})
|
|
await clickMidPoint()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'x',
|
|
currentArgValue: '0',
|
|
headerArguments: {
|
|
Selection: '1 path',
|
|
X: '',
|
|
Y: '',
|
|
Z: '',
|
|
},
|
|
highlightedHeaderArg: 'x',
|
|
commandName: 'Translate',
|
|
})
|
|
await page.keyboard.insertText('2')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Selection: '1 path',
|
|
X: '2',
|
|
Y: '0',
|
|
Z: '0',
|
|
},
|
|
commandName: 'Translate',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step('Confirm code and scene have changed', async () => {
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(
|
|
`
|
|
sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
|> translate(x = 2, y = 0, z = 0)
|
|
`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
await scene.expectPixelColor(bgColor, midPoint, tolerance)
|
|
await scene.expectPixelColor(partColor, moreToTheRightPoint, tolerance)
|
|
})
|
|
|
|
await test.step('Set rotate through command bar flow', async () => {
|
|
// clear selection
|
|
await clickMidPoint()
|
|
await cmdBar.openCmdBar()
|
|
await cmdBar.chooseCommand('Rotate')
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
Roll: '',
|
|
Pitch: '',
|
|
Yaw: '',
|
|
},
|
|
highlightedHeaderArg: 'selection',
|
|
commandName: 'Rotate',
|
|
})
|
|
await clickMoreToTheRightPoint()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'roll',
|
|
currentArgValue: '0',
|
|
headerArguments: {
|
|
Selection: '1 path',
|
|
Roll: '',
|
|
Pitch: '',
|
|
Yaw: '',
|
|
},
|
|
highlightedHeaderArg: 'roll',
|
|
commandName: 'Rotate',
|
|
})
|
|
await page.keyboard.insertText('0.1')
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('0.2')
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('0.3')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Selection: '1 path',
|
|
Roll: '0.1',
|
|
Pitch: '0.2',
|
|
Yaw: '0.3',
|
|
},
|
|
commandName: 'Rotate',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
})
|
|
|
|
await test.step('Confirm code has changed', async () => {
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(
|
|
`
|
|
sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
|> translate(x = 2, y = 0, z = 0)
|
|
|> rotate(roll = 0.1, pitch = 0.2, yaw = 0.3)
|
|
`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
// No change here since the angles are super small
|
|
await scene.expectPixelColor(bgColor, midPoint, tolerance)
|
|
await scene.expectPixelColor(partColor, moreToTheRightPoint, tolerance)
|
|
})
|
|
})
|
|
|
|
test('Point-and-click Clone extrude through selection', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, initialCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
// One dumb hardcoded screen pixel value
|
|
const midPoint = { x: 500, y: 250 }
|
|
const [clickMidPoint] = scene.makeMouseHelpers(midPoint.x, midPoint.y)
|
|
|
|
await test.step('Clone through command bar flow', async () => {
|
|
await toolbar.closePane('code')
|
|
await cmdBar.openCmdBar()
|
|
await cmdBar.chooseCommand('Clone a solid or sketch')
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
VariableName: '',
|
|
},
|
|
highlightedHeaderArg: 'selection',
|
|
commandName: 'Clone',
|
|
})
|
|
await clickMidPoint()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'variableName',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '1 path',
|
|
VariableName: '',
|
|
},
|
|
highlightedHeaderArg: 'variableName',
|
|
commandName: 'Clone',
|
|
})
|
|
await page.keyboard.insertText('yoyoyo')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Selection: '1 path',
|
|
VariableName: 'yoyoyo',
|
|
},
|
|
commandName: 'Clone',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
|
|
// Expect changes
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(
|
|
`
|
|
sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001, length = 1)
|
|
yoyoyo = clone(extrude001)
|
|
`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
})
|
|
})
|
|
|
|
const multiProfileSweepsCode = `sketch001 = startSketchOn(XY)
|
|
profile001 = circle(sketch001, center = [3, 0], radius = 1)
|
|
profile002 = circle(sketch001, center = [6, 0], radius = 1)
|
|
path001 = startProfile(sketch001, at = [0, 0])
|
|
|> yLine(length = 2)
|
|
`
|
|
const profile001Point = { x: 470, y: 270 }
|
|
const profile002Point = { x: 670, y: 270 }
|
|
|
|
test('Point-and-click multi-profile sweeps: extrude', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, multiProfileSweepsCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
await test.step('Select through scene', async () => {
|
|
// Unfortunately can't select thru code for multi profile yet
|
|
const [clickProfile001Point] = scene.makeMouseHelpers(
|
|
profile001Point.x,
|
|
profile001Point.y
|
|
)
|
|
const [clickProfile002Point] = scene.makeMouseHelpers(
|
|
profile002Point.x,
|
|
profile002Point.y
|
|
)
|
|
await toolbar.closePane('code')
|
|
await clickProfile001Point()
|
|
await page.keyboard.down('Shift')
|
|
await clickProfile002Point()
|
|
await page.waitForTimeout(500)
|
|
await page.keyboard.up('Shift')
|
|
})
|
|
|
|
await test.step('Go through command bar flow', async () => {
|
|
await toolbar.extrudeButton.click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'length',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Profiles: '2 profiles',
|
|
Length: '',
|
|
},
|
|
highlightedHeaderArg: 'length',
|
|
commandName: 'Extrude',
|
|
})
|
|
await page.keyboard.insertText('1')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Profiles: '2 profiles',
|
|
Length: '1',
|
|
},
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(
|
|
`extrude001 = extrude([profile001, profile002], length = 1)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
await editor.closePane()
|
|
})
|
|
|
|
await test.step('Delete extrude via feature tree selection', async () => {
|
|
const op = await toolbar.getFeatureTreeOperation('Extrude', 0)
|
|
await op.click({ button: 'right' })
|
|
await page.getByTestId('context-menu-delete').click()
|
|
await scene.settled(cmdBar)
|
|
await toolbar.closePane('feature-tree')
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.not.toContain(
|
|
`extrude001 = extrude([profile001, profile002], length = 1)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
})
|
|
})
|
|
|
|
test('Point-and-click multi-profile sweeps: sweep', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, multiProfileSweepsCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
await test.step('Select through scene', async () => {
|
|
// Unfortunately can't select thru code for multi profile yet
|
|
const [clickProfile001Point] = scene.makeMouseHelpers(
|
|
profile001Point.x,
|
|
profile001Point.y
|
|
)
|
|
const [clickProfile002Point] = scene.makeMouseHelpers(
|
|
profile002Point.x,
|
|
profile002Point.y
|
|
)
|
|
await toolbar.closePane('code')
|
|
await clickProfile001Point()
|
|
await page.keyboard.down('Shift')
|
|
await clickProfile002Point()
|
|
await page.waitForTimeout(500)
|
|
await page.keyboard.up('Shift')
|
|
})
|
|
|
|
await test.step('Go through command bar flow', async () => {
|
|
await toolbar.sweepButton.click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'path',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Profiles: '2 profiles',
|
|
Path: '',
|
|
Sectional: '',
|
|
},
|
|
highlightedHeaderArg: 'path',
|
|
commandName: 'Sweep',
|
|
})
|
|
await toolbar.openPane('code')
|
|
await page.getByText('yLine(length = 2)').click()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Profiles: '2 profiles',
|
|
Path: '1 segment',
|
|
Sectional: '',
|
|
},
|
|
commandName: 'Sweep',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(
|
|
`sweep001 = sweep([profile001, profile002], path = path001)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
})
|
|
|
|
await test.step('Delete sweep via feature tree selection', async () => {
|
|
await editor.closePane()
|
|
const op = await toolbar.getFeatureTreeOperation('Sweep', 0)
|
|
await op.click({ button: 'right' })
|
|
await page.getByTestId('context-menu-delete').click()
|
|
await scene.settled(cmdBar)
|
|
await editor.expectEditor.not.toContain(
|
|
`sweep001 = sweep([profile001, profile002], path = path001)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
})
|
|
})
|
|
|
|
test('Point-and-click multi-profile sweeps: revolve', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, multiProfileSweepsCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
await test.step('Select through scene', async () => {
|
|
// Unfortunately can't select thru code for multi profile yet
|
|
const [clickProfile001Point] = scene.makeMouseHelpers(
|
|
profile001Point.x,
|
|
profile001Point.y
|
|
)
|
|
const [clickProfile002Point] = scene.makeMouseHelpers(
|
|
profile002Point.x,
|
|
profile002Point.y
|
|
)
|
|
await toolbar.closePane('code')
|
|
await clickProfile001Point()
|
|
await page.keyboard.down('Shift')
|
|
await clickProfile002Point()
|
|
await page.waitForTimeout(500)
|
|
await page.keyboard.up('Shift')
|
|
})
|
|
|
|
await test.step('Go through command bar flow', async () => {
|
|
await toolbar.closePane('code')
|
|
await toolbar.revolveButton.click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'axisOrEdge',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Profiles: '2 profiles',
|
|
AxisOrEdge: '',
|
|
Angle: '',
|
|
},
|
|
highlightedHeaderArg: 'axisOrEdge',
|
|
commandName: 'Revolve',
|
|
})
|
|
await cmdBar.selectOption({ name: 'Edge' }).click()
|
|
await toolbar.openPane('code')
|
|
await page.getByText('yLine(length = 2)').click()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'angle',
|
|
currentArgValue: '360',
|
|
headerArguments: {
|
|
Profiles: '2 profiles',
|
|
AxisOrEdge: 'Edge',
|
|
Edge: '1 segment',
|
|
Angle: '',
|
|
},
|
|
highlightedHeaderArg: 'angle',
|
|
commandName: 'Revolve',
|
|
})
|
|
await page.keyboard.insertText('180')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Profiles: '2 profiles',
|
|
AxisOrEdge: 'Edge',
|
|
Edge: '1 segment',
|
|
Angle: '180',
|
|
},
|
|
commandName: 'Revolve',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await scene.settled(cmdBar)
|
|
|
|
await editor.expectEditor.toContain(`yLine(length = 2, tag = $seg01)`, {
|
|
shouldNormalise: true,
|
|
})
|
|
await editor.expectEditor.toContain(
|
|
`revolve001 = revolve([profile001, profile002], angle=180, axis=seg01)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
})
|
|
|
|
await test.step('Delete revolve via feature tree selection', async () => {
|
|
await editor.closePane()
|
|
const op = await toolbar.getFeatureTreeOperation('Revolve', 0)
|
|
await op.click({ button: 'right' })
|
|
await page.getByTestId('context-menu-delete').click()
|
|
await scene.settled(cmdBar)
|
|
await editor.expectEditor.not.toContain(
|
|
`revolve001 = revolve([profile001, profile002], axis = XY, angle = 180)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
})
|
|
})
|
|
|
|
test(`Point and click codemods can't run on KCL errors`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const badCode = `sketch001 = startSketchOn(XZ)
|
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
|
extrude001 = extrude(profile001 length = 1)`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, badCode)
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
await homePage.goToModelingScene()
|
|
await scene.connectionEstablished()
|
|
|
|
await test.step(`Start Sketch is disabled`, async () => {
|
|
await expect(toolbar.startSketchBtn).not.toBeEnabled()
|
|
await editor.expectEditor.toContain(badCode, { shouldNormalise: true })
|
|
})
|
|
|
|
await test.step(`Helix is disabled`, async () => {
|
|
await expect(toolbar.helixButton).not.toBeEnabled()
|
|
await editor.expectEditor.toContain(badCode, { shouldNormalise: true })
|
|
})
|
|
})
|
|
})
|