2025-04-07 16:28:11 -04:00
|
|
|
import path from 'path'
|
2025-04-16 00:11:25 +10:00
|
|
|
import * as fsp from 'fs/promises'
|
2025-04-07 16:28:11 -04:00
|
|
|
|
2025-04-09 07:47:57 -04:00
|
|
|
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
|
|
|
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
|
|
|
|
import {
|
|
|
|
executorInputPath,
|
|
|
|
getUtils,
|
2025-04-24 19:02:18 -04:00
|
|
|
kclSamplesPath,
|
2025-04-09 07:47:57 -04:00
|
|
|
testsInputPath,
|
|
|
|
} from '@e2e/playwright/test-utils'
|
|
|
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
|
|
|
import type { Page } from '@playwright/test'
|
|
|
|
|
|
|
|
async function insertPartIntoAssembly(
|
|
|
|
path: string,
|
|
|
|
alias: string,
|
|
|
|
toolbar: ToolbarFixture,
|
|
|
|
cmdBar: CmdBarFixture,
|
|
|
|
page: Page
|
|
|
|
) {
|
|
|
|
await toolbar.insertButton.click()
|
|
|
|
await cmdBar.selectOption({ name: path }).click()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'arguments',
|
|
|
|
currentArgKey: 'localName',
|
|
|
|
currentArgValue: '',
|
|
|
|
headerArguments: { Path: path, LocalName: '' },
|
|
|
|
highlightedHeaderArg: 'localName',
|
|
|
|
commandName: 'Insert',
|
|
|
|
})
|
|
|
|
await page.keyboard.insertText(alias)
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
|
|
|
headerArguments: { Path: path, LocalName: alias },
|
|
|
|
commandName: 'Insert',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
}
|
2025-04-07 16:28:11 -04:00
|
|
|
|
|
|
|
// test file is for testing point an click code gen functionality that's assemblies related
|
|
|
|
test.describe('Point-and-click assemblies tests', () => {
|
|
|
|
test(
|
2025-04-09 07:47:57 -04:00
|
|
|
`Insert kcl parts into assembly as whole module import`,
|
2025-05-29 09:29:03 -04:00
|
|
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
2025-04-07 16:28:11 -04:00
|
|
|
async ({
|
|
|
|
context,
|
|
|
|
page,
|
|
|
|
homePage,
|
|
|
|
scene,
|
|
|
|
editor,
|
|
|
|
toolbar,
|
|
|
|
cmdBar,
|
|
|
|
tronApp,
|
|
|
|
}) => {
|
|
|
|
if (!tronApp) {
|
|
|
|
fail()
|
|
|
|
}
|
|
|
|
|
2025-04-09 07:47:57 -04:00
|
|
|
const midPoint = { x: 500, y: 250 }
|
|
|
|
const partPoint = { x: midPoint.x + 30, y: midPoint.y - 30 } // mid point, just off top right
|
|
|
|
const defaultPlanesColor: [number, number, number] = [180, 220, 180]
|
|
|
|
const partColor: [number, number, number] = [100, 100, 100]
|
2025-04-07 16:28:11 -04:00
|
|
|
const tolerance = 50
|
2025-04-09 07:47:57 -04:00
|
|
|
const u = await getUtils(page)
|
|
|
|
const gizmo = page.locator('[aria-label*=gizmo]')
|
|
|
|
const resetCameraButton = page.getByRole('button', { name: 'Reset view' })
|
2025-04-07 16:28:11 -04:00
|
|
|
|
|
|
|
await test.step('Setup parts and expect empty assembly scene', async () => {
|
|
|
|
const projectName = 'assembly'
|
|
|
|
await context.folderSetupFn(async (dir) => {
|
2025-05-20 20:44:22 -04:00
|
|
|
const projDir = path.join(dir, projectName)
|
|
|
|
const nestedProjDir = path.join(dir, projectName, 'nested', 'twice')
|
|
|
|
await fsp.mkdir(projDir, { recursive: true })
|
|
|
|
await fsp.mkdir(nestedProjDir, { recursive: true })
|
2025-04-07 16:28:11 -04:00
|
|
|
await Promise.all([
|
|
|
|
fsp.copyFile(
|
2025-04-09 07:47:57 -04:00
|
|
|
executorInputPath('cylinder.kcl'),
|
2025-05-20 20:44:22 -04:00
|
|
|
path.join(projDir, 'cylinder.kcl')
|
|
|
|
),
|
|
|
|
fsp.copyFile(
|
|
|
|
executorInputPath('cylinder.kcl'),
|
|
|
|
path.join(nestedProjDir, 'main.kcl')
|
2025-04-07 16:28:11 -04:00
|
|
|
),
|
|
|
|
fsp.copyFile(
|
|
|
|
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
|
2025-05-20 20:44:22 -04:00
|
|
|
path.join(projDir, 'bracket.kcl')
|
2025-04-07 16:28:11 -04:00
|
|
|
),
|
2025-04-09 07:47:57 -04:00
|
|
|
fsp.copyFile(
|
|
|
|
testsInputPath('cube.step'),
|
2025-05-20 20:44:22 -04:00
|
|
|
path.join(projDir, 'cube.step')
|
2025-04-09 07:47:57 -04:00
|
|
|
),
|
2025-05-20 20:44:22 -04:00
|
|
|
fsp.writeFile(path.join(projDir, 'main.kcl'), ''),
|
2025-04-07 16:28:11 -04:00
|
|
|
])
|
|
|
|
})
|
|
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
|
|
await homePage.openProject(projectName)
|
|
|
|
await scene.settled(cmdBar)
|
2025-04-09 07:47:57 -04:00
|
|
|
await toolbar.closePane('code')
|
|
|
|
await scene.expectPixelColor(defaultPlanesColor, midPoint, tolerance)
|
2025-04-07 16:28:11 -04:00
|
|
|
})
|
|
|
|
|
2025-04-09 07:47:57 -04:00
|
|
|
await test.step('Insert kcl as first part as module', async () => {
|
|
|
|
await insertPartIntoAssembly(
|
|
|
|
'cylinder.kcl',
|
|
|
|
'cylinder',
|
|
|
|
toolbar,
|
|
|
|
cmdBar,
|
|
|
|
page
|
|
|
|
)
|
|
|
|
await toolbar.openPane('code')
|
2025-04-07 16:28:11 -04:00
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
2025-04-30 13:07:39 -04:00
|
|
|
import "cylinder.kcl" as cylinder
|
|
|
|
`,
|
2025-04-07 16:28:11 -04:00
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
2025-04-09 07:47:57 -04:00
|
|
|
await scene.settled(cmdBar)
|
|
|
|
|
|
|
|
// Check scene for changes
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
await u.doAndWaitForCmd(async () => {
|
|
|
|
await gizmo.click({ button: 'right' })
|
|
|
|
await resetCameraButton.click()
|
|
|
|
}, 'zoom_to_fit')
|
|
|
|
await toolbar.closePane('debug')
|
|
|
|
await scene.expectPixelColor(partColor, partPoint, tolerance)
|
|
|
|
await toolbar.openPane('code')
|
2025-04-07 16:28:11 -04:00
|
|
|
})
|
|
|
|
|
2025-04-26 18:26:39 -04:00
|
|
|
await test.step('Insert a second part with the same name and expect error', async () => {
|
2025-04-21 06:35:43 -04:00
|
|
|
await toolbar.insertButton.click()
|
|
|
|
await cmdBar.selectOption({ name: 'bracket.kcl' }).click()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'arguments',
|
|
|
|
currentArgKey: 'localName',
|
|
|
|
currentArgValue: '',
|
|
|
|
headerArguments: { Path: 'bracket.kcl', LocalName: '' },
|
|
|
|
highlightedHeaderArg: 'localName',
|
|
|
|
commandName: 'Insert',
|
|
|
|
})
|
2025-04-26 18:26:39 -04:00
|
|
|
await page.keyboard.insertText('cylinder')
|
2025-04-21 06:35:43 -04:00
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await expect(
|
|
|
|
page.getByText('This variable name is already in use')
|
|
|
|
).toBeVisible()
|
|
|
|
})
|
|
|
|
|
2025-04-26 18:26:39 -04:00
|
|
|
await test.step('Fix the name and expect the second part inserted', async () => {
|
|
|
|
await cmdBar.argumentInput.clear()
|
|
|
|
await page.keyboard.insertText('bracket')
|
2025-04-21 06:35:43 -04:00
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
2025-04-26 18:26:39 -04:00
|
|
|
headerArguments: { Path: 'bracket.kcl', LocalName: 'bracket' },
|
2025-04-21 06:35:43 -04:00
|
|
|
commandName: 'Insert',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
2025-04-09 07:47:57 -04:00
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
2025-04-30 13:07:39 -04:00
|
|
|
import "cylinder.kcl" as cylinder
|
|
|
|
import "bracket.kcl" as bracket
|
|
|
|
`,
|
2025-04-09 07:47:57 -04:00
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
2025-04-26 18:26:39 -04:00
|
|
|
await scene.settled(cmdBar)
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Insert a second time and expect error', async () => {
|
|
|
|
await toolbar.insertButton.click()
|
|
|
|
await cmdBar.selectOption({ name: 'bracket.kcl' }).click()
|
|
|
|
await expect(
|
|
|
|
page.getByText('This file is already imported')
|
|
|
|
).toBeVisible()
|
2025-05-20 20:44:22 -04:00
|
|
|
await cmdBar.closeCmdBar()
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Insert a nested kcl part', async () => {
|
|
|
|
await insertPartIntoAssembly(
|
|
|
|
'nested/twice/main.kcl',
|
|
|
|
'main',
|
|
|
|
toolbar,
|
|
|
|
cmdBar,
|
|
|
|
page
|
|
|
|
)
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await page.waitForTimeout(10000)
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
2025-05-29 09:29:03 -04:00
|
|
|
import "nested/twice/main.kcl" as main
|
2025-05-20 20:44:22 -04:00
|
|
|
`,
|
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
2025-04-09 07:47:57 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2025-04-30 13:07:39 -04:00
|
|
|
test(
|
|
|
|
`Can still translate, rotate, and delete inserted parts even with non standard code`,
|
2025-05-29 09:29:03 -04:00
|
|
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
2025-04-30 13:07:39 -04:00
|
|
|
async ({
|
|
|
|
context,
|
|
|
|
page,
|
|
|
|
homePage,
|
|
|
|
scene,
|
|
|
|
editor,
|
|
|
|
toolbar,
|
|
|
|
cmdBar,
|
|
|
|
tronApp,
|
|
|
|
}) => {
|
|
|
|
if (!tronApp) {
|
|
|
|
fail()
|
|
|
|
}
|
|
|
|
|
|
|
|
page.on('console', console.log)
|
|
|
|
|
|
|
|
await test.step('Setup parts and expect empty assembly scene', async () => {
|
|
|
|
const projectName = 'assembly'
|
|
|
|
await context.folderSetupFn(async (dir) => {
|
|
|
|
const projectDir = path.join(dir, projectName)
|
|
|
|
await fsp.mkdir(projectDir, { recursive: true })
|
|
|
|
await Promise.all([
|
|
|
|
fsp.copyFile(
|
|
|
|
executorInputPath('cylinder.kcl'),
|
|
|
|
path.join(projectDir, 'cylinder.kcl')
|
|
|
|
),
|
|
|
|
fsp.copyFile(
|
|
|
|
testsInputPath('cube.step'),
|
|
|
|
path.join(projectDir, 'cube.step')
|
|
|
|
),
|
|
|
|
fsp.writeFile(
|
|
|
|
path.join(projectDir, 'main.kcl'),
|
|
|
|
`
|
|
|
|
import "cube.step" as cube
|
|
|
|
import "cylinder.kcl" as cylinder
|
|
|
|
cylinder
|
|
|
|
|> translate(x = 1)
|
|
|
|
cube
|
|
|
|
|> rotate(pitch = 2)
|
|
|
|
|> translate(y = 2)
|
|
|
|
cylinder
|
|
|
|
|> rotate(roll = 1)
|
|
|
|
cylinder
|
|
|
|
|> translate(x = 0.1)
|
|
|
|
`
|
|
|
|
),
|
|
|
|
])
|
|
|
|
})
|
|
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
|
|
await homePage.openProject(projectName)
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
await page.waitForTimeout(1000)
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Set translate on cylinder', async () => {
|
|
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
const op = await toolbar.getFeatureTreeOperation('cylinder', 0)
|
|
|
|
await op.click({ button: 'right' })
|
|
|
|
await page.getByTestId('context-menu-set-translate').click()
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await page.keyboard.insertText('10')
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
|
|
|
headerArguments: {
|
|
|
|
X: '0.1',
|
|
|
|
Y: '0',
|
|
|
|
Z: '10',
|
|
|
|
},
|
|
|
|
commandName: 'Translate',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
|
|
|
import "cube.step" as cube
|
|
|
|
import "cylinder.kcl" as cylinder
|
|
|
|
cylinder
|
|
|
|
|> translate(x = 1)
|
|
|
|
cube
|
|
|
|
|> rotate(pitch = 2)
|
|
|
|
|> translate(y = 2)
|
|
|
|
cylinder
|
|
|
|
|> rotate(roll = 1)
|
|
|
|
cylinder
|
|
|
|
|> translate(x = 0.1, y = 0, z = 10)
|
|
|
|
`,
|
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Set rotate on cylinder', async () => {
|
|
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
const op = await toolbar.getFeatureTreeOperation('cylinder', 0)
|
|
|
|
await op.click({ button: 'right' })
|
|
|
|
await page.getByTestId('context-menu-set-rotate').click()
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await page.keyboard.insertText('100')
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
|
|
|
headerArguments: {
|
|
|
|
Roll: '1',
|
|
|
|
Pitch: '0',
|
|
|
|
Yaw: '100',
|
|
|
|
},
|
|
|
|
commandName: 'Rotate',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
|
|
|
import "cube.step" as cube
|
|
|
|
import "cylinder.kcl" as cylinder
|
|
|
|
cylinder
|
|
|
|
|> translate(x = 1)
|
|
|
|
cube
|
|
|
|
|> rotate(pitch = 2)
|
|
|
|
|> translate(y = 2)
|
|
|
|
cylinder
|
|
|
|
|> rotate(roll = 1, pitch = 0, yaw = 100)
|
|
|
|
cylinder
|
|
|
|
|> translate(x = 0.1, y = 0, z = 10)
|
|
|
|
`,
|
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Set rotate on cube', async () => {
|
|
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
const op = await toolbar.getFeatureTreeOperation('cube', 0)
|
|
|
|
await op.click({ button: 'right' })
|
|
|
|
await page.getByTestId('context-menu-set-rotate').click()
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await page.keyboard.insertText('200')
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
|
|
|
headerArguments: {
|
|
|
|
Roll: '0',
|
|
|
|
Pitch: '2',
|
|
|
|
Yaw: '200',
|
|
|
|
},
|
|
|
|
commandName: 'Rotate',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
|
|
|
import "cube.step" as cube
|
|
|
|
import "cylinder.kcl" as cylinder
|
|
|
|
cylinder
|
|
|
|
|> translate(x = 1)
|
|
|
|
cube
|
|
|
|
|> rotate(roll = 0, pitch = 2, yaw = 200)
|
|
|
|
|> translate(y = 2)
|
|
|
|
cylinder
|
|
|
|
|> rotate(roll = 1, pitch = 0, yaw = 100)
|
|
|
|
cylinder
|
|
|
|
|> translate(x = 0.1, y = 0, z = 10)
|
|
|
|
`,
|
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Delete cylinder using the feature tree', async () => {
|
|
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
const op = await toolbar.getFeatureTreeOperation('cylinder', 0)
|
|
|
|
await op.click({ button: 'right' })
|
|
|
|
await page.getByTestId('context-menu-delete').click()
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
|
|
|
import "cube.step" as cube
|
|
|
|
cube
|
|
|
|
|> rotate(roll = 0, pitch = 2, yaw = 200)
|
|
|
|
|> translate(y = 2)
|
|
|
|
`,
|
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
test(
|
2025-04-17 11:44:31 -04:00
|
|
|
`Insert the bracket part into an assembly and transform it`,
|
2025-05-29 09:29:03 -04:00
|
|
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
2025-04-17 11:44:31 -04:00
|
|
|
async ({
|
|
|
|
context,
|
|
|
|
page,
|
|
|
|
homePage,
|
|
|
|
scene,
|
|
|
|
editor,
|
|
|
|
toolbar,
|
|
|
|
cmdBar,
|
|
|
|
tronApp,
|
|
|
|
}) => {
|
|
|
|
if (!tronApp) {
|
|
|
|
fail()
|
|
|
|
}
|
|
|
|
|
|
|
|
const midPoint = { x: 500, y: 250 }
|
|
|
|
const moreToTheRightPoint = { x: 900, y: 250 }
|
|
|
|
const bgColor: [number, number, number] = [30, 30, 30]
|
|
|
|
const partColor: [number, number, number] = [100, 100, 100]
|
|
|
|
const tolerance = 30
|
|
|
|
const u = await getUtils(page)
|
|
|
|
const gizmo = page.locator('[aria-label*=gizmo]')
|
|
|
|
const resetCameraButton = page.getByRole('button', { name: 'Reset view' })
|
|
|
|
|
|
|
|
await test.step('Setup parts and expect empty assembly scene', async () => {
|
|
|
|
const projectName = 'assembly'
|
|
|
|
await context.folderSetupFn(async (dir) => {
|
|
|
|
const bracketDir = path.join(dir, projectName)
|
|
|
|
await fsp.mkdir(bracketDir, { recursive: true })
|
|
|
|
await Promise.all([
|
|
|
|
fsp.copyFile(
|
|
|
|
path.join('public', 'kcl-samples', 'bracket', 'main.kcl'),
|
|
|
|
path.join(bracketDir, 'bracket.kcl')
|
|
|
|
),
|
|
|
|
fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''),
|
|
|
|
])
|
|
|
|
})
|
|
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
|
|
await homePage.openProject(projectName)
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Insert kcl as module', async () => {
|
|
|
|
await insertPartIntoAssembly(
|
|
|
|
'bracket.kcl',
|
|
|
|
'bracket',
|
|
|
|
toolbar,
|
|
|
|
cmdBar,
|
|
|
|
page
|
|
|
|
)
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
2025-04-30 13:07:39 -04:00
|
|
|
import "bracket.kcl" as bracket
|
|
|
|
`,
|
2025-04-17 11:44:31 -04:00
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
|
|
|
|
// Check scene for changes
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
await u.doAndWaitForCmd(async () => {
|
|
|
|
await gizmo.click({ button: 'right' })
|
|
|
|
await resetCameraButton.click()
|
|
|
|
}, 'zoom_to_fit')
|
|
|
|
await toolbar.closePane('debug')
|
|
|
|
await scene.expectPixelColor(partColor, midPoint, tolerance)
|
|
|
|
await scene.expectPixelColor(bgColor, moreToTheRightPoint, tolerance)
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Set translate on module', async () => {
|
|
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
|
|
|
|
const op = await toolbar.getFeatureTreeOperation('bracket', 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',
|
|
|
|
})
|
2025-04-23 10:58:35 +12:00
|
|
|
await page.keyboard.insertText('100')
|
2025-04-17 11:44:31 -04:00
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await page.keyboard.insertText('0.1')
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await page.keyboard.insertText('0.2')
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
|
|
|
headerArguments: {
|
2025-04-23 10:58:35 +12:00
|
|
|
X: '100',
|
2025-04-17 11:44:31 -04:00
|
|
|
Y: '0.1',
|
|
|
|
Z: '0.2',
|
|
|
|
},
|
|
|
|
commandName: 'Translate',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
2025-04-30 13:07:39 -04:00
|
|
|
bracket
|
|
|
|
|> translate(x = 100, y = 0.1, z = 0.2)
|
|
|
|
`,
|
2025-04-17 11:44:31 -04:00
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
// Expect translated part in the scene
|
|
|
|
await scene.expectPixelColor(bgColor, midPoint, tolerance)
|
|
|
|
await scene.expectPixelColor(partColor, moreToTheRightPoint, tolerance)
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Set rotate on module', async () => {
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
|
|
|
|
const op = await toolbar.getFeatureTreeOperation('bracket', 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('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: {
|
|
|
|
Roll: '0.1',
|
|
|
|
Pitch: '0.2',
|
|
|
|
Yaw: '0.3',
|
|
|
|
},
|
|
|
|
commandName: 'Rotate',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
2025-04-30 13:07:39 -04:00
|
|
|
bracket
|
|
|
|
|> translate(x = 100, y = 0.1, z = 0.2)
|
|
|
|
|> rotate(roll = 0.1, pitch = 0.2, yaw = 0.3)
|
|
|
|
`,
|
2025-04-17 11:44:31 -04:00
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
// Expect no change in the scene as the rotations are tiny
|
|
|
|
await scene.expectPixelColor(bgColor, midPoint, tolerance)
|
|
|
|
await scene.expectPixelColor(partColor, moreToTheRightPoint, tolerance)
|
|
|
|
})
|
2025-04-25 10:45:51 -04:00
|
|
|
|
|
|
|
await test.step('Delete the part using the feature tree', async () => {
|
|
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
const op = await toolbar.getFeatureTreeOperation('bracket', 0)
|
|
|
|
await op.click({ button: 'right' })
|
|
|
|
await page.getByTestId('context-menu-delete').click()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
|
|
|
|
// Expect empty editor and scene
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.not.toContain('import')
|
|
|
|
await editor.expectEditor.not.toContain('bracket')
|
|
|
|
await editor.expectEditor.not.toContain('|> translate')
|
|
|
|
await editor.expectEditor.not.toContain('|> rotate')
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
await scene.expectPixelColorNotToBe(partColor, midPoint, tolerance)
|
|
|
|
})
|
2025-04-17 11:44:31 -04:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2025-05-07 09:56:03 -04:00
|
|
|
test(
|
|
|
|
`Insert foreign parts into assembly and delete them`,
|
2025-05-29 09:29:03 -04:00
|
|
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
2025-04-09 07:47:57 -04:00
|
|
|
async ({
|
|
|
|
context,
|
|
|
|
page,
|
|
|
|
homePage,
|
|
|
|
scene,
|
|
|
|
editor,
|
|
|
|
toolbar,
|
|
|
|
cmdBar,
|
|
|
|
tronApp,
|
|
|
|
}) => {
|
|
|
|
if (!tronApp) {
|
|
|
|
fail()
|
|
|
|
}
|
|
|
|
|
|
|
|
const midPoint = { x: 500, y: 250 }
|
|
|
|
const partPoint = { x: midPoint.x + 30, y: midPoint.y - 30 } // mid point, just off top right
|
|
|
|
const defaultPlanesColor: [number, number, number] = [180, 220, 180]
|
|
|
|
const partColor: [number, number, number] = [150, 150, 150]
|
|
|
|
const tolerance = 50
|
|
|
|
|
|
|
|
const complexPlmFileName = 'cube_Complex-PLM_Name_-001.sldprt'
|
|
|
|
const camelCasedSolidworksFileName = 'cubeComplexPLMName001'
|
|
|
|
|
|
|
|
await test.step('Setup parts and expect empty assembly scene', async () => {
|
|
|
|
const projectName = 'assembly'
|
|
|
|
await context.folderSetupFn(async (dir) => {
|
|
|
|
const bracketDir = path.join(dir, projectName)
|
|
|
|
await fsp.mkdir(bracketDir, { recursive: true })
|
|
|
|
await Promise.all([
|
|
|
|
fsp.copyFile(
|
|
|
|
testsInputPath('cube.step'),
|
|
|
|
path.join(bracketDir, 'cube.step')
|
|
|
|
),
|
|
|
|
fsp.copyFile(
|
|
|
|
testsInputPath('cube.sldprt'),
|
|
|
|
path.join(bracketDir, complexPlmFileName)
|
|
|
|
),
|
|
|
|
fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''),
|
|
|
|
])
|
2025-04-07 16:28:11 -04:00
|
|
|
})
|
2025-04-09 07:47:57 -04:00
|
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
|
|
await homePage.openProject(projectName)
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
await scene.expectPixelColor(defaultPlanesColor, midPoint, tolerance)
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Insert step part as module', async () => {
|
|
|
|
await insertPartIntoAssembly('cube.step', 'cube', toolbar, cmdBar, page)
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
2025-04-30 13:07:39 -04:00
|
|
|
import "cube.step" as cube
|
|
|
|
`,
|
2025-04-09 07:47:57 -04:00
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
|
|
|
|
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
await scene.expectPixelColor(partColor, partPoint, tolerance)
|
|
|
|
})
|
|
|
|
|
2025-04-30 13:07:39 -04:00
|
|
|
await test.step('Insert second foreign part by clicking', async () => {
|
2025-04-09 07:47:57 -04:00
|
|
|
await toolbar.openPane('files')
|
|
|
|
await toolbar.expectFileTreeState([
|
|
|
|
complexPlmFileName,
|
|
|
|
'cube.step',
|
|
|
|
'main.kcl',
|
|
|
|
])
|
|
|
|
await toolbar.openFile(complexPlmFileName)
|
|
|
|
|
|
|
|
// Go through the ToastInsert prompt
|
|
|
|
await page.getByText('Insert into my current file').click()
|
|
|
|
|
|
|
|
// Check getPathFilenameInVariableCase output
|
|
|
|
const parsedValueFromFile =
|
|
|
|
await cmdBar.currentArgumentInput.inputValue()
|
|
|
|
expect(parsedValueFromFile).toEqual(camelCasedSolidworksFileName)
|
|
|
|
|
|
|
|
// Continue on with the flow
|
|
|
|
await page.keyboard.insertText('cubeSw')
|
2025-04-07 16:28:11 -04:00
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
2025-04-09 07:47:57 -04:00
|
|
|
headerArguments: { Path: complexPlmFileName, LocalName: 'cubeSw' },
|
2025-04-07 16:28:11 -04:00
|
|
|
commandName: 'Insert',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
2025-04-09 07:47:57 -04:00
|
|
|
await toolbar.closePane('files')
|
|
|
|
await toolbar.openPane('code')
|
2025-04-07 16:28:11 -04:00
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
2025-04-30 13:07:39 -04:00
|
|
|
import "cube.step" as cube
|
|
|
|
import "${complexPlmFileName}" as cubeSw
|
|
|
|
`,
|
2025-04-07 16:28:11 -04:00
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
2025-04-09 07:47:57 -04:00
|
|
|
await scene.settled(cmdBar)
|
|
|
|
|
|
|
|
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
await scene.expectPixelColor(partColor, partPoint, tolerance)
|
2025-04-07 16:28:11 -04:00
|
|
|
})
|
2025-04-25 10:45:51 -04:00
|
|
|
|
2025-04-30 13:07:39 -04:00
|
|
|
// TODO: enable once deleting the first import is fixed
|
|
|
|
// await test.step('Delete first part using the feature tree', async () => {
|
|
|
|
// page.on('console', console.log)
|
|
|
|
// await toolbar.openPane('feature-tree')
|
|
|
|
// const op = await toolbar.getFeatureTreeOperation('cube', 0)
|
|
|
|
// await op.click({ button: 'right' })
|
|
|
|
// await page.getByTestId('context-menu-delete').click()
|
|
|
|
// await scene.settled(cmdBar)
|
|
|
|
// await toolbar.closePane('feature-tree')
|
|
|
|
|
|
|
|
// // Expect only the import statement to be there
|
|
|
|
// await toolbar.openPane('code')
|
|
|
|
// await editor.expectEditor.not.toContain(`import "cube.step" as cube`)
|
|
|
|
// await toolbar.closePane('code')
|
|
|
|
// await editor.expectEditor.toContain(
|
|
|
|
// `
|
|
|
|
// import "${complexPlmFileName}" as cubeSw
|
|
|
|
// `,
|
|
|
|
// { shouldNormalise: true }
|
|
|
|
// )
|
|
|
|
// await toolbar.closePane('code')
|
|
|
|
// })
|
2025-04-25 10:45:51 -04:00
|
|
|
|
|
|
|
await test.step('Delete second part using the feature tree', async () => {
|
|
|
|
await toolbar.openPane('feature-tree')
|
2025-04-30 13:07:39 -04:00
|
|
|
const op = await toolbar.getFeatureTreeOperation('cube_Complex', 0)
|
2025-04-25 10:45:51 -04:00
|
|
|
await op.click({ button: 'right' })
|
|
|
|
await page.getByTestId('context-menu-delete').click()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
|
|
|
|
// Expect empty editor and scene
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.not.toContain(
|
|
|
|
`import "${complexPlmFileName}" as cubeSw`
|
|
|
|
)
|
|
|
|
await toolbar.closePane('code')
|
2025-04-30 13:07:39 -04:00
|
|
|
// TODO: enable once deleting the first import is fixed
|
|
|
|
// await scene.expectPixelColorNotToBe(partColor, midPoint, tolerance)
|
2025-04-25 10:45:51 -04:00
|
|
|
})
|
2025-04-07 16:28:11 -04:00
|
|
|
}
|
|
|
|
)
|
2025-04-24 19:02:18 -04:00
|
|
|
|
|
|
|
test(
|
|
|
|
'Assembly gets reexecuted when imported models are updated externally',
|
2025-05-29 09:29:03 -04:00
|
|
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
2025-04-24 19:02:18 -04:00
|
|
|
async ({ context, page, homePage, scene, toolbar, cmdBar, tronApp }) => {
|
|
|
|
if (!tronApp) {
|
|
|
|
fail()
|
|
|
|
}
|
|
|
|
|
|
|
|
const midPoint = { x: 500, y: 250 }
|
|
|
|
const washerPoint = { x: 645, y: 250 }
|
|
|
|
const partColor: [number, number, number] = [120, 120, 120]
|
|
|
|
const redPartColor: [number, number, number] = [200, 0, 0]
|
|
|
|
const bgColor: [number, number, number] = [30, 30, 30]
|
|
|
|
const tolerance = 50
|
|
|
|
const projectName = 'assembly'
|
|
|
|
|
|
|
|
await test.step('Setup parts and expect imported model', async () => {
|
|
|
|
await context.folderSetupFn(async (dir) => {
|
|
|
|
const projectDir = path.join(dir, projectName)
|
|
|
|
await fsp.mkdir(projectDir, { recursive: true })
|
|
|
|
await Promise.all([
|
|
|
|
fsp.copyFile(
|
|
|
|
executorInputPath('cube.kcl'),
|
|
|
|
path.join(projectDir, 'cube.kcl')
|
|
|
|
),
|
|
|
|
fsp.copyFile(
|
|
|
|
kclSamplesPath(
|
|
|
|
path.join(
|
|
|
|
'pipe-flange-assembly',
|
|
|
|
'mcmaster-parts',
|
|
|
|
'98017a257-washer.step'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
path.join(projectDir, 'foreign.step')
|
|
|
|
),
|
|
|
|
fsp.writeFile(
|
|
|
|
path.join(projectDir, 'main.kcl'),
|
|
|
|
`
|
|
|
|
import "cube.kcl" as cube
|
|
|
|
import "foreign.step" as foreign
|
|
|
|
cube
|
|
|
|
foreign
|
|
|
|
|> translate(x = 40, z = 10)`
|
|
|
|
),
|
|
|
|
])
|
|
|
|
})
|
|
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
|
|
await homePage.openProject(projectName)
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
await scene.expectPixelColor(partColor, midPoint, tolerance)
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Change imported kcl file and expect change', async () => {
|
|
|
|
await context.folderSetupFn(async (dir) => {
|
|
|
|
// Append appearance to the cube.kcl file
|
|
|
|
await fsp.appendFile(
|
|
|
|
path.join(dir, projectName, 'cube.kcl'),
|
|
|
|
`\n |> appearance(color = "#ff0000")`
|
|
|
|
)
|
|
|
|
})
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
await scene.expectPixelColor(redPartColor, midPoint, tolerance)
|
|
|
|
await scene.expectPixelColor(partColor, washerPoint, tolerance)
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Change imported step file and expect change', async () => {
|
|
|
|
await context.folderSetupFn(async (dir) => {
|
|
|
|
// Replace the washer with a pipe
|
|
|
|
await fsp.copyFile(
|
|
|
|
kclSamplesPath(
|
|
|
|
path.join(
|
|
|
|
'pipe-flange-assembly',
|
|
|
|
'mcmaster-parts',
|
|
|
|
'1120t74-pipe.step'
|
|
|
|
)
|
|
|
|
),
|
|
|
|
path.join(dir, projectName, 'foreign.step')
|
|
|
|
)
|
|
|
|
})
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
// Expect pipe to take over the red cube but leave some space where the washer was
|
|
|
|
await scene.expectPixelColor(partColor, midPoint, tolerance)
|
|
|
|
await scene.expectPixelColor(bgColor, washerPoint, tolerance)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
2025-04-26 18:26:39 -04:00
|
|
|
|
2025-05-02 17:25:33 -04:00
|
|
|
test(
|
|
|
|
`Point-and-click clone`,
|
2025-05-29 09:29:03 -04:00
|
|
|
{ tag: ['@desktop', '@macos', '@windows'] },
|
2025-04-26 18:26:39 -04:00
|
|
|
async ({
|
|
|
|
context,
|
|
|
|
page,
|
|
|
|
homePage,
|
|
|
|
scene,
|
2025-05-02 17:25:33 -04:00
|
|
|
editor,
|
2025-04-26 18:26:39 -04:00
|
|
|
toolbar,
|
|
|
|
cmdBar,
|
|
|
|
tronApp,
|
|
|
|
}) => {
|
|
|
|
if (!tronApp) {
|
|
|
|
fail()
|
|
|
|
}
|
|
|
|
|
|
|
|
const projectName = 'assembly'
|
2025-05-02 17:25:33 -04:00
|
|
|
const midPoint = { x: 500, y: 250 }
|
|
|
|
const [clickMidPoint] = scene.makeMouseHelpers(midPoint.x, midPoint.y)
|
2025-04-26 18:26:39 -04:00
|
|
|
|
|
|
|
await test.step('Setup parts and expect imported model', async () => {
|
|
|
|
await context.folderSetupFn(async (dir) => {
|
|
|
|
const projectDir = path.join(dir, projectName)
|
|
|
|
await fsp.mkdir(projectDir, { recursive: true })
|
|
|
|
await Promise.all([
|
|
|
|
fsp.copyFile(
|
|
|
|
path.join('public', 'kcl-samples', 'washer', 'main.kcl'),
|
|
|
|
path.join(projectDir, 'washer.kcl')
|
|
|
|
),
|
|
|
|
fsp.copyFile(
|
|
|
|
path.join(
|
|
|
|
'public',
|
|
|
|
'kcl-samples',
|
|
|
|
'socket-head-cap-screw',
|
|
|
|
'main.kcl'
|
|
|
|
),
|
|
|
|
path.join(projectDir, 'screw.kcl')
|
|
|
|
),
|
|
|
|
fsp.writeFile(
|
|
|
|
path.join(projectDir, 'main.kcl'),
|
|
|
|
`
|
|
|
|
import "washer.kcl" as washer
|
|
|
|
import "screw.kcl" as screw
|
|
|
|
screw
|
|
|
|
washer
|
|
|
|
|> rotate(roll = 90, pitch = 0, yaw = 0)`
|
|
|
|
),
|
|
|
|
])
|
|
|
|
})
|
|
|
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
|
|
await homePage.openProject(projectName)
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
})
|
|
|
|
|
2025-05-02 17:25:33 -04:00
|
|
|
await test.step('Try to clone from scene selection and expect error', async () => {
|
|
|
|
await cmdBar.openCmdBar()
|
|
|
|
await cmdBar.chooseCommand('Clone a solid')
|
|
|
|
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 cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
|
|
|
headerArguments: {
|
|
|
|
Selection: '1 path',
|
|
|
|
VariableName: 'clone001',
|
|
|
|
},
|
|
|
|
commandName: 'Clone',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await expect(
|
|
|
|
page.getByText(
|
|
|
|
"Couldn't retrieve selection. If you're trying to transform an import, use the feature tree."
|
|
|
|
)
|
|
|
|
).toBeVisible()
|
|
|
|
})
|
|
|
|
|
2025-04-26 18:26:39 -04:00
|
|
|
await test.step('Clone the part using the feature tree', async () => {
|
|
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
const op = await toolbar.getFeatureTreeOperation('washer', 0)
|
|
|
|
await op.click({ button: 'right' })
|
|
|
|
await page.getByTestId('context-menu-clone').click()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'arguments',
|
|
|
|
currentArgKey: 'variableName',
|
|
|
|
currentArgValue: '',
|
|
|
|
headerArguments: {
|
|
|
|
VariableName: '',
|
|
|
|
},
|
|
|
|
highlightedHeaderArg: 'variableName',
|
|
|
|
commandName: 'Clone',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
|
|
|
headerArguments: {
|
|
|
|
VariableName: 'clone001',
|
|
|
|
},
|
|
|
|
commandName: 'Clone',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
|
|
|
|
// Expect changes
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
2025-04-27 16:54:32 -07:00
|
|
|
washer
|
2025-04-26 18:26:39 -04:00
|
|
|
|> rotate(roll = 90, pitch = 0, yaw = 0)
|
|
|
|
clone001 = clone(washer)
|
|
|
|
`,
|
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
await toolbar.closePane('code')
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Set translate on clone', async () => {
|
|
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
const op = await toolbar.getFeatureTreeOperation('Clone', 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 cmdBar.progressCmdBar()
|
|
|
|
await page.keyboard.insertText('-3')
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
|
|
|
headerArguments: {
|
|
|
|
X: '0',
|
|
|
|
Y: '-3',
|
|
|
|
Z: '0',
|
|
|
|
},
|
|
|
|
commandName: 'Translate',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
|
|
|
|
// Expect changes
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
|
|
|
screw
|
|
|
|
washer
|
|
|
|
|> rotate(roll = 90, pitch = 0, yaw = 0)
|
|
|
|
clone001 = clone(washer)
|
|
|
|
|> translate(x = 0, y = -3, z = 0)
|
|
|
|
`,
|
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
await test.step('Clone the translated clone', async () => {
|
|
|
|
await toolbar.openPane('feature-tree')
|
|
|
|
const op = await toolbar.getFeatureTreeOperation('Clone', 0)
|
|
|
|
await op.click({ button: 'right' })
|
|
|
|
await page.getByTestId('context-menu-clone').click()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'arguments',
|
|
|
|
currentArgKey: 'variableName',
|
|
|
|
currentArgValue: '',
|
|
|
|
headerArguments: {
|
|
|
|
VariableName: '',
|
|
|
|
},
|
|
|
|
highlightedHeaderArg: 'variableName',
|
|
|
|
commandName: 'Clone',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await cmdBar.expectState({
|
|
|
|
stage: 'review',
|
|
|
|
headerArguments: {
|
|
|
|
VariableName: 'clone002',
|
|
|
|
},
|
|
|
|
commandName: 'Clone',
|
|
|
|
})
|
|
|
|
await cmdBar.progressCmdBar()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await toolbar.closePane('feature-tree')
|
|
|
|
|
|
|
|
// Expect changes
|
|
|
|
await toolbar.openPane('code')
|
|
|
|
await editor.expectEditor.toContain(
|
|
|
|
`
|
|
|
|
screw
|
|
|
|
washer
|
|
|
|
|> rotate(roll = 90, pitch = 0, yaw = 0)
|
|
|
|
clone001 = clone(washer)
|
|
|
|
|> translate(x = 0, y = -3, z = 0)
|
|
|
|
clone002 = clone(clone001)
|
|
|
|
`,
|
|
|
|
{ shouldNormalise: true }
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
)
|
2025-04-07 16:28:11 -04:00
|
|
|
})
|