Merge main (tests changed x_x) and pass all constraints.spec tests (pain)

This commit is contained in:
49lf
2024-11-29 14:12:19 -05:00
parent 60e62d435e
commit 3c1c1303e1
12 changed files with 2113 additions and 1962 deletions

View File

@ -52,10 +52,12 @@ export class SceneFixture {
} }
expectState = async (expected: SceneSerialised) => { expectState = async (expected: SceneSerialised) => {
return expect.poll(async () => await this._serialiseScene(), { return expect
intervals: [1_000, 2_000, 10_000], .poll(async () => await this._serialiseScene(), {
timeout: 60000, intervals: [1_000, 2_000, 10_000],
}).toEqual(expected) timeout: 60000,
})
.toEqual(expected)
} }
reConstruct = (page: Page) => { reConstruct = (page: Page) => {

View File

@ -115,9 +115,7 @@ test.describe('Onboarding tests', () => {
await replayButton.click() await replayButton.click()
// Ensure we see the warning, and that the code has not yet updated // Ensure we see the warning, and that the code has not yet updated
await expect( await expect(page.getByText('Would you like to create')).toBeVisible()
page.getByText('Would you like to create')
).toBeVisible()
await expect(page.locator('.cm-content')).toHaveText(initialCode) await expect(page.locator('.cm-content')).toHaveText(initialCode)
const nextButton = page.getByTestId('onboarding-next') const nextButton = page.getByTestId('onboarding-next')
@ -263,7 +261,9 @@ test.describe('Onboarding tests', () => {
await page.setBodyDimensions({ width: 1200, height: 1080 }) await page.setBodyDimensions({ width: 1200, height: 1080 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await expect.poll(() => page.url()).toContain(onboardingPaths.PARAMETRIC_MODELING) await expect
.poll(() => page.url())
.toContain(onboardingPaths.PARAMETRIC_MODELING)
const bracketNoNewLines = bracket.replace(/\n/g, '') const bracketNoNewLines = bracket.replace(/\n/g, '')

View File

@ -7,27 +7,42 @@ import path from 'node:path'
// test file is for testing point an click code gen functionality that's not sketch mode related // test file is for testing point an click code gen functionality that's not sketch mode related
test( test('verify extruding circle works', async ({
'verify extruding circle works', context,
async ({ context, homePage, cmdBar, editor, toolbar, scene }) => { homePage,
const file = await fs.readFile( cmdBar,
path.resolve( editor,
__dirname, toolbar,
'../../', scene,
'./src/wasm-lib/tests/executor/inputs/test-circle-extrude.kcl' }) => {
), const file = await fs.readFile(
'utf-8' path.resolve(
) __dirname,
await context.addInitScript((file) => { '../../',
localStorage.setItem('persistCode', file) './src/wasm-lib/tests/executor/inputs/test-circle-extrude.kcl'
}, file) ),
await homePage.goToModelingScene() 'utf-8'
)
await context.addInitScript((file) => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217) const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217)
await test.step('because there is sweepable geometry, verify extrude is enable when nothing is selected', async () => { await test.step('because there is sweepable geometry, verify extrude is enable when nothing is selected', async () => {
await scene.clickNoWhere() await scene.clickNoWhere()
await expect(toolbar.extrudeButton).toBeEnabled() 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: ["constsketch002=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 test.step('check code model connection works and that button is still enable once circle is selected ', async () => {
@ -35,9 +50,7 @@ test(
const circleSnippet = const circleSnippet =
'circle({ center = [318.33, 168.1], radius = 182.8 }, %)' 'circle({ center = [318.33, 168.1], radius = 182.8 }, %)'
await editor.expectState({ await editor.expectState({
activeLines: [ activeLines: ["constsketch002=startSketchOn('XZ')"],
"constsketch002=startSketchOn('XZ')"
],
highlightedCode: circleSnippet, highlightedCode: circleSnippet,
diagnostics: [], diagnostics: [],
}) })
@ -50,34 +63,35 @@ test(
}) })
await expect(toolbar.extrudeButton).toBeEnabled() 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 test.step('do extrude flow and check extrude code is added to editor', async () => {
await toolbar.extrudeButton.click() await toolbar.extrudeButton.click()
await cmdBar.expectState({ await cmdBar.expectState({
stage: 'arguments', stage: 'arguments',
currentArgKey: 'distance', currentArgKey: 'distance',
currentArgValue: '5', currentArgValue: '5',
headerArguments: { Selection: '1 face', Distance: '' }, headerArguments: { Selection: '1 face', Distance: '' },
highlightedHeaderArg: 'distance', highlightedHeaderArg: 'distance',
commandName: 'Extrude', commandName: 'Extrude',
})
await cmdBar.progressCmdBar()
const expectString = 'extrude001 = extrude(5, sketch001)'
await editor.expectEditor.not.toContain(expectString)
await cmdBar.expectState({
stage: 'review',
headerArguments: { Selection: '1 face', Distance: '5' },
commandName: 'Extrude',
})
await cmdBar.progressCmdBar()
await editor.expectEditor.toContain(expectString)
}) })
} await cmdBar.progressCmdBar()
)
const expectString = 'extrude001 = extrude(5, sketch001)'
await editor.expectEditor.not.toContain(expectString)
await cmdBar.expectState({
stage: 'review',
headerArguments: { Selection: '1 face', Distance: '5' },
commandName: 'Extrude',
})
await cmdBar.progressCmdBar()
await editor.expectEditor.toContain(expectString)
})
})
test.describe('verify sketch on chamfer works', () => { test.describe('verify sketch on chamfer works', () => {
const _sketchOnAChamfer = const _sketchOnAChamfer =
@ -145,7 +159,9 @@ test.describe('verify sketch on chamfer works', () => {
pixelDiff: 50, pixelDiff: 50,
}) })
await rectangle2ndClick() await rectangle2ndClick()
await editor.expectEditor.toContain(afterRectangle2ndClickSnippet, { shouldNormalise: true }) await editor.expectEditor.toContain(afterRectangle2ndClickSnippet, {
shouldNormalise: true,
})
}) })
await test.step('Clean up so that `_sketchOnAChamfer` util can be called again', async () => { await test.step('Clean up so that `_sketchOnAChamfer` util can be called again', async () => {
@ -160,30 +176,35 @@ test.describe('verify sketch on chamfer works', () => {
}) })
}) })
} }
test( test('works on all edge selections and can break up multi edges in a chamfer array', async ({
'works on all edge selections and can break up multi edges in a chamfer array', context,
async ({ context, page, homePage, editor, toolbar, scene }) => { page,
const file = await fs.readFile( homePage,
path.resolve( editor,
__dirname, toolbar,
'../../', scene,
'./src/wasm-lib/tests/executor/inputs/e2e-can-sketch-on-chamfer.kcl' }) => {
), const file = await fs.readFile(
'utf-8' path.resolve(
) __dirname,
await context.addInitScript((file) => { '../../',
localStorage.setItem('persistCode', file) './src/wasm-lib/tests/executor/inputs/e2e-can-sketch-on-chamfer.kcl'
}, file) ),
await page.setBodyDimensions({ width: 1000, height: 500 }) 'utf-8'
await homePage.goToModelingScene() )
await context.addInitScript((file) => {
localStorage.setItem('persistCode', file)
}, file)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene) const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
await sketchOnAChamfer({ await sketchOnAChamfer({
clickCoords: { x: 570, y: 220 }, clickCoords: { x: 570, y: 220 },
cameraPos: { x: 16020, y: -2000, z: 10500 }, cameraPos: { x: 16020, y: -2000, z: 10500 },
cameraTarget: { x: -150, y: -4500, z: -80 }, cameraTarget: { x: -150, y: -4500, z: -80 },
beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01) beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)
chamfer({length = 30,tags = [ chamfer({length = 30,tags = [
seg01, seg01,
getNextAdjacentEdge(yo), getNextAdjacentEdge(yo),
@ -191,10 +212,9 @@ test.describe('verify sketch on chamfer works', () => {
getOppositeEdge(seg01) getOppositeEdge(seg01)
]}, %)`, ]}, %)`,
afterChamferSelectSnippet: afterChamferSelectSnippet: 'sketch002 = startSketchOn(extrude001, seg03)',
'sketch002 = startSketchOn(extrude001, seg03)', afterRectangle1stClickSnippet: 'startProfileAt([160.39, 254.59], %)',
afterRectangle1stClickSnippet: 'startProfileAt([160.39, 254.59], %)', afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002)
afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002)
|> angledLine([ |> angledLine([
segAng(rectangleSegmentA002) - 90, segAng(rectangleSegmentA002) - 90,
105.26 105.26
@ -205,13 +225,13 @@ test.describe('verify sketch on chamfer works', () => {
], %, $rectangleSegmentC001) ], %, $rectangleSegmentC001)
|> lineTo([profileStartX(%), profileStartY(%)], %) |> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)`, |> close(%)`,
}) })
await sketchOnAChamfer({ await sketchOnAChamfer({
clickCoords: { x: 690, y: 250 }, clickCoords: { x: 690, y: 250 },
cameraPos: { x: 16020, y: -2000, z: 10500 }, cameraPos: { x: 16020, y: -2000, z: 10500 },
cameraTarget: { x: -150, y: -4500, z: -80 }, cameraTarget: { x: -150, y: -4500, z: -80 },
beforeChamferSnippet: `angledLine([ beforeChamferSnippet: `angledLine([
segAng(rectangleSegmentA001) - 90, segAng(rectangleSegmentA001) - 90,
217.26 217.26
], %, $seg01)chamfer({ ], %, $seg01)chamfer({
@ -223,10 +243,9 @@ test.describe('verify sketch on chamfer works', () => {
] ]
}, %)`, }, %)`,
afterChamferSelectSnippet: afterChamferSelectSnippet: 'sketch003 = startSketchOn(extrude001, seg04)',
'sketch003 = startSketchOn(extrude001, seg04)', afterRectangle1stClickSnippet: 'startProfileAt([-255.89, 255.28], %)',
afterRectangle1stClickSnippet: 'startProfileAt([-255.89, 255.28], %)', afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003)
afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003)
|> angledLine([ |> angledLine([
segAng(rectangleSegmentA003) - 90, segAng(rectangleSegmentA003) - 90,
106.84 106.84
@ -237,22 +256,21 @@ test.describe('verify sketch on chamfer works', () => {
], %, $rectangleSegmentC002) ], %, $rectangleSegmentC002)
|> lineTo([profileStartX(%), profileStartY(%)], %) |> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)`, |> close(%)`,
}) })
await sketchOnAChamfer({ await sketchOnAChamfer({
clickCoords: { x: 677, y: 87 }, clickCoords: { x: 677, y: 87 },
cameraPos: { x: -6200, y: 1500, z: 6200 }, cameraPos: { x: -6200, y: 1500, z: 6200 },
cameraTarget: { x: 8300, y: 1100, z: 4800 }, cameraTarget: { x: 8300, y: 1100, z: 4800 },
beforeChamferSnippet: `angledLine([0, 268.43], %, $rectangleSegmentA001)chamfer({ beforeChamferSnippet: `angledLine([0, 268.43], %, $rectangleSegmentA001)chamfer({
length = 30, length = 30,
tags = [ tags = [
getNextAdjacentEdge(yo), getNextAdjacentEdge(yo),
getNextAdjacentEdge(seg02) getNextAdjacentEdge(seg02)
] ]
}, %)`, }, %)`,
afterChamferSelectSnippet: afterChamferSelectSnippet: 'sketch003 = startSketchOn(extrude001, seg04)',
'sketch003 = startSketchOn(extrude001, seg04)', afterRectangle1stClickSnippet: 'startProfileAt([37.95, 322.96], %)',
afterRectangle1stClickSnippet: 'startProfileAt([37.95, 322.96], %)', afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003)
afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003)
|> angledLine([ |> angledLine([
segAng(rectangleSegmentA003) - 90, segAng(rectangleSegmentA003) - 90,
106.84 106.84
@ -263,20 +281,19 @@ test.describe('verify sketch on chamfer works', () => {
], %, $rectangleSegmentC002) ], %, $rectangleSegmentC002)
|> lineTo([profileStartX(%), profileStartY(%)], %) |> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)`, |> close(%)`,
}) })
/// last one /// last one
await sketchOnAChamfer({ await sketchOnAChamfer({
clickCoords: { x: 620, y: 300 }, clickCoords: { x: 620, y: 300 },
cameraPos: { x: -1100, y: -7700, z: 1600 }, cameraPos: { x: -1100, y: -7700, z: 1600 },
cameraTarget: { x: 1450, y: 670, z: 4000 }, cameraTarget: { x: 1450, y: 670, z: 4000 },
beforeChamferSnippet: `chamfer({ beforeChamferSnippet: `chamfer({
length = 30, length = 30,
tags = [getNextAdjacentEdge(yo)] tags = [getNextAdjacentEdge(yo)]
}, %)`, }, %)`,
afterChamferSelectSnippet: afterChamferSelectSnippet: 'sketch005 = startSketchOn(extrude001, seg06)',
'sketch005 = startSketchOn(extrude001, seg06)', afterRectangle1stClickSnippet: 'startProfileAt([-59.83, 19.69], %)',
afterRectangle1stClickSnippet: 'startProfileAt([-59.83, 19.69], %)', afterRectangle2ndClickSnippet: `angledLine([0, 9.1], %, $rectangleSegmentA005)
afterRectangle2ndClickSnippet: `angledLine([0, 9.1], %, $rectangleSegmentA005)
|> angledLine([ |> angledLine([
segAng(rectangleSegmentA005) - 90, segAng(rectangleSegmentA005) - 90,
@ -288,11 +305,11 @@ test.describe('verify sketch on chamfer works', () => {
], %, $rectangleSegmentC004) ], %, $rectangleSegmentC004)
|> lineTo([profileStartX(%), profileStartY(%)], %) |> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)`, |> close(%)`,
}) })
await test.step('verify at the end of the test that final code is what is expected', async () => { await test.step('verify at the end of the test that final code is what is expected', async () => {
await editor.expectEditor.toContain( await editor.expectEditor.toContain(
`sketch001 = startSketchOn('XZ') `sketch001 = startSketchOn('XZ')
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag] |> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([0, 268.43], %, $rectangleSegmentA001)
@ -373,47 +390,48 @@ test.describe('verify sketch on chamfer works', () => {
|> lineTo([profileStartX(%), profileStartY(%)], %) |> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%) |> close(%)
`, `,
{ shouldNormalise: true } { shouldNormalise: true }
)
})
}
)
test(
'Works on chamfers that are non in a pipeExpression can break up multi edges in a chamfer array',
async ({ context, page, homePage, editor, toolbar, scene }) => {
const file = await fs.readFile(
path.resolve(
__dirname,
'../../',
'./src/wasm-lib/tests/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()
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene) test('Works on chamfers that are non in a pipeExpression can break up multi edges in a chamfer array', async ({
context,
page,
homePage,
editor,
toolbar,
scene,
}) => {
const file = await fs.readFile(
path.resolve(
__dirname,
'../../',
'./src/wasm-lib/tests/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 sketchOnAChamfer({ await sketchOnAChamfer({
clickCoords: { x: 570, y: 220 }, clickCoords: { x: 570, y: 220 },
cameraPos: { x: 16020, y: -2000, z: 10500 }, cameraPos: { x: 16020, y: -2000, z: 10500 },
cameraTarget: { x: -150, y: -4500, z: -80 }, cameraTarget: { x: -150, y: -4500, z: -80 },
beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01) beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01)
chamfer({length=30,tags=[ chamfer({length=30,tags=[
seg01, seg01,
getNextAdjacentEdge(yo), getNextAdjacentEdge(yo),
getNextAdjacentEdge(seg02), getNextAdjacentEdge(seg02),
getOppositeEdge(seg01) getOppositeEdge(seg01)
]}, extrude001)`, ]}, extrude001)`,
beforeChamferSnippetEnd: '}, extrude001)', beforeChamferSnippetEnd: '}, extrude001)',
afterChamferSelectSnippet: afterChamferSelectSnippet: 'sketch002 = startSketchOn(extrude001, seg03)',
'sketch002 = startSketchOn(extrude001, seg03)', afterRectangle1stClickSnippet: 'startProfileAt([160.39, 254.59], %)',
afterRectangle1stClickSnippet: 'startProfileAt([160.39, 254.59], %)', afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002)
afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002)
|> angledLine([ |> angledLine([
segAng(rectangleSegmentA002) - 90, segAng(rectangleSegmentA002) - 90,
105.26 105.26
@ -424,9 +442,9 @@ test.describe('verify sketch on chamfer works', () => {
], %, $rectangleSegmentC001) ], %, $rectangleSegmentC001)
|> lineTo([profileStartX(%), profileStartY(%)], %) |> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)`, |> close(%)`,
}) })
await editor.expectEditor.toContain( await editor.expectEditor.toContain(
`sketch001 = startSketchOn('XZ') `sketch001 = startSketchOn('XZ')
|> startProfileAt([75.8, 317.2], %) |> startProfileAt([75.8, 317.2], %)
|> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -466,10 +484,9 @@ sketch002 = startSketchOn(extrude001, seg03)
|> lineTo([profileStartX(%), profileStartY(%)], %) |> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%) |> close(%)
`, `,
{ shouldNormalise: true } { shouldNormalise: true }
) )
} })
)
}) })
test(`Verify axis, origin, and horizontal snapping`, async ({ test(`Verify axis, origin, and horizontal snapping`, async ({

View File

@ -56,7 +56,6 @@ test(
}) })
await expect(projectLinks).toHaveCount(0) await expect(projectLinks).toHaveCount(0)
} }
) )
@ -64,7 +63,6 @@ test(
'click help/keybindings from home page', 'click help/keybindings from home page',
{ tag: '@electron' }, { tag: '@electron' },
async ({ page }, testInfo) => { async ({ page }, testInfo) => {
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log) page.on('console', console.log)
@ -76,7 +74,6 @@ test(
await page.getByTestId('keybindings-button').click() await page.getByTestId('keybindings-button').click()
// Make sure the keyboard shortcuts modal is visible. // Make sure the keyboard shortcuts modal is visible.
await expect(page.getByText('Enter Sketch Mode')).toBeVisible() await expect(page.getByText('Enter Sketch Mode')).toBeVisible()
} }
) )
@ -114,7 +111,6 @@ test(
await page.getByTestId('keybindings-button').click() await page.getByTestId('keybindings-button').click()
// Make sure the keyboard shortcuts modal is visible. // Make sure the keyboard shortcuts modal is visible.
await expect(page.getByText('Enter Sketch Mode')).toBeVisible() await expect(page.getByText('Enter Sketch Mode')).toBeVisible()
} }
) )
@ -148,7 +144,6 @@ test(
await page.hover('.cm-lint-marker-error') await page.hover('.cm-lint-marker-error')
const crypticErrorText = `Expected a tag declarator` const crypticErrorText = `Expected a tag declarator`
await expect(page.getByText(crypticErrorText).first()).toBeVisible() await expect(page.getByText(crypticErrorText).first()).toBeVisible()
} }
) )
@ -240,7 +235,6 @@ test.describe('Can export from electron app', () => {
// clean up exported file // clean up exported file
await fsp.rm(filepath) await fsp.rm(filepath)
}) })
} }
) )
} }
@ -248,7 +242,7 @@ test.describe('Can export from electron app', () => {
test( test(
'Rename and delete projects, also spam arrow keys when renaming', 'Rename and delete projects, also spam arrow keys when renaming',
{ tag: '@electron' }, { tag: '@electron' },
async ({ context, page}, testInfo) => { async ({ context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => { await context.folderSetupFn(async (dir) => {
await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }) await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
@ -441,7 +435,6 @@ test(
// expect the name not to have changed // expect the name not to have changed
await expect(page.getByText('bracket')).toBeVisible() await expect(page.getByText('bracket')).toBeVisible()
}) })
} }
) )
@ -470,7 +463,6 @@ test(
// expect to still be on the home page // expect to still be on the home page
await expect(page.getByText('router-template-slate')).toBeVisible() await expect(page.getByText('router-template-slate')).toBeVisible()
await expect(page.getByText('Your Projects')).toBeVisible() await expect(page.getByText('Your Projects')).toBeVisible()
} }
) )
@ -533,7 +525,6 @@ test.describe(`Project management commands`, () => {
await expect(projectHomeLink.first()).toBeVisible() await expect(projectHomeLink.first()).toBeVisible()
await expect(projectHomeLink.first()).toContainText(projectRenamedName) await expect(projectHomeLink.first()).toContainText(projectRenamedName)
}) })
} }
) )
@ -586,7 +577,6 @@ test.describe(`Project management commands`, () => {
await test.step(`Check the project was deleted and we navigated home`, async () => { await test.step(`Check the project was deleted and we navigated home`, async () => {
await expect(noProjectsMessage).toBeVisible() await expect(noProjectsMessage).toBeVisible()
}) })
} }
) )
test( test(
@ -642,7 +632,6 @@ test.describe(`Project management commands`, () => {
).toBeVisible() ).toBeVisible()
await expect(projectHomeLink).not.toHaveText(projectName) await expect(projectHomeLink).not.toHaveText(projectName)
}) })
} }
) )
test( test(
@ -692,7 +681,6 @@ test.describe(`Project management commands`, () => {
await expect(projectHomeLink).not.toBeVisible() await expect(projectHomeLink).not.toBeVisible()
await expect(noProjectsMessage).toBeVisible() await expect(noProjectsMessage).toBeVisible()
}) })
} }
) )
}) })
@ -738,7 +726,6 @@ test(
await expect(u.codeLocator).toContainText( await expect(u.codeLocator).toContainText(
'A mounting bracket for the Focusrite Scarlett Solo audio interface' 'A mounting bracket for the Focusrite Scarlett Solo audio interface'
) )
} }
) )
@ -794,10 +781,11 @@ test(
).rejects.toThrow() ).rejects.toThrow()
// eslint-disable-next-line jest/no-conditional-expect // eslint-disable-next-line jest/no-conditional-expect
await expect( await expect(
fsp.access(path.join(testDir, 'router-template-slate', 'nested', 'main.kcl')) fsp.access(
path.join(testDir, 'router-template-slate', 'nested', 'main.kcl')
)
).rejects.toThrow() ).rejects.toThrow()
} }
} }
) )
@ -876,7 +864,6 @@ test.fixme(
page.getByTestId('project-link').filter({ hasText: 'project-000' }) page.getByTestId('project-link').filter({ hasText: 'project-000' })
).toBeVisible() ).toBeVisible()
}) })
} }
) )
@ -914,7 +901,6 @@ test(
await expect(u.codeLocator).toContainText('routerDiameter') await expect(u.codeLocator).toContainText('routerDiameter')
await expect(u.codeLocator).toContainText('templateGap') await expect(u.codeLocator).toContainText('templateGap')
await expect(u.codeLocator).toContainText('minClampingDistance') await expect(u.codeLocator).toContainText('minClampingDistance')
} }
) )
@ -1022,7 +1008,6 @@ test(
) )
} }
}) })
} }
) )
@ -1211,7 +1196,6 @@ test(
await expect(page.getByText('router-template-slate')).toBeVisible() await expect(page.getByText('router-template-slate')).toBeVisible()
await expect(page.getByText('New Project')).toBeVisible() await expect(page.getByText('New Project')).toBeVisible()
}) })
} }
) )
@ -1271,9 +1255,9 @@ test(
await page.getByTestId('project-directory-button').click() await page.getByTestId('project-directory-button').click()
await handleFile await handleFile
await expect.poll(() => page.locator('section#projectDirectory input').inputValue()).toContain( await expect
newProjectDirName .poll(() => page.locator('section#projectDirectory input').inputValue())
) .toContain(newProjectDirName)
await page.getByTestId('settings-close-button').click() await page.getByTestId('settings-close-button').click()
@ -1291,7 +1275,6 @@ test(
await page.getByTestId('project-directory-settings-link').click() await page.getByTestId('project-directory-settings-link').click()
const handleFile = electronApp.evaluate( const handleFile = electronApp.evaluate(
async ({ dialog }, filePaths) => { async ({ dialog }, filePaths) => {
dialog.showOpenDialog = () => dialog.showOpenDialog = () =>
@ -1369,7 +1352,6 @@ test(
await expect(page.getByText(name)).toBeVisible() await expect(page.getByText(name)).toBeVisible()
} }
}) })
} }
) )
@ -1475,7 +1457,6 @@ test(
false false
) )
}) })
} }
) )
@ -1534,7 +1515,6 @@ test(
expect(selectedText.length).toBe(0) expect(selectedText.length).toBe(0)
await expect(u.codeLocator).toHaveText('') await expect(u.codeLocator).toHaveText('')
}) })
} }
) )
@ -1554,7 +1534,6 @@ test(
await expect(page.getByTestId('app-theme')).toHaveValue('dark') await expect(page.getByTestId('app-theme')).toHaveValue('dark')
await page.getByTestId('app-theme').selectOption('light') await page.getByTestId('app-theme').selectOption('light')
}) })
await test.step('Starting the app again and we can see the same theme', async () => { await test.step('Starting the app again and we can see the same theme', async () => {
@ -1563,7 +1542,6 @@ test(
page.on('console', console.log) page.on('console', console.log)
await expect(page.getByTestId('app-theme')).toHaveValue('light') await expect(page.getByTestId('app-theme')).toHaveValue('light')
}) })
} }
) )
@ -1605,6 +1583,5 @@ test.fixme(
await expect(projectLink).toContainText(projectNames[index]) await expect(projectLink).toContainText(projectNames[index])
} }
}) })
} }
) )

