* Add display of units in UI modals with calculated KCL values * Fix command bar display to handle units * Add display of units in the command bar * Fix more cases of NaN from units * Fix to support explicit plus for exponent in scientific notation * Fix display in autocomplete * Change to parseFloat to be more resilient * Add e2e test for command bar * Change an existing test to use explicit inline units * Fix case when input string can't be parsed
5141 lines
168 KiB
TypeScript
5141 lines
168 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'
|
|
import type { CmdBarSerialised } from '@e2e/playwright/fixtures/cmdBarFixture'
|
|
|
|
// 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: 'sketches',
|
|
currentArgValue: '',
|
|
headerArguments: { Profiles: '', Length: '' },
|
|
highlightedHeaderArg: 'Profiles',
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
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.001in')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Length: '4.999in',
|
|
},
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await editor.expectEditor.toContain('extrude(length = width - 0.001in)')
|
|
})
|
|
|
|
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: 200 }
|
|
// TODO: replace the testPoint selection with a feature tree click once that's supported #7544
|
|
const [clickOnXzPlane] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
const expectedOutput = `plane001 = offsetPlane(XZ, offset = 5)`
|
|
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
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
|
|
})
|
|
})
|
|
|
|
const initialCmdBarStateHelix: CmdBarSerialised = {
|
|
stage: 'arguments',
|
|
currentArgKey: 'mode',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Mode: '',
|
|
AngleStart: '',
|
|
Revolutions: '',
|
|
Radius: '',
|
|
},
|
|
highlightedHeaderArg: 'mode',
|
|
commandName: 'Helix',
|
|
}
|
|
|
|
test('Helix point-and-click on default axis', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const expectedOutput = `helix001 = helix( axis = X, radius = 5, length = 5, revolutions = 1, angleStart = 270,)`
|
|
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(initialCmdBarStateHelix)
|
|
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: '',
|
|
},
|
|
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',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.submit()
|
|
})
|
|
|
|
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()
|
|
const initialInput = '5'
|
|
const newInput = '50'
|
|
await cmdBar.expectState({
|
|
commandName: 'Helix',
|
|
stage: 'arguments',
|
|
currentArgKey: 'length',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Axis: 'X',
|
|
AngleStart: '270',
|
|
Revolutions: '1',
|
|
Radius: '5',
|
|
Length: initialInput,
|
|
},
|
|
highlightedHeaderArg: 'length',
|
|
})
|
|
await page.keyboard.insertText(newInput)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Axis: 'X',
|
|
AngleStart: '270',
|
|
Revolutions: '1',
|
|
Radius: '5',
|
|
Length: newInput,
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.submit()
|
|
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')
|
|
await scene.settled(cmdBar)
|
|
await editor.expectEditor.not.toContain('helix')
|
|
await expect(
|
|
await toolbar.getFeatureTreeOperation('Helix', 0)
|
|
).not.toBeVisible()
|
|
})
|
|
})
|
|
|
|
test(`Helix point-and-click around segment`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const initialCode = `sketch001 = startSketchOn(XZ)
|
|
profile001 = startProfile(sketch001, at = [0, 0])
|
|
|> yLine(length = 100)
|
|
|> line(endAbsolute = [100, 0])
|
|
|> 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)
|
|
|
|
await test.step(`Go through the command bar flow`, async () => {
|
|
await toolbar.closePane('code')
|
|
await toolbar.helixButton.click()
|
|
await cmdBar.expectState(initialCmdBarStateHelix)
|
|
await cmdBar.selectOption({ name: 'Edge' }).click()
|
|
await editor.selectText('yLine(length = 100)')
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('1')
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('2')
|
|
await cmdBar.progressCmdBar()
|
|
await page.keyboard.insertText('3')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Mode: 'Edge',
|
|
Edge: `1 segment`,
|
|
AngleStart: '2',
|
|
Revolutions: '1',
|
|
Radius: '3',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.submit()
|
|
await scene.settled(cmdBar)
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(
|
|
`
|
|
helix001 = helix(
|
|
axis = seg01,
|
|
radius = 3,
|
|
revolutions = 1,
|
|
angleStart = 2,
|
|
)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
await toolbar.closePane('code')
|
|
})
|
|
})
|
|
|
|
test(`Helix point-and-click around sweepEdge with edit and delete flows`, async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
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 to click on the sweepEdge, can't think of another way?
|
|
const testPoint = { x: 564, y: 364 }
|
|
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(initialCmdBarStateHelix)
|
|
await cmdBar.selectOption({ name: 'Edge' }).click()
|
|
await expect
|
|
.poll(() => page.getByText('Please select one').count())
|
|
.toBe(1)
|
|
await clickOnEdge()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.argumentInput.focus()
|
|
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 sweepEdge`,
|
|
AngleStart: '0',
|
|
Revolutions: '20',
|
|
Radius: '1',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.submit()
|
|
await scene.settled(cmdBar)
|
|
})
|
|
|
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(
|
|
`
|
|
helix001 = helix(
|
|
axis = getOppositeEdge(seg01),
|
|
radius = 1,
|
|
revolutions = 20,
|
|
angleStart = 0,
|
|
)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
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: 'radius',
|
|
currentArgValue: initialInput,
|
|
headerArguments: {
|
|
AngleStart: '0',
|
|
Revolutions: '20',
|
|
Radius: initialInput,
|
|
},
|
|
highlightedHeaderArg: 'radius',
|
|
})
|
|
await page.keyboard.insertText(newInput)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
AngleStart: '0',
|
|
Revolutions: '20',
|
|
Radius: newInput,
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.clickOptionalArgument('ccw')
|
|
await cmdBar.expectState({
|
|
commandName: 'Helix',
|
|
stage: 'arguments',
|
|
currentArgKey: 'CounterClockWise',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
AngleStart: '0',
|
|
Revolutions: '20',
|
|
Radius: newInput,
|
|
CounterClockWise: '',
|
|
},
|
|
highlightedHeaderArg: 'CounterClockWise',
|
|
})
|
|
await cmdBar.selectOption({ name: 'True' }).click()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
AngleStart: '0',
|
|
Revolutions: '20',
|
|
Radius: newInput,
|
|
CounterClockWise: '',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.submit()
|
|
await toolbar.closePane('feature-tree')
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(
|
|
`
|
|
helix001 = helix(
|
|
axis = getOppositeEdge(seg01),
|
|
radius = 5,
|
|
revolutions = 20,
|
|
angleStart = 0,
|
|
ccw = true,
|
|
)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
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('helix')
|
|
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)`
|
|
const expectedEditedOutput = `helix001 = helix(cylinder = extrude001, revolutions = 1, angleStart = 10)`
|
|
|
|
await test.step(`Go through the command bar flow`, async () => {
|
|
await toolbar.helixButton.click()
|
|
await cmdBar.expectState(initialCmdBarStateHelix)
|
|
await cmdBar.selectOption({ name: 'Cylinder' }).click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'cylinder',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Mode: 'Cylinder',
|
|
Cylinder: '',
|
|
AngleStart: '',
|
|
Revolutions: '',
|
|
},
|
|
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',
|
|
},
|
|
commandName: 'Helix',
|
|
})
|
|
await cmdBar.submit()
|
|
})
|
|
|
|
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 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: 'angleStart',
|
|
currentArgValue: '360',
|
|
headerArguments: {
|
|
AngleStart: '360',
|
|
Revolutions: '1',
|
|
},
|
|
highlightedHeaderArg: 'angleStart',
|
|
})
|
|
await page.keyboard.insertText('10')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
AngleStart: '10',
|
|
Revolutions: '1',
|
|
},
|
|
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])'
|
|
const editedLoftDeclaration =
|
|
'loft001 = loft([sketch001, sketch002], vDegree = 3)'
|
|
|
|
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: 'arguments',
|
|
currentArgKey: 'sketches',
|
|
currentArgValue: '',
|
|
headerArguments: { Profiles: '' },
|
|
highlightedHeaderArg: 'Profiles',
|
|
commandName: 'Loft',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
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('Go through the edit flow via feature tree', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const op = await toolbar.getFeatureTreeOperation('Loft', 0)
|
|
await op.dblclick()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {},
|
|
commandName: 'Loft',
|
|
})
|
|
await cmdBar.clickOptionalArgument('vDegree')
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'vDegree',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
VDegree: '',
|
|
},
|
|
highlightedHeaderArg: 'vDegree',
|
|
commandName: 'Loft',
|
|
})
|
|
await page.keyboard.insertText('3')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
VDegree: '3',
|
|
},
|
|
commandName: 'Loft',
|
|
})
|
|
await cmdBar.submit()
|
|
await editor.expectEditor.toContain(editedLoftDeclaration)
|
|
})
|
|
|
|
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)
|
|
})
|
|
})
|
|
})
|
|
|
|
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)
|
|
profile002 = startProfile(sketch002, 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)
|
|
profile002 = startProfile(sketch002, 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 = profile002)'
|
|
const editedSweepDeclaration =
|
|
'sweep001 = sweep(profile001, path = profile002, 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: {
|
|
Profiles: '',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'Profiles',
|
|
stage: 'arguments',
|
|
})
|
|
await clickOnSketch1()
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
currentArgKey: 'path',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Profiles: '1 profile',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'path',
|
|
stage: 'arguments',
|
|
})
|
|
await clickOnSketch2()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
currentArgKey: 'path',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Profiles: '1 profile',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'path',
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
headerArguments: {
|
|
Profiles: '1 profile',
|
|
Path: '1 segment',
|
|
},
|
|
stage: 'review',
|
|
})
|
|
// Confirm we can submit from the review step with just `Enter`
|
|
await cmdBar.progressCmdBar(true)
|
|
await cmdBar.expectState({
|
|
stage: 'commandBarClosed',
|
|
})
|
|
})
|
|
|
|
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 page
|
|
.getByRole('button', { name: 'sectional', exact: false })
|
|
.click()
|
|
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)'
|
|
const editedSweepDeclaration = `sweep001 = sweep(profile001, path = helix001, relativeTo = 'sketchPlane')`
|
|
|
|
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: {
|
|
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: {
|
|
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: {
|
|
Profiles: '1 profile',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'path',
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
commandName: 'Sweep',
|
|
headerArguments: {
|
|
Profiles: '1 profile',
|
|
Path: '1 helix',
|
|
},
|
|
stage: 'review',
|
|
})
|
|
await cmdBar.progressCmdBar(true)
|
|
await editor.expectEditor.toContain(sweepDeclaration)
|
|
})
|
|
|
|
await test.step('Go through the edit flow via feature tree', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const op = await toolbar.getFeatureTreeOperation('Sweep', 0)
|
|
await op.dblclick()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {},
|
|
commandName: 'Sweep',
|
|
})
|
|
await cmdBar.clickOptionalArgument('relativeTo')
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'relativeTo',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
RelativeTo: '',
|
|
},
|
|
highlightedHeaderArg: 'relativeTo',
|
|
commandName: 'Sweep',
|
|
})
|
|
await cmdBar.selectOption({ name: 'sketchPlane' }).click()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
RelativeTo: 'sketchPlane',
|
|
},
|
|
commandName: 'Sweep',
|
|
})
|
|
await cmdBar.submit()
|
|
await editor.expectEditor.toContain(editedSweepDeclaration)
|
|
})
|
|
|
|
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(editedSweepDeclaration)
|
|
})
|
|
})
|
|
|
|
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: '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 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: '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',
|
|
})
|
|
// 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: 'selection',
|
|
currentArgKey: 'selection',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Selection: '',
|
|
Length: '',
|
|
},
|
|
stage: 'arguments',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await page.waitForTimeout(1000)
|
|
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 page.waitForTimeout(500)
|
|
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()
|
|
await toolbar.revolveButton.click()
|
|
await cmdBar.progressCmdBar()
|
|
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 cmdBar.variableCheckbox.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'
|
|
const newAngle2 = '5'
|
|
const editedCodeToFind = `revolve001 = revolve(sketch003, angle = ${newAngle}, axis = seg01, bidirectionalAngle = ${newAngle2}, )`
|
|
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.clickOptionalArgument('bidirectionalAngle')
|
|
await cmdBar.expectState({
|
|
commandName: 'Revolve',
|
|
currentArgKey: 'bidirectionalAngle',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Angle: newAngle,
|
|
BidirectionalAngle: '',
|
|
},
|
|
highlightedHeaderArg: 'bidirectionalAngle',
|
|
stage: 'arguments',
|
|
})
|
|
await page.keyboard.insertText(newAngle2)
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Angle: newAngle,
|
|
BidirectionalAngle: newAngle2,
|
|
},
|
|
commandName: 'Revolve',
|
|
})
|
|
await cmdBar.submit()
|
|
await toolbar.closePane('feature-tree')
|
|
await editor.expectEditor.toContain(editedCodeToFind, {
|
|
shouldNormalise: true,
|
|
})
|
|
})
|
|
})
|
|
|
|
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: 'sketches',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Profiles: '',
|
|
Length: '',
|
|
},
|
|
highlightedHeaderArg: 'Profiles',
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
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: 'sketches',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Profiles: '',
|
|
Path: '',
|
|
},
|
|
highlightedHeaderArg: 'Profiles',
|
|
commandName: 'Sweep',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'path',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Profiles: '2 profiles',
|
|
Path: '',
|
|
},
|
|
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',
|
|
},
|
|
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: 'sketches',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Profiles: '',
|
|
AxisOrEdge: '',
|
|
Angle: '',
|
|
},
|
|
highlightedHeaderArg: 'Profiles',
|
|
commandName: 'Revolve',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
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 })
|
|
})
|
|
})
|
|
|
|
test('Point-and-click extrude with optional args', async ({
|
|
context,
|
|
page,
|
|
homePage,
|
|
scene,
|
|
editor,
|
|
toolbar,
|
|
cmdBar,
|
|
}) => {
|
|
const squareProfileCode = `length001 = 100
|
|
sketch001 = startSketchOn(XY)
|
|
profile001 = startProfile(sketch001, at = [0, 0])
|
|
|> yLine(length = length001)
|
|
|> xLine(length = length001)
|
|
|> yLine(length = -length001)
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|> close()
|
|
`
|
|
await context.addInitScript((initialCode) => {
|
|
localStorage.setItem('persistCode', initialCode)
|
|
}, squareProfileCode)
|
|
await homePage.goToModelingScene()
|
|
await scene.settled(cmdBar)
|
|
|
|
await test.step('Select through code', async () => {
|
|
await editor.selectText('startProfile(sketch001, at = [0, 0])')
|
|
})
|
|
|
|
await test.step('Go through command bar flow', async () => {
|
|
await toolbar.extrudeButton.click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'sketches',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Profiles: '',
|
|
Length: '',
|
|
},
|
|
highlightedHeaderArg: 'Profiles',
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'length',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Profiles: '1 profile',
|
|
Length: '',
|
|
},
|
|
highlightedHeaderArg: 'length',
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Profiles: '1 profile',
|
|
Length: '5',
|
|
},
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.clickOptionalArgument('bidirectionalLength')
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'bidirectionalLength',
|
|
currentArgValue: '',
|
|
headerArguments: {
|
|
Profiles: '1 profile',
|
|
Length: '5',
|
|
BidirectionalLength: '',
|
|
},
|
|
highlightedHeaderArg: 'bidirectionalLength',
|
|
commandName: 'Extrude',
|
|
})
|
|
await page.keyboard.insertText('10')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Profiles: '1 profile',
|
|
Length: '5',
|
|
BidirectionalLength: '10',
|
|
},
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.submit()
|
|
})
|
|
|
|
await test.step('Check that the code has changed', async () => {
|
|
await scene.settled(cmdBar)
|
|
await editor.expectEditor.toContain(
|
|
`extrude001 = extrude(profile001, length = 5, bidirectionalLength = 10)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
})
|
|
|
|
await test.step('Go through the edit flow via feature tree', async () => {
|
|
await toolbar.openPane('feature-tree')
|
|
const op = await toolbar.getFeatureTreeOperation('Extrude', 0)
|
|
await op.dblclick()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'length',
|
|
currentArgValue: '5',
|
|
headerArguments: {
|
|
Length: '5',
|
|
BidirectionalLength: '10',
|
|
},
|
|
highlightedHeaderArg: 'length',
|
|
commandName: 'Extrude',
|
|
})
|
|
await page.keyboard.insertText('10')
|
|
await cmdBar.progressCmdBar()
|
|
await page.getByRole('button', { name: 'BidirectionalLength' }).click()
|
|
await cmdBar.expectState({
|
|
stage: 'arguments',
|
|
currentArgKey: 'bidirectionalLength',
|
|
currentArgValue: '10',
|
|
headerArguments: {
|
|
Length: '10',
|
|
BidirectionalLength: '10',
|
|
},
|
|
highlightedHeaderArg: 'bidirectionalLength',
|
|
commandName: 'Extrude',
|
|
})
|
|
await page.keyboard.insertText('20')
|
|
await cmdBar.progressCmdBar()
|
|
await cmdBar.expectState({
|
|
stage: 'review',
|
|
headerArguments: {
|
|
Length: '10',
|
|
BidirectionalLength: '20',
|
|
},
|
|
commandName: 'Extrude',
|
|
})
|
|
await cmdBar.submit()
|
|
})
|
|
|
|
await test.step('Check that the code has changed again', async () => {
|
|
await scene.settled(cmdBar)
|
|
await toolbar.closePane('feature-tree')
|
|
await toolbar.openPane('code')
|
|
await editor.expectEditor.toContain(
|
|
`extrude001 = extrude(profile001, length = 10, bidirectionalLength = 20)`,
|
|
{ shouldNormalise: true }
|
|
)
|
|
})
|
|
})
|
|
})
|