File diff suppressed because it is too large Load Diff

View File

@ -3,210 +3,221 @@ import { test, expect } from './zoo-test'
import { commonPoints, getUtils } from './test-utils' import { commonPoints, getUtils } from './test-utils'
test.describe('Test network and connection issues', () => { test.describe('Test network and connection issues', () => {
test('simulate network down and network little widget', async ({ page, homePage }) => { const u = await getUtils(page) test('simulate network down and network little widget', async ({
await page.setBodyDimensions({ width: 1200, height: 500 }) page,
homePage,
await homePage.goToModelingScene() }) => {
const u = await getUtils(page)
const networkToggle = page.getByTestId('network-toggle') await page.setBodyDimensions({ width: 1200, height: 500 })
// This is how we wait until the stream is online
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled({ timeout: 15000 })
const networkWidget = page.locator('[data-testid="network-toggle"]')
await expect(networkWidget).toBeVisible()
await networkWidget.hover()
const networkPopover = page.locator('[data-testid="network-popover"]')
await expect(networkPopover).not.toBeVisible()
// (First check) Expect the network to be up
await expect(networkToggle).toContainText('Connected')
// Click the network widget
await networkWidget.click()
// Check the modal opened.
await expect(networkPopover).toBeVisible()
// Click off the modal.
await page.mouse.click(100, 100)
await expect(networkPopover).not.toBeVisible()
// Turn off the network
await u.emulateNetworkConditions({
offline: true,
// values of 0 remove any active throttling. crbug.com/456324#c9
latency: 0,
downloadThroughput: -1,
uploadThroughput: -1,
})
// Expect the network to be down
await expect(networkToggle).toContainText('Problem')
// Click the network widget
await networkWidget.click()
// Check the modal opened.
await expect(networkPopover).toBeVisible()
// Click off the modal.
await page.mouse.click(0, 0)
await expect(networkPopover).not.toBeVisible()
// Turn back on the network
await u.emulateNetworkConditions({
offline: false,
// values of 0 remove any active throttling. crbug.com/456324#c9
latency: 0,
downloadThroughput: -1,
uploadThroughput: -1,
})
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled({ timeout: 15000 })
// (Second check) expect the network to be up
await expect(networkToggle).toContainText('Connected') })
test('Engine disconnect & reconnect in sketch mode', async ({ page, browserName, homePage }) => { // TODO: Don't skip Mac for these. After `window.tearDown` is working in Safari, these should work on webkit await homePage.goToModelingScene()
const networkToggle = page.getByTestId('network-toggle')
const networkToggle = page.getByTestId('network-toggle')
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) // This is how we wait until the stream is online
const PUR = 400 / 37.5 //pixeltoUnitRatio await expect(
page.getByRole('button', { name: 'Start Sketch' })
await homePage.goToModelingScene() ).not.toBeDisabled({ timeout: 15000 })
await u.waitForPageLoad()
const networkWidget = page.locator('[data-testid="network-toggle"]')
await u.openDebugPanel() await expect(networkWidget).toBeVisible()
// click on "Start Sketch" button await networkWidget.hover()
await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click() const networkPopover = page.locator('[data-testid="network-popover"]')
await page.waitForTimeout(100) await expect(networkPopover).not.toBeVisible()
// select a plane // (First check) Expect the network to be up
await page.mouse.click(700, 200) await expect(networkToggle).toContainText('Connected')
await expect(page.locator('.cm-content')).toHaveText( // Click the network widget
`sketch001 = startSketchOn('XZ')` await networkWidget.click()
)
await u.closeDebugPanel() // Check the modal opened.
await expect(networkPopover).toBeVisible()
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
// Click off the modal.
const startXPx = 600 await page.mouse.click(100, 100)
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10) await expect(networkPopover).not.toBeVisible()
await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn('XZ') // Turn off the network
await u.emulateNetworkConditions({
offline: true,
// values of 0 remove any active throttling. crbug.com/456324#c9
latency: 0,
downloadThroughput: -1,
uploadThroughput: -1,
})
// Expect the network to be down
await expect(networkToggle).toContainText('Problem')
// Click the network widget
await networkWidget.click()
// Check the modal opened.
await expect(networkPopover).toBeVisible()
// Click off the modal.
await page.mouse.click(0, 0)
await expect(networkPopover).not.toBeVisible()
// Turn back on the network
await u.emulateNetworkConditions({
offline: false,
// values of 0 remove any active throttling. crbug.com/456324#c9
latency: 0,
downloadThroughput: -1,
uploadThroughput: -1,
})
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled({ timeout: 15000 })
// (Second check) expect the network to be up
await expect(networkToggle).toContainText('Connected')
})
test('Engine disconnect & reconnect in sketch mode', async ({
page,
browserName,
homePage,
}) => {
// TODO: Don't skip Mac for these. After `window.tearDown` is working in Safari, these should work on webkit
const networkToggle = page.getByTestId('network-toggle')
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
await homePage.goToModelingScene()
await u.waitForPageLoad()
await u.openDebugPanel()
// click on "Start Sketch" button
await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(100)
// select a plane
await page.mouse.click(700, 200)
await expect(page.locator('.cm-content')).toHaveText(
`sketch001 = startSketchOn('XZ')`
)
await u.closeDebugPanel()
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
const startXPx = 600
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn('XZ')
|> startProfileAt(${commonPoints.startAt}, %)`) |> startProfileAt(${commonPoints.startAt}, %)`)
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10) await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
await page.waitForTimeout(100) await page.waitForTimeout(100)
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn('XZ') .toHaveText(`sketch001 = startSketchOn('XZ')
|> startProfileAt(${commonPoints.startAt}, %) |> startProfileAt(${commonPoints.startAt}, %)
|> xLine(${commonPoints.num1}, %)`) |> xLine(${commonPoints.num1}, %)`)
// Expect the network to be up // Expect the network to be up
await expect(networkToggle).toContainText('Connected') await expect(networkToggle).toContainText('Connected')
// simulate network down // simulate network down
await u.emulateNetworkConditions({ await u.emulateNetworkConditions({
offline: true, offline: true,
// values of 0 remove any active throttling. crbug.com/456324#c9 // values of 0 remove any active throttling. crbug.com/456324#c9
latency: 0, latency: 0,
downloadThroughput: -1, downloadThroughput: -1,
uploadThroughput: -1, uploadThroughput: -1,
}) })
// Expect the network to be down // Expect the network to be down
await expect(networkToggle).toContainText('Problem') await expect(networkToggle).toContainText('Problem')
// Ensure we are not in sketch mode // Ensure we are not in sketch mode
await expect( await expect(
page.getByRole('button', { name: 'Exit Sketch' }) page.getByRole('button', { name: 'Exit Sketch' })
).not.toBeVisible() ).not.toBeVisible()
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible() ).toBeVisible()
// simulate network up // simulate network up
await u.emulateNetworkConditions({ await u.emulateNetworkConditions({
offline: false, offline: false,
// values of 0 remove any active throttling. crbug.com/456324#c9 // values of 0 remove any active throttling. crbug.com/456324#c9
latency: 0, latency: 0,
downloadThroughput: -1, downloadThroughput: -1,
uploadThroughput: -1, uploadThroughput: -1,
}) })
// Wait for the app to be ready for use // Wait for the app to be ready for use
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled({ timeout: 15000 }) ).not.toBeDisabled({ timeout: 15000 })
// Expect the network to be up // Expect the network to be up
await expect(networkToggle).toContainText('Connected') await expect(networkToggle).toContainText('Connected')
await expect(page.getByTestId('loading-stream')).not.toBeAttached() await expect(page.getByTestId('loading-stream')).not.toBeAttached()
// Click off the code pane. // Click off the code pane.
await page.mouse.click(100, 100) await page.mouse.click(100, 100)
// select a line // select a line
await page.getByText(`startProfileAt(${commonPoints.startAt}, %)`).click() await page.getByText(`startProfileAt(${commonPoints.startAt}, %)`).click()
// enter sketch again // enter sketch again
await u.doAndWaitForCmd( await u.doAndWaitForCmd(
() => page.getByRole('button', { name: 'Edit Sketch' }).click(), () => page.getByRole('button', { name: 'Edit Sketch' }).click(),
'default_camera_get_settings' 'default_camera_get_settings'
) )
await page.waitForTimeout(150) await page.waitForTimeout(150)
// Click the line tool // Click the line tool
await page.getByRole('button', { name: 'line Line', exact: true }).click() await page.getByRole('button', { name: 'line Line', exact: true }).click()
await page.waitForTimeout(150) await page.waitForTimeout(150)
// Ensure we can continue sketching // Ensure we can continue sketching
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20) await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
await expect.poll(u.normalisedEditorCode) await expect.poll(u.normalisedEditorCode)
.toBe(`sketch001 = startSketchOn('XZ') .toBe(`sketch001 = startSketchOn('XZ')
|> startProfileAt([12.34, -12.34], %) |> startProfileAt([12.34, -12.34], %)
|> xLine(12.34, %) |> xLine(12.34, %)
|> line([-12.34, 12.34], %) |> line([-12.34, 12.34], %)
`) `)
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(startXPx, 500 - PUR * 20) await page.mouse.click(startXPx, 500 - PUR * 20)
await expect.poll(u.normalisedEditorCode) await expect.poll(u.normalisedEditorCode)
.toBe(`sketch001 = startSketchOn('XZ') .toBe(`sketch001 = startSketchOn('XZ')
|> startProfileAt([12.34, -12.34], %) |> startProfileAt([12.34, -12.34], %)
|> xLine(12.34, %) |> xLine(12.34, %)
|> line([-12.34, 12.34], %) |> line([-12.34, 12.34], %)
|> xLine(-12.34, %) |> xLine(-12.34, %)
`) `)
// Unequip line tool // Unequip line tool
await page.keyboard.press('Escape') await page.keyboard.press('Escape')
// Make sure we didn't pop out of sketch mode. // Make sure we didn't pop out of sketch mode.
await expect( await expect(
page.getByRole('button', { name: 'Exit Sketch' }) page.getByRole('button', { name: 'Exit Sketch' })
).toBeVisible() ).toBeVisible()
await expect( await expect(
page.getByRole('button', { name: 'line Line', exact: true }) page.getByRole('button', { name: 'line Line', exact: true })
).not.toHaveAttribute('aria-pressed', 'true') ).not.toHaveAttribute('aria-pressed', 'true')
// Exit sketch // Exit sketch
await page.keyboard.press('Escape') await page.keyboard.press('Escape')
await expect( await expect(
page.getByRole('button', { name: 'Exit Sketch' }) page.getByRole('button', { name: 'Exit Sketch' })
).not.toBeVisible() }) ).not.toBeVisible()
})
}) })

View File

@ -1157,3 +1157,12 @@ export function getPixelRGBs(page: Page) {
}) })
} }
} }
export async function pollEditorLinesSelectedLength(page: Page, lines: number) {
return expect
.poll(async () => {
const lines = await page.locator('.cm-activeLine').all()
return lines.length
})
.toBe(lines)
}

View File

@ -1,30 +1,118 @@
import { test, expect } from './zoo-test' import { test, expect } from './zoo-test'
import { EngineCommand } from 'lang/std/artifactGraph' import { EngineCommand } from 'lang/std/artifactGraph'
import { uuidv4 } from 'lib/utils' import { uuidv4 } from 'lib/utils'
import { getUtils, } from './test-utils' import { getUtils } from './test-utils'
test.describe('Testing Camera Movement', () => { test.describe('Testing Camera Movement', () => {
test('Can move camera reliably', async ({ page, context, homePage }) => { test('Can move camera reliably', async ({ page, context, homePage }) => {
const u = await getUtils(page) const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await u.openAndClearDebugPanel() await u.openAndClearDebugPanel()
await u.closeKclCodePanel() await u.closeKclCodePanel()
const camPos: [number, number, number] = [0, 85, 85] const camPos: [number, number, number] = [0, 85, 85]
const bakeInRetries = async ( const bakeInRetries = async (
mouseActions: any, mouseActions: any,
xyz: [number, number, number], xyz: [number, number, number],
cnt = 0 cnt = 0
) => { ) => {
// hack that we're implemented our own retry instead of using retries built into playwright. // hack that we're implemented our own retry instead of using retries built into playwright.
// however each of these camera drags can be flaky, because of udp // however each of these camera drags can be flaky, because of udp
// and so putting them together means only one needs to fail to make this test extra flaky. // and so putting them together means only one needs to fail to make this test extra flaky.
// this way we can retry within the test // this way we can retry within the test
// We could break them out into separate tests, but the longest past of the test is waiting // We could break them out into separate tests, but the longest past of the test is waiting
// for the stream to start, so it can be good to bundle related things together. // for the stream to start, so it can be good to bundle related things together.
const camCommand: EngineCommand = {
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_look_at',
center: { x: 0, y: 0, z: 0 },
vantage: { x: camPos[0], y: camPos[1], z: camPos[2] },
up: { x: 0, y: 0, z: 1 },
},
}
const updateCamCommand: EngineCommand = {
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_get_settings',
},
}
await u.sendCustomCmd(camCommand)
await page.waitForTimeout(100)
await u.sendCustomCmd(updateCamCommand)
await page.waitForTimeout(100)
// rotate
await u.closeDebugPanel()
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(100)
// const yo = page.getByTestId('cam-x-position').inputValue()
await u.doAndWaitForImageDiff(async () => {
await mouseActions()
await u.openAndClearDebugPanel()
await u.closeDebugPanel()
await page.waitForTimeout(100)
}, 300)
await u.openAndClearDebugPanel()
await page.getByTestId('cam-x-position').isVisible()
const vals = await Promise.all([
page.getByTestId('cam-x-position').inputValue(),
page.getByTestId('cam-y-position').inputValue(),
page.getByTestId('cam-z-position').inputValue(),
])
const xError = Math.abs(Number(vals[0]) + xyz[0])
const yError = Math.abs(Number(vals[1]) + xyz[1])
const zError = Math.abs(Number(vals[2]) + xyz[2])
let shouldRetry = false
if (xError > 5 || yError > 5 || zError > 5) {
if (cnt > 2) {
console.log('xVal', vals[0], 'xError', xError)
console.log('yVal', vals[1], 'yError', yError)
console.log('zVal', vals[2], 'zError', zError)
throw new Error('Camera position not as expected')
}
shouldRetry = true
}
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(100)
if (shouldRetry) await bakeInRetries(mouseActions, xyz, cnt + 1)
}
await bakeInRetries(async () => {
await page.mouse.move(700, 200)
await page.mouse.down({ button: 'right' })
const appLogoBBox = await page.getByTestId('app-logo').boundingBox()
expect(appLogoBBox).not.toBeNull()
if (!appLogoBBox) throw new Error('app logo not found')
await page.mouse.move(
appLogoBBox.x + appLogoBBox.width / 2,
appLogoBBox.y + appLogoBBox.height / 2
)
await page.mouse.move(600, 303)
await page.mouse.up({ button: 'right' })
}, [4, -10.5, -120])
await bakeInRetries(async () => {
await page.keyboard.down('Shift')
await page.mouse.move(600, 200)
await page.mouse.down({ button: 'right' })
await page.mouse.move(700, 200, { steps: 2 })
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Shift')
}, [-19, -85, -85])
const camCommand: EngineCommand = { const camCommand: EngineCommand = {
type: 'modeling_cmd_req', type: 'modeling_cmd_req',
cmd_id: uuidv4(), cmd_id: uuidv4(),
@ -46,421 +134,344 @@ test.describe('Testing Camera Movement', () => {
await page.waitForTimeout(100) await page.waitForTimeout(100)
await u.sendCustomCmd(updateCamCommand) await u.sendCustomCmd(updateCamCommand)
await page.waitForTimeout(100) await page.waitForTimeout(100)
// rotate await u.clearCommandLogs()
await u.closeDebugPanel() await u.closeDebugPanel()
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(200)
// zoom
await u.doAndWaitForImageDiff(async () => {
await page.keyboard.down('Control')
await page.mouse.move(700, 400)
await page.mouse.down({ button: 'right' })
await page.mouse.move(700, 300)
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Control')
await u.openDebugPanel()
await page.waitForTimeout(300)
await u.clearCommandLogs()
await u.closeDebugPanel()
}, 300)
// zoom with scroll
await u.openAndClearDebugPanel()
// TODO, it appears we don't get the cam setting back from the engine when the interaction is zoom into `backInRetries` once the information is sent back on zoom
// await expect(Math.abs(Number(await page.getByTestId('cam-x-position').inputValue()) + 12)).toBeLessThan(1.5)
// await expect(Math.abs(Number(await page.getByTestId('cam-y-position').inputValue()) - 85)).toBeLessThan(1.5)
// await expect(Math.abs(Number(await page.getByTestId('cam-z-position').inputValue()) - 85)).toBeLessThan(1.5)
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await bakeInRetries(async () => {
await page.mouse.move(700, 400)
await page.mouse.wheel(0, -100)
}, [0, -85, -85])
})
test('Zoom should be consistent when exiting or entering sketches', async ({
page,
homePage,
}) => {
// start new sketch pan and zoom before exiting, when exiting the sketch should stay in the same place
// than zoom and pan outside of sketch mode and enter again and it should not change from where it is
// than again for sketching
test.skip(process.platform !== 'darwin', 'Zoom should be consistent')
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.openDebugPanel()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible()
// click on "Start Sketch" button
await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click() await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(100) await page.waitForTimeout(100)
// const yo = page.getByTestId('cam-x-position').inputValue()
// select a plane
await u.doAndWaitForImageDiff(async () => { await page.mouse.click(700, 325)
await mouseActions()
let code = `sketch001 = startSketchOn('XY')`
await u.openAndClearDebugPanel() await expect(u.codeLocator).toHaveText(code)
await u.closeDebugPanel()
await u.closeDebugPanel()
await page.waitForTimeout(100) await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
}, 300)
// move the camera slightly
await u.openAndClearDebugPanel()
await page.getByTestId('cam-x-position').isVisible()
const vals = await Promise.all([
page.getByTestId('cam-x-position').inputValue(),
page.getByTestId('cam-y-position').inputValue(),
page.getByTestId('cam-z-position').inputValue(),
])
const xError = Math.abs(Number(vals[0]) + xyz[0])
const yError = Math.abs(Number(vals[1]) + xyz[1])
const zError = Math.abs(Number(vals[2]) + xyz[2])
let shouldRetry = false
if (xError > 5 || yError > 5 || zError > 5) {
if (cnt > 2) {
console.log('xVal', vals[0], 'xError', xError)
console.log('yVal', vals[1], 'yError', yError)
console.log('zVal', vals[2], 'zError', zError)
throw new Error('Camera position not as expected')
}
shouldRetry = true
}
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(100)
if (shouldRetry) await bakeInRetries(mouseActions, xyz, cnt + 1)
}
await bakeInRetries(async () => {
await page.mouse.move(700, 200)
await page.mouse.down({ button: 'right' })
const appLogoBBox = await page.getByTestId('app-logo').boundingBox()
expect(appLogoBBox).not.toBeNull()
if (!appLogoBBox) throw new Error('app logo not found')
await page.mouse.move(
appLogoBBox.x + appLogoBBox.width / 2,
appLogoBBox.y + appLogoBBox.height / 2
)
await page.mouse.move(600, 303)
await page.mouse.up({ button: 'right' })
}, [4, -10.5, -120])
await bakeInRetries(async () => {
await page.keyboard.down('Shift') await page.keyboard.down('Shift')
await page.mouse.move(600, 200) await page.mouse.move(700, 300)
await page.mouse.down({ button: 'right' }) await page.mouse.down({ button: 'right' })
await page.mouse.move(700, 200, { steps: 2 }) await page.mouse.move(800, 200)
await page.mouse.up({ button: 'right' }) await page.mouse.up({ button: 'right' })
await page.keyboard.up('Shift') await page.keyboard.up('Shift')
}, [-19, -85, -85])
const camCommand: EngineCommand = {
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_look_at',
center: { x: 0, y: 0, z: 0 },
vantage: { x: camPos[0], y: camPos[1], z: camPos[2] },
up: { x: 0, y: 0, z: 1 },
},
}
const updateCamCommand: EngineCommand = {
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_get_settings',
},
}
await u.sendCustomCmd(camCommand)
await page.waitForTimeout(100)
await u.sendCustomCmd(updateCamCommand)
await page.waitForTimeout(100)
await u.clearCommandLogs()
await u.closeDebugPanel()
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(200)
// zoom
await u.doAndWaitForImageDiff(async () => {
await page.keyboard.down('Control')
await page.mouse.move(700, 400)
await page.mouse.down({ button: 'right' })
await page.mouse.move(700, 300)
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Control')
await u.openDebugPanel()
await page.waitForTimeout(300)
await u.clearCommandLogs()
await u.closeDebugPanel()
}, 300)
// zoom with scroll
await u.openAndClearDebugPanel()
// TODO, it appears we don't get the cam setting back from the engine when the interaction is zoom into `backInRetries` once the information is sent back on zoom
// await expect(Math.abs(Number(await page.getByTestId('cam-x-position').inputValue()) + 12)).toBeLessThan(1.5)
// await expect(Math.abs(Number(await page.getByTestId('cam-y-position').inputValue()) - 85)).toBeLessThan(1.5)
// await expect(Math.abs(Number(await page.getByTestId('cam-z-position').inputValue()) - 85)).toBeLessThan(1.5)
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await bakeInRetries(async () => {
await page.mouse.move(700, 400)
await page.mouse.wheel(0, -100)
}, [0, -85, -85]) })
test('Zoom should be consistent when exiting or entering sketches', async ({ page, homePage }) => { // start new sketch pan and zoom before exiting, when exiting the sketch should stay in the same place let y = 350,
// than zoom and pan outside of sketch mode and enter again and it should not change from where it is x = 948
// than again for sketching
await u.canvasLocator.click({ position: { x: 783, y } })
test.skip(process.platform !== 'darwin', 'Zoom should be consistent') code += `\n |> startProfileAt([8.12, -12.98], %)`
const u = await getUtils(page) // await expect(u.codeLocator).toHaveText(code)
await page.setBodyDimensions({ width: 1200, height: 500 }) await u.canvasLocator.click({ position: { x, y } })
code += `\n |> line([11.18, 0], %)`
await homePage.goToModelingScene() // await expect(u.codeLocator).toHaveText(code)
await u.openDebugPanel() await u.canvasLocator.click({ position: { x, y: 275 } })
code += `\n |> line([0, 6.99], %)`
await expect( // await expect(u.codeLocator).toHaveText(code)
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled() // click the line button
await expect( await page.getByRole('button', { name: 'line Line', exact: true }).click()
page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible() const hoverOverNothing = async () => {
// await u.canvasLocator.hover({position: {x: 700, y: 325}})
// click on "Start Sketch" button await page.mouse.move(700, 325)
await u.clearCommandLogs() await page.waitForTimeout(100)
await page.getByRole('button', { name: 'Start Sketch' }).click() await expect(page.getByTestId('hover-highlight')).not.toBeVisible({
await page.waitForTimeout(100) timeout: 10_000,
})
// select a plane }
await page.mouse.click(700, 325)
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
let code = `sketch001 = startSketchOn('XY')`
await expect(u.codeLocator).toHaveText(code) await page.waitForTimeout(200)
await u.closeDebugPanel() // hover over horizontal line
await u.canvasLocator.hover({ position: { x: 800, y } })
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
// move the camera slightly
await page.keyboard.down('Shift')
await page.mouse.move(700, 300)
await page.mouse.down({ button: 'right' })
await page.mouse.move(800, 200)
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Shift')
let y = 350,
x = 948
await u.canvasLocator.click({ position: { x: 783, y } })
code += `\n |> startProfileAt([8.12, -12.98], %)`
// await expect(u.codeLocator).toHaveText(code)
await u.canvasLocator.click({ position: { x, y } })
code += `\n |> line([11.18, 0], %)`
// await expect(u.codeLocator).toHaveText(code)
await u.canvasLocator.click({ position: { x, y: 275 } })
code += `\n |> line([0, 6.99], %)`
// await expect(u.codeLocator).toHaveText(code)
// click the line button
await page.getByRole('button', { name: 'line Line', exact: true }).click()
const hoverOverNothing = async () => {
// await u.canvasLocator.hover({position: {x: 700, y: 325}})
await page.mouse.move(700, 325)
await page.waitForTimeout(100)
await expect(page.getByTestId('hover-highlight')).not.toBeVisible({
timeout: 10_000, timeout: 10_000,
}) })
} await page.waitForTimeout(200)
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
await page.waitForTimeout(200)
// hover over horizontal line
await u.canvasLocator.hover({ position: { x: 800, y } })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
// hover over vertical line
await u.canvasLocator.hover({ position: { x, y: 325 } })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// click exit sketch
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(400)
await hoverOverNothing()
await page.waitForTimeout(200)
// hover over horizontal line
await page.mouse.move(858, y, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(x, 325)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(857, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
// now click it
await page.mouse.click(857, y)
await expect(
page.getByRole('button', { name: 'Edit Sketch' })
).toBeVisible()
await hoverOverNothing()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
await page.waitForTimeout(400)
x = 975
y = 468
await page.waitForTimeout(100)
await page.mouse.move(x, 419, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
await page.mouse.move(x, 419)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
}) })
test(`Zoom by scroll should not fire while orbiting`, async ({ page, homePage }) => { /** await hoverOverNothing()
* Currently we only allow zooming by scroll when no other camera movement is happening, await page.waitForTimeout(200)
* set within cameraMouseDragGuards in cameraControls.ts, // hover over vertical line
* until the engine supports unifying multiple camera movements. await u.canvasLocator.hover({ position: { x, y: 325 } })
* This verifies that scrollCallback's guard is working as expected. await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
*/ timeout: 10_000,
const u = await getUtils(page) })
// Constants and locators await hoverOverNothing()
const settingsLink = page.getByTestId('settings-link')
const settingsDialogHeading = page.getByRole('heading', { // click exit sketch
name: 'Settings', await page.getByRole('button', { name: 'Exit Sketch' }).click()
exact: true, await page.waitForTimeout(400)
})
const userSettingsTab = page.getByRole('radio', { name: 'User' }) await hoverOverNothing()
const mouseControlsSetting = page await page.waitForTimeout(200)
.locator('#mouseControls') // hover over horizontal line
.getByRole('combobox') await page.mouse.move(858, y, { steps: 5 })
const mouseControlSuccesToast = page.getByText( await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
'Set mouse controls to "Solidworks"' timeout: 10_000,
) })
const settingsCloseButton = page.getByTestId('settings-close-button')
const gizmo = page.locator('[aria-label*=gizmo]') await hoverOverNothing()
const resetCameraButton = page.getByRole('button', { name: 'Reset view' })
const orbitMouseStart = { x: 800, y: 130 } // hover over vertical line
const orbitMouseEnd = { x: 0, y: 130 } await page.mouse.move(x, 325)
const mid = (v1: number, v2: number) => v1 + (v2 - v1) / 2 await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
type Point = { x: number; y: number } timeout: 10_000,
const midPoint = (p1: Point, p2: Point) => ({ })
x: mid(p1.x, p2.x),
y: mid(p1.y, p2.y), await hoverOverNothing()
})
const orbitMouseStepOne = midPoint(orbitMouseStart, orbitMouseEnd) // hover over vertical line
const expectedStartCamZPosition = 64.0 await page.mouse.move(857, y)
const expectedZoomCamZPosition = 32.0 await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
const expectedOrbitCamZPosition = 64.0 timeout: 10_000,
})
await test.step(`Test setup`, async () => { // now click it
await homePage.goToModelingScene() await page.mouse.click(857, y)
await u.closeKclCodePanel()
// This test requires the mouse controls to be set to Solidworks await expect(
await u.openDebugPanel() page.getByRole('button', { name: 'Edit Sketch' })
await test.step(`Set mouse controls setting to Solidworks`, async () => { ).toBeVisible()
await settingsLink.click() await hoverOverNothing()
await expect(settingsDialogHeading).toBeVisible() await page.getByRole('button', { name: 'Edit Sketch' }).click()
await userSettingsTab.click()
await mouseControlsSetting.selectOption({ label: 'Solidworks' }) await page.waitForTimeout(400)
await expect(mouseControlSuccesToast).toBeVisible()
await settingsCloseButton.click() x = 975
y = 468
await page.waitForTimeout(100)
await page.mouse.move(x, 419, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
await page.mouse.move(x, 419)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
}) })
}) })
await test.step(`Test scrolling zoom works`, async () => { test(`Zoom by scroll should not fire while orbiting`, async ({
await resetCamera() page,
await page.mouse.move(orbitMouseStart.x, orbitMouseStart.y) homePage,
await page.mouse.wheel(0, -100) }) => {
await test.step(`Force a refresh of the camera position`, async () => { /**
await u.openAndClearDebugPanel() * Currently we only allow zooming by scroll when no other camera movement is happening,
await u.sendCustomCmd({ * set within cameraMouseDragGuards in cameraControls.ts,
type: 'modeling_cmd_req', * until the engine supports unifying multiple camera movements.
cmd_id: uuidv4(), * This verifies that scrollCallback's guard is working as expected.
cmd: { */
type: 'default_camera_get_settings', const u = await getUtils(page)
},
}) // Constants and locators
await u.waitForCmdReceive('default_camera_get_settings') const settingsLink = page.getByTestId('settings-link')
const settingsDialogHeading = page.getByRole('heading', {
name: 'Settings',
exact: true,
}) })
const userSettingsTab = page.getByRole('radio', { name: 'User' })
await expect const mouseControlsSetting = page
.poll(getCameraZValue, { .locator('#mouseControls')
message: 'Camera should be at expected position after zooming', .getByRole('combobox')
}) const mouseControlSuccesToast = page.getByText(
.toEqual(expectedZoomCamZPosition) 'Set mouse controls to "Solidworks"'
}) )
const settingsCloseButton = page.getByTestId('settings-close-button')
await test.step(`Test orbiting works`, async () => { const gizmo = page.locator('[aria-label*=gizmo]')
await doOrbitWith() const resetCameraButton = page.getByRole('button', { name: 'Reset view' })
}) const orbitMouseStart = { x: 800, y: 130 }
const orbitMouseEnd = { x: 0, y: 130 }
await test.step(`Test scrolling while orbiting doesn't zoom`, async () => { const mid = (v1: number, v2: number) => v1 + (v2 - v1) / 2
await doOrbitWith(async () => { type Point = { x: number; y: number }
await page.mouse.wheel(0, -100) const midPoint = (p1: Point, p2: Point) => ({
x: mid(p1.x, p2.x),
y: mid(p1.y, p2.y),
}) })
}) const orbitMouseStepOne = midPoint(orbitMouseStart, orbitMouseEnd)
const expectedStartCamZPosition = 64.0
// Helper functions const expectedZoomCamZPosition = 32.0
async function resetCamera() { const expectedOrbitCamZPosition = 64.0
await test.step(`Reset camera`, async () => {
await test.step(`Test setup`, async () => {
await homePage.goToModelingScene()
await u.closeKclCodePanel()
// This test requires the mouse controls to be set to Solidworks
await u.openDebugPanel() await u.openDebugPanel()
await u.clearCommandLogs() await test.step(`Set mouse controls setting to Solidworks`, async () => {
await u.doAndWaitForCmd(async () => { await settingsLink.click()
await gizmo.click({ button: 'right' }) await expect(settingsDialogHeading).toBeVisible()
await resetCameraButton.click() await userSettingsTab.click()
}, 'zoom_to_fit') await mouseControlsSetting.selectOption({ label: 'Solidworks' })
await expect await expect(mouseControlSuccesToast).toBeVisible()
.poll(getCameraZValue, { await settingsCloseButton.click()
message: 'Camera Z should be at expected position after reset', })
})
.toEqual(expectedStartCamZPosition)
}) })
}
await test.step(`Test scrolling zoom works`, async () => {
async function getCameraZValue() { await resetCamera()
return page
.getByTestId('cam-z-position')
.inputValue()
.then((value) => parseFloat(value))
}
async function doOrbitWith(callback = async () => {}) {
await resetCamera()
await test.step(`Perform orbit`, async () => {
await page.mouse.move(orbitMouseStart.x, orbitMouseStart.y) await page.mouse.move(orbitMouseStart.x, orbitMouseStart.y)
await page.mouse.down({ button: 'middle' }) await page.mouse.wheel(0, -100)
await page.mouse.move(orbitMouseStepOne.x, orbitMouseStepOne.y, { await test.step(`Force a refresh of the camera position`, async () => {
steps: 3, await u.openAndClearDebugPanel()
await u.sendCustomCmd({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_get_settings',
},
})
await u.waitForCmdReceive('default_camera_get_settings')
}) })
await callback()
await page.mouse.move(orbitMouseEnd.x, orbitMouseEnd.y, {
steps: 3,
})
})
await test.step(`Verify orbit`, async () => {
await expect await expect
.poll(getCameraZValue, { .poll(getCameraZValue, {
message: 'Camera should be at expected position after orbiting', message: 'Camera should be at expected position after zooming',
}) })
.toEqual(expectedOrbitCamZPosition) .toEqual(expectedZoomCamZPosition)
await page.mouse.up({ button: 'middle' })
}) })
} })
await test.step(`Test orbiting works`, async () => {
await doOrbitWith()
})
await test.step(`Test scrolling while orbiting doesn't zoom`, async () => {
await doOrbitWith(async () => {
await page.mouse.wheel(0, -100)
})
})
// Helper functions
async function resetCamera() {
await test.step(`Reset camera`, async () => {
await u.openDebugPanel()
await u.clearCommandLogs()
await u.doAndWaitForCmd(async () => {
await gizmo.click({ button: 'right' })
await resetCameraButton.click()
}, 'zoom_to_fit')
await expect
.poll(getCameraZValue, {
message: 'Camera Z should be at expected position after reset',
})
.toEqual(expectedStartCamZPosition)
})
}
async function getCameraZValue() {
return page
.getByTestId('cam-z-position')
.inputValue()
.then((value) => parseFloat(value))
}
async function doOrbitWith(callback = async () => {}) {
await resetCamera()
await test.step(`Perform orbit`, async () => {
await page.mouse.move(orbitMouseStart.x, orbitMouseStart.y)
await page.mouse.down({ button: 'middle' })
await page.mouse.move(orbitMouseStepOne.x, orbitMouseStepOne.y, {
steps: 3,
})
await callback()
await page.mouse.move(orbitMouseEnd.x, orbitMouseEnd.y, {
steps: 3,
})
})
await test.step(`Verify orbit`, async () => {
await expect
.poll(getCameraZValue, {
message: 'Camera should be at expected position after orbiting',
})
.toEqual(expectedOrbitCamZPosition)
await page.mouse.up({ button: 'middle' })
})
}
})
}) })

File diff suppressed because it is too large Load Diff

View File

@ -52,15 +52,105 @@ test.describe('Testing Gizmo', () => {
} of cases) { } of cases) {
test(`check ${testDescription}`, async ({ page, homePage }) => { test(`check ${testDescription}`, async ({ page, homePage }) => {
const u = await getUtils(page) const u = await getUtils(page)
await page.addInitScript((TEST_CODE_GIZMO) => {
localStorage.setItem('persistCode', TEST_CODE_GIZMO)
}, TEST_CODE_GIZMO)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await page.waitForTimeout(100)
// wait for execution done
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.sendCustomCmd({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_look_at',
vantage: {
x: 3000,
y: 3000,
z: 3000,
},
center: {
x: 800,
y: -152,
z: 26,
},
up: { x: 0, y: 0, z: 1 },
},
})
await page.waitForTimeout(100)
await u.clearCommandLogs()
await u.sendCustomCmd({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_get_settings',
},
})
await u.waitForCmdReceive('default_camera_get_settings')
await u.clearCommandLogs()
await page.mouse.move(clickPosition.x, clickPosition.y)
await page.waitForTimeout(100)
await page.mouse.click(clickPosition.x, clickPosition.y)
await page.mouse.move(0, 0)
await u.waitForCmdReceive('default_camera_look_at')
await u.clearCommandLogs()
await u.sendCustomCmd({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_get_settings',
},
})
await u.waitForCmdReceive('default_camera_get_settings')
await Promise.all([
// position
expect(page.getByTestId('cam-x-position')).toHaveValue(
expectedCameraPosition.x.toString()
),
expect(page.getByTestId('cam-y-position')).toHaveValue(
expectedCameraPosition.y.toString()
),
expect(page.getByTestId('cam-z-position')).toHaveValue(
expectedCameraPosition.z.toString()
),
// target
expect(page.getByTestId('cam-x-target')).toHaveValue(
expectedCameraTarget.x.toString()
),
expect(page.getByTestId('cam-y-target')).toHaveValue(
expectedCameraTarget.y.toString()
),
expect(page.getByTestId('cam-z-target')).toHaveValue(
expectedCameraTarget.z.toString()
),
])
})
}
test('Context menu and popover menu', async ({ page, homePage }) => {
const testCase = {
testDescription: 'Right view',
expectedCameraPosition: { x: 5660.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
}
// Test prelude taken from the above test
const u = await getUtils(page)
await page.addInitScript((TEST_CODE_GIZMO) => { await page.addInitScript((TEST_CODE_GIZMO) => {
localStorage.setItem('persistCode', TEST_CODE_GIZMO) localStorage.setItem('persistCode', TEST_CODE_GIZMO)
}, TEST_CODE_GIZMO) }, TEST_CODE_GIZMO)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await u.waitForPageLoad()
await page.waitForTimeout(100) await page.waitForTimeout(100)
// wait for execution done // wait for execution done
await u.openDebugPanel() await u.openDebugPanel()
@ -93,15 +183,22 @@ test.describe('Testing Gizmo', () => {
}, },
}) })
await u.waitForCmdReceive('default_camera_get_settings') await u.waitForCmdReceive('default_camera_get_settings')
// Now find and select the correct
// view from the context menu
await u.clearCommandLogs() await u.clearCommandLogs()
await page.mouse.move(clickPosition.x, clickPosition.y) const gizmo = page.locator('[aria-label*=gizmo]')
await page.waitForTimeout(100) await gizmo.click({ button: 'right' })
await page.mouse.click(clickPosition.x, clickPosition.y) const buttonToTest = page.getByRole('button', {
await page.mouse.move(0, 0) name: testCase.testDescription,
})
await expect(buttonToTest).toBeVisible()
await buttonToTest.click()
// Now assert we've moved to the correct view
// Taken from the above test
await u.waitForCmdReceive('default_camera_look_at') await u.waitForCmdReceive('default_camera_look_at')
await u.clearCommandLogs()
await u.sendCustomCmd({ await u.sendCustomCmd({
type: 'modeling_cmd_req', type: 'modeling_cmd_req',
cmd_id: uuidv4(), cmd_id: uuidv4(),
@ -110,135 +207,41 @@ test.describe('Testing Gizmo', () => {
}, },
}) })
await u.waitForCmdReceive('default_camera_get_settings') await u.waitForCmdReceive('default_camera_get_settings')
await page.waitForTimeout(400)
await Promise.all([ await Promise.all([
// position // position
expect(page.getByTestId('cam-x-position')).toHaveValue( expect(page.getByTestId('cam-x-position')).toHaveValue(
expectedCameraPosition.x.toString() testCase.expectedCameraPosition.x.toString()
), ),
expect(page.getByTestId('cam-y-position')).toHaveValue( expect(page.getByTestId('cam-y-position')).toHaveValue(
expectedCameraPosition.y.toString() testCase.expectedCameraPosition.y.toString()
), ),
expect(page.getByTestId('cam-z-position')).toHaveValue( expect(page.getByTestId('cam-z-position')).toHaveValue(
expectedCameraPosition.z.toString() testCase.expectedCameraPosition.z.toString()
), ),
// target // target
expect(page.getByTestId('cam-x-target')).toHaveValue( expect(page.getByTestId('cam-x-target')).toHaveValue(
expectedCameraTarget.x.toString() testCase.expectedCameraTarget.x.toString()
), ),
expect(page.getByTestId('cam-y-target')).toHaveValue( expect(page.getByTestId('cam-y-target')).toHaveValue(
expectedCameraTarget.y.toString() testCase.expectedCameraTarget.y.toString()
), ),
expect(page.getByTestId('cam-z-target')).toHaveValue( expect(page.getByTestId('cam-z-target')).toHaveValue(
expectedCameraTarget.z.toString() testCase.expectedCameraTarget.z.toString()
), ),
]) }) ])
}
test('Context menu and popover menu', async ({ page, homePage }) => { const testCase = { // Now test the popover menu.
testDescription: 'Right view', // It has the same click handlers, so we can just
expectedCameraPosition: { x: 5660.02, y: -152, z: 26 }, // test that it opens and contains the same content.
expectedCameraTarget: { x: 800, y: -152, z: 26 }, const gizmoPopoverButton = page.getByRole('button', {
} name: 'view settings',
})
// Test prelude taken from the above test await expect(gizmoPopoverButton).toBeVisible()
const u = await getUtils(page) await gizmoPopoverButton.click()
await page.addInitScript((TEST_CODE_GIZMO) => { await expect(buttonToTest).toBeVisible()
localStorage.setItem('persistCode', TEST_CODE_GIZMO)
}, TEST_CODE_GIZMO)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await page.waitForTimeout(100)
// wait for execution done
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.sendCustomCmd({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_look_at',
vantage: {
x: 3000,
y: 3000,
z: 3000,
},
center: {
x: 800,
y: -152,
z: 26,
},
up: { x: 0, y: 0, z: 1 },
},
}) })
await page.waitForTimeout(100)
await u.clearCommandLogs()
await u.sendCustomCmd({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_get_settings',
},
})
await u.waitForCmdReceive('default_camera_get_settings')
// Now find and select the correct
// view from the context menu
await u.clearCommandLogs()
const gizmo = page.locator('[aria-label*=gizmo]')
await gizmo.click({ button: 'right' })
const buttonToTest = page.getByRole('button', {
name: testCase.testDescription,
})
await expect(buttonToTest).toBeVisible()
await buttonToTest.click()
// Now assert we've moved to the correct view
// Taken from the above test
await u.waitForCmdReceive('default_camera_look_at')
await u.sendCustomCmd({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_get_settings',
},
})
await u.waitForCmdReceive('default_camera_get_settings')
await page.waitForTimeout(400)
await Promise.all([
// position
expect(page.getByTestId('cam-x-position')).toHaveValue(
testCase.expectedCameraPosition.x.toString()
),
expect(page.getByTestId('cam-y-position')).toHaveValue(
testCase.expectedCameraPosition.y.toString()
),
expect(page.getByTestId('cam-z-position')).toHaveValue(
testCase.expectedCameraPosition.z.toString()
),
// target
expect(page.getByTestId('cam-x-target')).toHaveValue(
testCase.expectedCameraTarget.x.toString()
),
expect(page.getByTestId('cam-y-target')).toHaveValue(
testCase.expectedCameraTarget.y.toString()
),
expect(page.getByTestId('cam-z-target')).toHaveValue(
testCase.expectedCameraTarget.z.toString()
),
])
// Now test the popover menu.
// It has the same click handlers, so we can just
// test that it opens and contains the same content.
const gizmoPopoverButton = page.getByRole('button', {
name: 'view settings',
})
await expect(gizmoPopoverButton).toBeVisible()
await gizmoPopoverButton.click()
await expect(buttonToTest).toBeVisible() })
}) })
test.describe(`Testing gizmo, fixture-based`, () => { test.describe(`Testing gizmo, fixture-based`, () => {
@ -252,7 +255,9 @@ test.describe(`Testing gizmo, fixture-based`, () => {
scene, scene,
}) => { }) => {
await context.addInitScript(() => { await context.addInitScript(() => {
localStorage.setItem('persistCode', ` localStorage.setItem(
'persistCode',
`
const sketch002 = startSketchOn('XZ') const sketch002 = startSketchOn('XZ')
|> startProfileAt([-108.83, -57.48], %) |> startProfileAt([-108.83, -57.48], %)
|> angledLine([0, 105.13], %, $rectangleSegmentA001) |> angledLine([0, 105.13], %, $rectangleSegmentA001)
@ -271,7 +276,8 @@ test.describe(`Testing gizmo, fixture-based`, () => {
radius: 182.8 radius: 182.8
}, %) }, %)
|> extrude(50, %) |> extrude(50, %)
`) `
)
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })

View File

@ -1,18 +1,10 @@
import { test, expect } from '@playwright/test' import { test, expect } from './zoo-test'
import { getUtils, setup, tearDown } from './test-utils' import { getUtils } from './test-utils'
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates' import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates'
import * as TOML from '@iarna/toml' import * as TOML from '@iarna/toml'
test.beforeEach(async ({ context, page }, testInfo) => {
await setup(context, page, testInfo)
})
test.afterEach(async ({ page }, testInfo) => {
await tearDown(page, testInfo)
})
test.describe('Test toggling perspective', () => { test.describe('Test toggling perspective', () => {
test('via command palette and toggle', async ({ page }) => { test('via command palette and toggle', async ({ page, homePage }) => {
const u = await getUtils(page) const u = await getUtils(page)
// Locators and constants // Locators and constants
@ -40,8 +32,8 @@ test.describe('Test toggling perspective', () => {
}) })
await test.step('Setup', async () => { await test.step('Setup', async () => {
await page.setViewportSize({ width: screenWidth, height: screenHeight }) await page.setBodyDimensions({ width: screenWidth, height: screenHeight })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.closeKclCodePanel() await u.closeKclCodePanel()
await expect await expect
.poll(async () => locationToHaveColor(backgroundColor), { .poll(async () => locationToHaveColor(backgroundColor), {
@ -87,7 +79,7 @@ test.describe('Test toggling perspective', () => {
} }
) )
await page.reload() await page.reload()
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await expect await expect
.poll(async () => locationToHaveColor(xzPlaneColor), { .poll(async () => locationToHaveColor(xzPlaneColor), {
timeout: 5000, timeout: 5000,

View File

@ -7,7 +7,8 @@ import packageJson from '../package.json'
import { MachinesListing } from 'components/MachineManagerProvider' import { MachinesListing } from 'components/MachineManagerProvider'
import chokidar from 'chokidar' import chokidar from 'chokidar'
const resizeWindow = (width: number, height: number) => ipcRenderer.invoke('app.resizeWindow', [width, height]) const resizeWindow = (width: number, height: number) =>
ipcRenderer.invoke('app.resizeWindow', [width, height])
const open = (args: any) => ipcRenderer.invoke('dialog.showOpenDialog', args) const open = (args: any) => ipcRenderer.invoke('dialog.showOpenDialog', args)
const save = (args: any) => ipcRenderer.invoke('dialog.showSaveDialog', args) const save = (args: any) => ipcRenderer.invoke('dialog.showSaveDialog', args)
const openExternal = (url: any) => ipcRenderer.invoke('shell.openExternal', url) const openExternal = (url: any) => ipcRenderer.invoke('shell.openExternal', url)