Merge main (tests changed x_x) and pass all constraints.spec tests (pain)
This commit is contained in:
		| @ -52,10 +52,12 @@ export class SceneFixture { | ||||
|   } | ||||
|  | ||||
|   expectState = async (expected: SceneSerialised) => { | ||||
|     return expect.poll(async () => await this._serialiseScene(), { | ||||
|       intervals: [1_000, 2_000, 10_000], | ||||
|       timeout: 60000, | ||||
|     }).toEqual(expected) | ||||
|     return expect | ||||
|       .poll(async () => await this._serialiseScene(), { | ||||
|         intervals: [1_000, 2_000, 10_000], | ||||
|         timeout: 60000, | ||||
|       }) | ||||
|       .toEqual(expected) | ||||
|   } | ||||
|  | ||||
|   reConstruct = (page: Page) => { | ||||
|  | ||||
| @ -115,9 +115,7 @@ test.describe('Onboarding tests', () => { | ||||
|       await replayButton.click() | ||||
|  | ||||
|       // Ensure we see the warning, and that the code has not yet updated | ||||
|       await expect( | ||||
|         page.getByText('Would you like to create') | ||||
|       ).toBeVisible() | ||||
|       await expect(page.getByText('Would you like to create')).toBeVisible() | ||||
|       await expect(page.locator('.cm-content')).toHaveText(initialCode) | ||||
|  | ||||
|       const nextButton = page.getByTestId('onboarding-next') | ||||
| @ -263,7 +261,9 @@ test.describe('Onboarding tests', () => { | ||||
|       await page.setBodyDimensions({ width: 1200, height: 1080 }) | ||||
|       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, '') | ||||
|  | ||||
|  | ||||
| @ -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( | ||||
|   'verify extruding circle works', | ||||
|   async ({ context, homePage, cmdBar, editor, toolbar, scene }) => { | ||||
|     const file = await fs.readFile( | ||||
|       path.resolve( | ||||
|         __dirname, | ||||
|         '../../', | ||||
|         './src/wasm-lib/tests/executor/inputs/test-circle-extrude.kcl' | ||||
|       ), | ||||
|       'utf-8' | ||||
|     ) | ||||
|     await context.addInitScript((file) => { | ||||
|       localStorage.setItem('persistCode', file) | ||||
|     }, file) | ||||
|     await homePage.goToModelingScene() | ||||
| test('verify extruding circle works', async ({ | ||||
|   context, | ||||
|   homePage, | ||||
|   cmdBar, | ||||
|   editor, | ||||
|   toolbar, | ||||
|   scene, | ||||
| }) => { | ||||
|   const file = await fs.readFile( | ||||
|     path.resolve( | ||||
|       __dirname, | ||||
|       '../../', | ||||
|       './src/wasm-lib/tests/executor/inputs/test-circle-extrude.kcl' | ||||
|     ), | ||||
|     '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 scene.clickNoWhere() | ||||
|       await expect(toolbar.extrudeButton).toBeEnabled() | ||||
|   await test.step('because there is sweepable geometry, verify extrude is enable when nothing is selected', async () => { | ||||
|     await scene.clickNoWhere() | ||||
|     await expect(toolbar.extrudeButton).toBeEnabled() | ||||
|   }) | ||||
|  | ||||
|   await test.step('check code model connection works and that button is still enable once circle is selected ', async () => { | ||||
|     await moveToCircle() | ||||
|     const circleSnippet = | ||||
|       'circle({ center: [318.33, 168.1], radius: 182.8 }, %)' | ||||
|     await editor.expectState({ | ||||
|       activeLines: ["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 () => { | ||||
| @ -35,9 +50,7 @@ test( | ||||
|       const circleSnippet = | ||||
|         'circle({ center = [318.33, 168.1], radius = 182.8 }, %)' | ||||
|       await editor.expectState({ | ||||
|         activeLines: [ | ||||
|           "constsketch002=startSketchOn('XZ')" | ||||
|         ], | ||||
|         activeLines: ["constsketch002=startSketchOn('XZ')"], | ||||
|         highlightedCode: circleSnippet, | ||||
|         diagnostics: [], | ||||
|       }) | ||||
| @ -50,34 +63,35 @@ test( | ||||
|       }) | ||||
|       await expect(toolbar.extrudeButton).toBeEnabled() | ||||
|     }) | ||||
|     await expect(toolbar.extrudeButton).toBeEnabled() | ||||
|   }) | ||||
|  | ||||
|     await test.step('do extrude flow and check extrude code is added to editor', async () => { | ||||
|       await toolbar.extrudeButton.click() | ||||
|   await test.step('do extrude flow and check extrude code is added to editor', async () => { | ||||
|     await toolbar.extrudeButton.click() | ||||
|  | ||||
|       await cmdBar.expectState({ | ||||
|         stage: 'arguments', | ||||
|         currentArgKey: 'distance', | ||||
|         currentArgValue: '5', | ||||
|         headerArguments: { Selection: '1 face', Distance: '' }, | ||||
|         highlightedHeaderArg: 'distance', | ||||
|         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.expectState({ | ||||
|       stage: 'arguments', | ||||
|       currentArgKey: 'distance', | ||||
|       currentArgValue: '5', | ||||
|       headerArguments: { Selection: '1 face', Distance: '' }, | ||||
|       highlightedHeaderArg: 'distance', | ||||
|       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) | ||||
|   }) | ||||
| }) | ||||
|  | ||||
| test.describe('verify sketch on chamfer works', () => { | ||||
|   const _sketchOnAChamfer = | ||||
| @ -145,7 +159,9 @@ test.describe('verify sketch on chamfer works', () => { | ||||
|           pixelDiff: 50, | ||||
|         }) | ||||
|         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 () => { | ||||
| @ -160,30 +176,35 @@ test.describe('verify sketch on chamfer works', () => { | ||||
|         }) | ||||
|       }) | ||||
|     } | ||||
|   test( | ||||
|     'works on all edge selections and 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.kcl' | ||||
|         ), | ||||
|         'utf-8' | ||||
|       ) | ||||
|       await context.addInitScript((file) => { | ||||
|         localStorage.setItem('persistCode', file) | ||||
|       }, file) | ||||
|       await page.setBodyDimensions({ width: 1000, height: 500 }) | ||||
|       await homePage.goToModelingScene() | ||||
|   test('works on all edge selections and 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.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) | ||||
|     const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene) | ||||
|  | ||||
|       await sketchOnAChamfer({ | ||||
|         clickCoords: { x: 570, y: 220 }, | ||||
|         cameraPos: { x: 16020, y: -2000, z: 10500 }, | ||||
|         cameraTarget: { x: -150, y: -4500, z: -80 }, | ||||
|         beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01) | ||||
|     await sketchOnAChamfer({ | ||||
|       clickCoords: { x: 570, y: 220 }, | ||||
|       cameraPos: { x: 16020, y: -2000, z: 10500 }, | ||||
|       cameraTarget: { x: -150, y: -4500, z: -80 }, | ||||
|       beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01) | ||||
|       chamfer({length = 30,tags = [ | ||||
|       seg01, | ||||
|       getNextAdjacentEdge(yo), | ||||
| @ -191,10 +212,9 @@ test.describe('verify sketch on chamfer works', () => { | ||||
|       getOppositeEdge(seg01) | ||||
|     ]}, %)`, | ||||
|  | ||||
|         afterChamferSelectSnippet: | ||||
|           'sketch002 = startSketchOn(extrude001, seg03)', | ||||
|         afterRectangle1stClickSnippet: 'startProfileAt([160.39, 254.59], %)', | ||||
|         afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002) | ||||
|       afterChamferSelectSnippet: 'sketch002 = startSketchOn(extrude001, seg03)', | ||||
|       afterRectangle1stClickSnippet: 'startProfileAt([160.39, 254.59], %)', | ||||
|       afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002) | ||||
|     |> angledLine([ | ||||
|          segAng(rectangleSegmentA002) - 90, | ||||
|          105.26 | ||||
| @ -205,13 +225,13 @@ test.describe('verify sketch on chamfer works', () => { | ||||
|        ], %, $rectangleSegmentC001) | ||||
|     |> lineTo([profileStartX(%), profileStartY(%)], %) | ||||
|     |> close(%)`, | ||||
|       }) | ||||
|     }) | ||||
|  | ||||
|       await sketchOnAChamfer({ | ||||
|         clickCoords: { x: 690, y: 250 }, | ||||
|         cameraPos: { x: 16020, y: -2000, z: 10500 }, | ||||
|         cameraTarget: { x: -150, y: -4500, z: -80 }, | ||||
|         beforeChamferSnippet: `angledLine([ | ||||
|     await sketchOnAChamfer({ | ||||
|       clickCoords: { x: 690, y: 250 }, | ||||
|       cameraPos: { x: 16020, y: -2000, z: 10500 }, | ||||
|       cameraTarget: { x: -150, y: -4500, z: -80 }, | ||||
|       beforeChamferSnippet: `angledLine([ | ||||
|          segAng(rectangleSegmentA001) - 90, | ||||
|          217.26 | ||||
|        ], %, $seg01)chamfer({ | ||||
| @ -223,10 +243,9 @@ test.describe('verify sketch on chamfer works', () => { | ||||
|          ] | ||||
|        }, %)`, | ||||
|  | ||||
|         afterChamferSelectSnippet: | ||||
|           'sketch003 = startSketchOn(extrude001, seg04)', | ||||
|         afterRectangle1stClickSnippet: 'startProfileAt([-255.89, 255.28], %)', | ||||
|         afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003) | ||||
|       afterChamferSelectSnippet: 'sketch003 = startSketchOn(extrude001, seg04)', | ||||
|       afterRectangle1stClickSnippet: 'startProfileAt([-255.89, 255.28], %)', | ||||
|       afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003) | ||||
|     |> angledLine([ | ||||
|          segAng(rectangleSegmentA003) - 90, | ||||
|          106.84 | ||||
| @ -237,22 +256,21 @@ test.describe('verify sketch on chamfer works', () => { | ||||
|        ], %, $rectangleSegmentC002) | ||||
|     |> lineTo([profileStartX(%), profileStartY(%)], %) | ||||
|     |> close(%)`, | ||||
|       }) | ||||
|       await sketchOnAChamfer({ | ||||
|         clickCoords: { x: 677, y: 87 }, | ||||
|         cameraPos: { x: -6200, y: 1500, z: 6200 }, | ||||
|         cameraTarget: { x: 8300, y: 1100, z: 4800 }, | ||||
|         beforeChamferSnippet: `angledLine([0, 268.43], %, $rectangleSegmentA001)chamfer({ | ||||
|     }) | ||||
|     await sketchOnAChamfer({ | ||||
|       clickCoords: { x: 677, y: 87 }, | ||||
|       cameraPos: { x: -6200, y: 1500, z: 6200 }, | ||||
|       cameraTarget: { x: 8300, y: 1100, z: 4800 }, | ||||
|       beforeChamferSnippet: `angledLine([0, 268.43], %, $rectangleSegmentA001)chamfer({ | ||||
|          length = 30, | ||||
|          tags = [ | ||||
|            getNextAdjacentEdge(yo), | ||||
|            getNextAdjacentEdge(seg02) | ||||
|          ] | ||||
|        }, %)`, | ||||
|         afterChamferSelectSnippet: | ||||
|           'sketch003 = startSketchOn(extrude001, seg04)', | ||||
|         afterRectangle1stClickSnippet: 'startProfileAt([37.95, 322.96], %)', | ||||
|         afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003) | ||||
|       afterChamferSelectSnippet: 'sketch003 = startSketchOn(extrude001, seg04)', | ||||
|       afterRectangle1stClickSnippet: 'startProfileAt([37.95, 322.96], %)', | ||||
|       afterRectangle2ndClickSnippet: `angledLine([0, 11.56], %, $rectangleSegmentA003) | ||||
|     |> angledLine([ | ||||
|          segAng(rectangleSegmentA003) - 90, | ||||
|          106.84 | ||||
| @ -263,20 +281,19 @@ test.describe('verify sketch on chamfer works', () => { | ||||
|        ], %, $rectangleSegmentC002) | ||||
|     |> lineTo([profileStartX(%), profileStartY(%)], %) | ||||
|     |> close(%)`, | ||||
|       }) | ||||
|       /// last one | ||||
|       await sketchOnAChamfer({ | ||||
|         clickCoords: { x: 620, y: 300 }, | ||||
|         cameraPos: { x: -1100, y: -7700, z: 1600 }, | ||||
|         cameraTarget: { x: 1450, y: 670, z: 4000 }, | ||||
|         beforeChamferSnippet: `chamfer({ | ||||
|     }) | ||||
|     /// last one | ||||
|     await sketchOnAChamfer({ | ||||
|       clickCoords: { x: 620, y: 300 }, | ||||
|       cameraPos: { x: -1100, y: -7700, z: 1600 }, | ||||
|       cameraTarget: { x: 1450, y: 670, z: 4000 }, | ||||
|       beforeChamferSnippet: `chamfer({ | ||||
|          length = 30, | ||||
|          tags = [getNextAdjacentEdge(yo)] | ||||
|        }, %)`, | ||||
|         afterChamferSelectSnippet: | ||||
|           'sketch005 = startSketchOn(extrude001, seg06)', | ||||
|         afterRectangle1stClickSnippet: 'startProfileAt([-59.83, 19.69], %)', | ||||
|         afterRectangle2ndClickSnippet: `angledLine([0, 9.1], %, $rectangleSegmentA005) | ||||
|       afterChamferSelectSnippet: 'sketch005 = startSketchOn(extrude001, seg06)', | ||||
|       afterRectangle1stClickSnippet: 'startProfileAt([-59.83, 19.69], %)', | ||||
|       afterRectangle2ndClickSnippet: `angledLine([0, 9.1], %, $rectangleSegmentA005) | ||||
|  | ||||
|     |> angledLine([ | ||||
|          segAng(rectangleSegmentA005) - 90, | ||||
| @ -288,11 +305,11 @@ test.describe('verify sketch on chamfer works', () => { | ||||
|        ], %, $rectangleSegmentC004) | ||||
|     |> lineTo([profileStartX(%), profileStartY(%)], %) | ||||
|     |> close(%)`, | ||||
|       }) | ||||
|     }) | ||||
|  | ||||
|       await test.step('verify at the end of the test that final code is what is expected', async () => { | ||||
|         await editor.expectEditor.toContain( | ||||
|           `sketch001 = startSketchOn('XZ') | ||||
|     await test.step('verify at the end of the test that final code is what is expected', async () => { | ||||
|       await editor.expectEditor.toContain( | ||||
|         `sketch001 = startSketchOn('XZ') | ||||
|  | ||||
|       |> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag] | ||||
|       |> angledLine([0, 268.43], %, $rectangleSegmentA001) | ||||
| @ -373,47 +390,48 @@ test.describe('verify sketch on chamfer works', () => { | ||||
|       |> lineTo([profileStartX(%), profileStartY(%)], %) | ||||
|       |> close(%) | ||||
|     `, | ||||
|           { 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' | ||||
|         { shouldNormalise: true } | ||||
|       ) | ||||
|       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({ | ||||
|         clickCoords: { x: 570, y: 220 }, | ||||
|         cameraPos: { x: 16020, y: -2000, z: 10500 }, | ||||
|         cameraTarget: { x: -150, y: -4500, z: -80 }, | ||||
|         beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01) | ||||
|     await sketchOnAChamfer({ | ||||
|       clickCoords: { x: 570, y: 220 }, | ||||
|       cameraPos: { x: 16020, y: -2000, z: 10500 }, | ||||
|       cameraTarget: { x: -150, y: -4500, z: -80 }, | ||||
|       beforeChamferSnippet: `angledLine([segAng(rectangleSegmentA001)-90,217.26],%,$seg01) | ||||
|       chamfer({length=30,tags=[ | ||||
|       seg01, | ||||
|       getNextAdjacentEdge(yo), | ||||
|       getNextAdjacentEdge(seg02), | ||||
|       getOppositeEdge(seg01) | ||||
|     ]}, extrude001)`, | ||||
|         beforeChamferSnippetEnd: '}, extrude001)', | ||||
|         afterChamferSelectSnippet: | ||||
|           'sketch002 = startSketchOn(extrude001, seg03)', | ||||
|         afterRectangle1stClickSnippet: 'startProfileAt([160.39, 254.59], %)', | ||||
|         afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002) | ||||
|       beforeChamferSnippetEnd: '}, extrude001)', | ||||
|       afterChamferSelectSnippet: 'sketch002 = startSketchOn(extrude001, seg03)', | ||||
|       afterRectangle1stClickSnippet: 'startProfileAt([160.39, 254.59], %)', | ||||
|       afterRectangle2ndClickSnippet: `angledLine([0, 11.39], %, $rectangleSegmentA002) | ||||
|     |> angledLine([ | ||||
|          segAng(rectangleSegmentA002) - 90, | ||||
|          105.26 | ||||
| @ -424,9 +442,9 @@ test.describe('verify sketch on chamfer works', () => { | ||||
|        ], %, $rectangleSegmentC001) | ||||
|     |> lineTo([profileStartX(%), profileStartY(%)], %) | ||||
|     |> close(%)`, | ||||
|       }) | ||||
|       await editor.expectEditor.toContain( | ||||
|         `sketch001 = startSketchOn('XZ') | ||||
|     }) | ||||
|     await editor.expectEditor.toContain( | ||||
|       `sketch001 = startSketchOn('XZ') | ||||
|   |> startProfileAt([75.8, 317.2], %) | ||||
|   |> angledLine([0, 268.43], %, $rectangleSegmentA001) | ||||
|   |> angledLine([ | ||||
| @ -466,10 +484,9 @@ sketch002 = startSketchOn(extrude001, seg03) | ||||
|   |> lineTo([profileStartX(%), profileStartY(%)], %) | ||||
|   |> close(%) | ||||
| `, | ||||
|         { shouldNormalise: true } | ||||
|       ) | ||||
|     } | ||||
|   ) | ||||
|       { shouldNormalise: true } | ||||
|     ) | ||||
|   }) | ||||
| }) | ||||
|  | ||||
| test(`Verify axis, origin, and horizontal snapping`, async ({ | ||||
|  | ||||
| @ -56,7 +56,6 @@ test( | ||||
|     }) | ||||
|  | ||||
|     await expect(projectLinks).toHaveCount(0) | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -64,7 +63,6 @@ test( | ||||
|   'click help/keybindings from home page', | ||||
|   { tag: '@electron' }, | ||||
|   async ({ page }, testInfo) => { | ||||
|  | ||||
|     await page.setBodyDimensions({ width: 1200, height: 500 }) | ||||
|  | ||||
|     page.on('console', console.log) | ||||
| @ -76,7 +74,6 @@ test( | ||||
|     await page.getByTestId('keybindings-button').click() | ||||
|     // Make sure the keyboard shortcuts modal is visible. | ||||
|     await expect(page.getByText('Enter Sketch Mode')).toBeVisible() | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -114,7 +111,6 @@ test( | ||||
|     await page.getByTestId('keybindings-button').click() | ||||
|     // Make sure the keyboard shortcuts modal is visible. | ||||
|     await expect(page.getByText('Enter Sketch Mode')).toBeVisible() | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -148,7 +144,6 @@ test( | ||||
|     await page.hover('.cm-lint-marker-error') | ||||
|     const crypticErrorText = `Expected a tag declarator` | ||||
|     await expect(page.getByText(crypticErrorText).first()).toBeVisible() | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -240,7 +235,6 @@ test.describe('Can export from electron app', () => { | ||||
|           // clean up exported file | ||||
|           await fsp.rm(filepath) | ||||
|         }) | ||||
|  | ||||
|       } | ||||
|     ) | ||||
|   } | ||||
| @ -248,7 +242,7 @@ test.describe('Can export from electron app', () => { | ||||
| test( | ||||
|   'Rename and delete projects, also spam arrow keys when renaming', | ||||
|   { tag: '@electron' }, | ||||
|   async ({ context, page}, testInfo) => { | ||||
|   async ({ context, page }, testInfo) => { | ||||
|     await context.folderSetupFn(async (dir) => { | ||||
|       await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }) | ||||
|       await fsp.copyFile( | ||||
| @ -441,7 +435,6 @@ test( | ||||
|       // expect the name not to have changed | ||||
|       await expect(page.getByText('bracket')).toBeVisible() | ||||
|     }) | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -470,7 +463,6 @@ test( | ||||
|     // expect to still be on the home page | ||||
|     await expect(page.getByText('router-template-slate')).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()).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 expect(noProjectsMessage).toBeVisible() | ||||
|       }) | ||||
|  | ||||
|     } | ||||
|   ) | ||||
|   test( | ||||
| @ -642,7 +632,6 @@ test.describe(`Project management commands`, () => { | ||||
|         ).toBeVisible() | ||||
|         await expect(projectHomeLink).not.toHaveText(projectName) | ||||
|       }) | ||||
|  | ||||
|     } | ||||
|   ) | ||||
|   test( | ||||
| @ -692,7 +681,6 @@ test.describe(`Project management commands`, () => { | ||||
|         await expect(projectHomeLink).not.toBeVisible() | ||||
|         await expect(noProjectsMessage).toBeVisible() | ||||
|       }) | ||||
|  | ||||
|     } | ||||
|   ) | ||||
| }) | ||||
| @ -738,7 +726,6 @@ test( | ||||
|     await expect(u.codeLocator).toContainText( | ||||
|       'A mounting bracket for the Focusrite Scarlett Solo audio interface' | ||||
|     ) | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -794,10 +781,11 @@ test( | ||||
|       ).rejects.toThrow() | ||||
|       // eslint-disable-next-line jest/no-conditional-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() | ||||
|     } | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -876,7 +864,6 @@ test.fixme( | ||||
|         page.getByTestId('project-link').filter({ hasText: 'project-000' }) | ||||
|       ).toBeVisible() | ||||
|     }) | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -914,7 +901,6 @@ test( | ||||
|     await expect(u.codeLocator).toContainText('routerDiameter') | ||||
|     await expect(u.codeLocator).toContainText('templateGap') | ||||
|     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('New Project')).toBeVisible() | ||||
|     }) | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -1271,9 +1255,9 @@ test( | ||||
|       await page.getByTestId('project-directory-button').click() | ||||
|       await handleFile | ||||
|  | ||||
|       await expect.poll(() => page.locator('section#projectDirectory input').inputValue()).toContain( | ||||
|         newProjectDirName | ||||
|       ) | ||||
|       await expect | ||||
|         .poll(() => page.locator('section#projectDirectory input').inputValue()) | ||||
|         .toContain(newProjectDirName) | ||||
|  | ||||
|       await page.getByTestId('settings-close-button').click() | ||||
|  | ||||
| @ -1291,7 +1275,6 @@ test( | ||||
|  | ||||
|       await page.getByTestId('project-directory-settings-link').click() | ||||
|  | ||||
|  | ||||
|       const handleFile = electronApp.evaluate( | ||||
|         async ({ dialog }, filePaths) => { | ||||
|           dialog.showOpenDialog = () => | ||||
| @ -1369,7 +1352,6 @@ test( | ||||
|         await expect(page.getByText(name)).toBeVisible() | ||||
|       } | ||||
|     }) | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -1475,7 +1457,6 @@ test( | ||||
|         false | ||||
|       ) | ||||
|     }) | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -1534,7 +1515,6 @@ test( | ||||
|       expect(selectedText.length).toBe(0) | ||||
|       await expect(u.codeLocator).toHaveText('') | ||||
|     }) | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
| @ -1554,7 +1534,6 @@ test( | ||||
|       await expect(page.getByTestId('app-theme')).toHaveValue('dark') | ||||
|  | ||||
|       await page.getByTestId('app-theme').selectOption('light') | ||||
|  | ||||
|     }) | ||||
|  | ||||
|     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) | ||||
|       await expect(page.getByTestId('app-theme')).toHaveValue('light') | ||||
|  | ||||
|     }) | ||||
|   } | ||||
| ) | ||||
| @ -1605,6 +1583,5 @@ test.fixme( | ||||
|         await expect(projectLink).toContainText(projectNames[index]) | ||||
|       } | ||||
|     }) | ||||
|  | ||||
|   } | ||||
| ) | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -3,210 +3,221 @@ import { test, expect } from './zoo-test' | ||||
| import { commonPoints, getUtils } from './test-utils' | ||||
|  | ||||
| test.describe('Test network and connection issues', () => { | ||||
|   test('simulate network down and network little widget', async ({ page, homePage }) => { const u = await getUtils(page) | ||||
|   await page.setBodyDimensions({ width: 1200, height: 500 }) | ||||
|    | ||||
|   await homePage.goToModelingScene() | ||||
|    | ||||
|   const networkToggle = page.getByTestId('network-toggle') | ||||
|    | ||||
|   // 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('simulate network down and network little widget', async ({ | ||||
|     page, | ||||
|     homePage, | ||||
|   }) => { | ||||
|     const u = await getUtils(page) | ||||
|     await page.setBodyDimensions({ width: 1200, height: 500 }) | ||||
|  | ||||
|   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') | ||||
|     await homePage.goToModelingScene() | ||||
|  | ||||
|     const networkToggle = page.getByTestId('network-toggle') | ||||
|  | ||||
|     // 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 | ||||
|     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}, %)`) | ||||
|   await page.waitForTimeout(100) | ||||
|    | ||||
|   await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10) | ||||
|   await page.waitForTimeout(100) | ||||
|    | ||||
|   await expect(page.locator('.cm-content')) | ||||
|     .toHaveText(`sketch001 = startSketchOn('XZ') | ||||
|     await page.waitForTimeout(100) | ||||
|  | ||||
|     await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10) | ||||
|     await page.waitForTimeout(100) | ||||
|  | ||||
|     await expect(page.locator('.cm-content')) | ||||
|       .toHaveText(`sketch001 = startSketchOn('XZ') | ||||
|   |> startProfileAt(${commonPoints.startAt}, %) | ||||
|   |> xLine(${commonPoints.num1}, %)`) | ||||
|    | ||||
|   // Expect the network to be up | ||||
|   await expect(networkToggle).toContainText('Connected') | ||||
|    | ||||
|   // simulate network down | ||||
|   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') | ||||
|    | ||||
|   // Ensure we are not in sketch mode | ||||
|   await expect( | ||||
|     page.getByRole('button', { name: 'Exit Sketch' }) | ||||
|   ).not.toBeVisible() | ||||
|   await expect( | ||||
|     page.getByRole('button', { name: 'Start Sketch' }) | ||||
|   ).toBeVisible() | ||||
|    | ||||
|   // simulate network up | ||||
|   await u.emulateNetworkConditions({ | ||||
|     offline: false, | ||||
|     // values of 0 remove any active throttling. crbug.com/456324#c9 | ||||
|     latency: 0, | ||||
|     downloadThroughput: -1, | ||||
|     uploadThroughput: -1, | ||||
|   }) | ||||
|    | ||||
|   // Wait for the app to be ready for use | ||||
|   await expect( | ||||
|     page.getByRole('button', { name: 'Start Sketch' }) | ||||
|   ).not.toBeDisabled({ timeout: 15000 }) | ||||
|    | ||||
|   // Expect the network to be up | ||||
|   await expect(networkToggle).toContainText('Connected') | ||||
|   await expect(page.getByTestId('loading-stream')).not.toBeAttached() | ||||
|    | ||||
|   // Click off the code pane. | ||||
|   await page.mouse.click(100, 100) | ||||
|    | ||||
|   // select a line | ||||
|   await page.getByText(`startProfileAt(${commonPoints.startAt}, %)`).click() | ||||
|    | ||||
|   // enter sketch again | ||||
|   await u.doAndWaitForCmd( | ||||
|     () => page.getByRole('button', { name: 'Edit Sketch' }).click(), | ||||
|     'default_camera_get_settings' | ||||
|   ) | ||||
|   await page.waitForTimeout(150) | ||||
|    | ||||
|   // Click the line tool | ||||
|   await page.getByRole('button', { name: 'line Line', exact: true }).click() | ||||
|    | ||||
|   await page.waitForTimeout(150) | ||||
|    | ||||
|   // Ensure we can continue sketching | ||||
|   await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20) | ||||
|   await expect.poll(u.normalisedEditorCode) | ||||
|     .toBe(`sketch001 = startSketchOn('XZ') | ||||
|  | ||||
|     // Expect the network to be up | ||||
|     await expect(networkToggle).toContainText('Connected') | ||||
|  | ||||
|     // simulate network down | ||||
|     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') | ||||
|  | ||||
|     // Ensure we are not in sketch mode | ||||
|     await expect( | ||||
|       page.getByRole('button', { name: 'Exit Sketch' }) | ||||
|     ).not.toBeVisible() | ||||
|     await expect( | ||||
|       page.getByRole('button', { name: 'Start Sketch' }) | ||||
|     ).toBeVisible() | ||||
|  | ||||
|     // simulate network up | ||||
|     await u.emulateNetworkConditions({ | ||||
|       offline: false, | ||||
|       // values of 0 remove any active throttling. crbug.com/456324#c9 | ||||
|       latency: 0, | ||||
|       downloadThroughput: -1, | ||||
|       uploadThroughput: -1, | ||||
|     }) | ||||
|  | ||||
|     // Wait for the app to be ready for use | ||||
|     await expect( | ||||
|       page.getByRole('button', { name: 'Start Sketch' }) | ||||
|     ).not.toBeDisabled({ timeout: 15000 }) | ||||
|  | ||||
|     // Expect the network to be up | ||||
|     await expect(networkToggle).toContainText('Connected') | ||||
|     await expect(page.getByTestId('loading-stream')).not.toBeAttached() | ||||
|  | ||||
|     // Click off the code pane. | ||||
|     await page.mouse.click(100, 100) | ||||
|  | ||||
|     // select a line | ||||
|     await page.getByText(`startProfileAt(${commonPoints.startAt}, %)`).click() | ||||
|  | ||||
|     // enter sketch again | ||||
|     await u.doAndWaitForCmd( | ||||
|       () => page.getByRole('button', { name: 'Edit Sketch' }).click(), | ||||
|       'default_camera_get_settings' | ||||
|     ) | ||||
|     await page.waitForTimeout(150) | ||||
|  | ||||
|     // Click the line tool | ||||
|     await page.getByRole('button', { name: 'line Line', exact: true }).click() | ||||
|  | ||||
|     await page.waitForTimeout(150) | ||||
|  | ||||
|     // Ensure we can continue sketching | ||||
|     await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20) | ||||
|     await expect.poll(u.normalisedEditorCode) | ||||
|       .toBe(`sketch001 = startSketchOn('XZ') | ||||
|   |> startProfileAt([12.34, -12.34], %) | ||||
|   |> xLine(12.34, %) | ||||
|   |> line([-12.34, 12.34], %) | ||||
|  | ||||
| `) | ||||
|   await page.waitForTimeout(100) | ||||
|   await page.mouse.click(startXPx, 500 - PUR * 20) | ||||
|    | ||||
|   await expect.poll(u.normalisedEditorCode) | ||||
|     .toBe(`sketch001 = startSketchOn('XZ') | ||||
|     await page.waitForTimeout(100) | ||||
|     await page.mouse.click(startXPx, 500 - PUR * 20) | ||||
|  | ||||
|     await expect.poll(u.normalisedEditorCode) | ||||
|       .toBe(`sketch001 = startSketchOn('XZ') | ||||
|   |> startProfileAt([12.34, -12.34], %) | ||||
|   |> xLine(12.34, %) | ||||
|   |> line([-12.34, 12.34], %) | ||||
|   |> xLine(-12.34, %) | ||||
|  | ||||
| `) | ||||
|    | ||||
|   // Unequip line tool | ||||
|   await page.keyboard.press('Escape') | ||||
|   // Make sure we didn't pop out of sketch mode. | ||||
|   await expect( | ||||
|     page.getByRole('button', { name: 'Exit Sketch' }) | ||||
|   ).toBeVisible() | ||||
|   await expect( | ||||
|     page.getByRole('button', { name: 'line Line', exact: true }) | ||||
|   ).not.toHaveAttribute('aria-pressed', 'true') | ||||
|    | ||||
|   // Exit sketch | ||||
|   await page.keyboard.press('Escape') | ||||
|   await expect( | ||||
|     page.getByRole('button', { name: 'Exit Sketch' }) | ||||
|   ).not.toBeVisible() }) | ||||
|  | ||||
|     // Unequip line tool | ||||
|     await page.keyboard.press('Escape') | ||||
|     // Make sure we didn't pop out of sketch mode. | ||||
|     await expect( | ||||
|       page.getByRole('button', { name: 'Exit Sketch' }) | ||||
|     ).toBeVisible() | ||||
|     await expect( | ||||
|       page.getByRole('button', { name: 'line Line', exact: true }) | ||||
|     ).not.toHaveAttribute('aria-pressed', 'true') | ||||
|  | ||||
|     // Exit sketch | ||||
|     await page.keyboard.press('Escape') | ||||
|     await expect( | ||||
|       page.getByRole('button', { name: 'Exit Sketch' }) | ||||
|     ).not.toBeVisible() | ||||
|   }) | ||||
| }) | ||||
|  | ||||
| @ -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) | ||||
| } | ||||
|  | ||||
| @ -1,30 +1,118 @@ | ||||
| import { test, expect } from './zoo-test' | ||||
| import { EngineCommand } from 'lang/std/artifactGraph' | ||||
| import { uuidv4 } from 'lib/utils' | ||||
| import { getUtils,  } from './test-utils' | ||||
| import { getUtils } from './test-utils' | ||||
|  | ||||
| test.describe('Testing Camera Movement', () => { | ||||
|   test('Can move camera reliably', async ({ page, context, homePage }) => { | ||||
|   const u = await getUtils(page) | ||||
|   await page.setBodyDimensions({ width: 1200, height: 500 }) | ||||
|    | ||||
|   await homePage.goToModelingScene() | ||||
|   await u.openAndClearDebugPanel() | ||||
|   await u.closeKclCodePanel() | ||||
|    | ||||
|   const camPos: [number, number, number] = [0, 85, 85] | ||||
|   const bakeInRetries = async ( | ||||
|     mouseActions: any, | ||||
|     xyz: [number, number, number], | ||||
|     cnt = 0 | ||||
|   ) => { | ||||
|     // 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 | ||||
|     // 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 | ||||
|     // 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. | ||||
|    | ||||
|     const u = await getUtils(page) | ||||
|     await page.setBodyDimensions({ width: 1200, height: 500 }) | ||||
|  | ||||
|     await homePage.goToModelingScene() | ||||
|     await u.openAndClearDebugPanel() | ||||
|     await u.closeKclCodePanel() | ||||
|  | ||||
|     const camPos: [number, number, number] = [0, 85, 85] | ||||
|     const bakeInRetries = async ( | ||||
|       mouseActions: any, | ||||
|       xyz: [number, number, number], | ||||
|       cnt = 0 | ||||
|     ) => { | ||||
|       // 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 | ||||
|       // 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 | ||||
|       // 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. | ||||
|  | ||||
|       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 = { | ||||
|       type: 'modeling_cmd_req', | ||||
|       cmd_id: uuidv4(), | ||||
| @ -46,421 +134,344 @@ test.describe('Testing Camera Movement', () => { | ||||
|     await page.waitForTimeout(100) | ||||
|     await u.sendCustomCmd(updateCamCommand) | ||||
|     await page.waitForTimeout(100) | ||||
|    | ||||
|     // rotate | ||||
|  | ||||
|     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 | ||||
|     // 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.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 () => { | ||||
|  | ||||
|     // select a plane | ||||
|     await page.mouse.click(700, 325) | ||||
|  | ||||
|     let code = `sketch001 = startSketchOn('XY')` | ||||
|     await expect(u.codeLocator).toHaveText(code) | ||||
|     await u.closeDebugPanel() | ||||
|  | ||||
|     await page.waitForTimeout(500) // TODO detect animation ending, or disable animation | ||||
|  | ||||
|     // move the camera slightly | ||||
|     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.move(700, 200, { steps: 2 }) | ||||
|     await page.mouse.move(800, 200) | ||||
|     await page.mouse.up({ button: 'right' }) | ||||
|     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 | ||||
|   // 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.waitForTimeout(100) | ||||
|    | ||||
|   // select a plane | ||||
|   await page.mouse.click(700, 325) | ||||
|    | ||||
|   let code = `sketch001 = startSketchOn('XY')` | ||||
|   await expect(u.codeLocator).toHaveText(code) | ||||
|   await u.closeDebugPanel() | ||||
|    | ||||
|   await page.waitForTimeout(500) // TODO detect animation ending, or disable animation | ||||
|    | ||||
|   // 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({ | ||||
|     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, | ||||
|       }) | ||||
|     } | ||||
|  | ||||
|     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 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, | ||||
|   }) }) | ||||
|     await page.waitForTimeout(200) | ||||
|  | ||||
|   test(`Zoom by scroll should not fire while orbiting`, async ({ page, homePage }) => { /** | ||||
|    * Currently we only allow zooming by scroll when no other camera movement is happening, | ||||
|    * set within cameraMouseDragGuards in cameraControls.ts, | ||||
|    * until the engine supports unifying multiple camera movements. | ||||
|    * This verifies that scrollCallback's guard is working as expected. | ||||
|    */ | ||||
|   const u = await getUtils(page) | ||||
|    | ||||
|   // Constants and locators | ||||
|   const settingsLink = page.getByTestId('settings-link') | ||||
|   const settingsDialogHeading = page.getByRole('heading', { | ||||
|     name: 'Settings', | ||||
|     exact: true, | ||||
|   }) | ||||
|   const userSettingsTab = page.getByRole('radio', { name: 'User' }) | ||||
|   const mouseControlsSetting = page | ||||
|     .locator('#mouseControls') | ||||
|     .getByRole('combobox') | ||||
|   const mouseControlSuccesToast = page.getByText( | ||||
|     'Set mouse controls to "Solidworks"' | ||||
|   ) | ||||
|   const settingsCloseButton = page.getByTestId('settings-close-button') | ||||
|   const gizmo = page.locator('[aria-label*=gizmo]') | ||||
|   const resetCameraButton = page.getByRole('button', { name: 'Reset view' }) | ||||
|   const orbitMouseStart = { x: 800, y: 130 } | ||||
|   const orbitMouseEnd = { x: 0, y: 130 } | ||||
|   const mid = (v1: number, v2: number) => v1 + (v2 - v1) / 2 | ||||
|   type Point = { x: number; y: number } | ||||
|   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 | ||||
|   const expectedZoomCamZPosition = 32.0 | ||||
|   const expectedOrbitCamZPosition = 64.0 | ||||
|    | ||||
|   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 test.step(`Set mouse controls setting to Solidworks`, async () => { | ||||
|       await settingsLink.click() | ||||
|       await expect(settingsDialogHeading).toBeVisible() | ||||
|       await userSettingsTab.click() | ||||
|       await mouseControlsSetting.selectOption({ label: 'Solidworks' }) | ||||
|       await expect(mouseControlSuccesToast).toBeVisible() | ||||
|       await settingsCloseButton.click() | ||||
|     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, | ||||
|     }) | ||||
|   }) | ||||
|    | ||||
|   await test.step(`Test scrolling zoom works`, async () => { | ||||
|     await resetCamera() | ||||
|     await page.mouse.move(orbitMouseStart.x, orbitMouseStart.y) | ||||
|     await page.mouse.wheel(0, -100) | ||||
|     await test.step(`Force a refresh of the camera position`, async () => { | ||||
|       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') | ||||
|  | ||||
|   test(`Zoom by scroll should not fire while orbiting`, async ({ | ||||
|     page, | ||||
|     homePage, | ||||
|   }) => { | ||||
|     /** | ||||
|      * Currently we only allow zooming by scroll when no other camera movement is happening, | ||||
|      * set within cameraMouseDragGuards in cameraControls.ts, | ||||
|      * until the engine supports unifying multiple camera movements. | ||||
|      * This verifies that scrollCallback's guard is working as expected. | ||||
|      */ | ||||
|     const u = await getUtils(page) | ||||
|  | ||||
|     // Constants and locators | ||||
|     const settingsLink = page.getByTestId('settings-link') | ||||
|     const settingsDialogHeading = page.getByRole('heading', { | ||||
|       name: 'Settings', | ||||
|       exact: true, | ||||
|     }) | ||||
|    | ||||
|     await expect | ||||
|       .poll(getCameraZValue, { | ||||
|         message: 'Camera should be at expected position after zooming', | ||||
|       }) | ||||
|       .toEqual(expectedZoomCamZPosition) | ||||
|   }) | ||||
|    | ||||
|   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) | ||||
|     const userSettingsTab = page.getByRole('radio', { name: 'User' }) | ||||
|     const mouseControlsSetting = page | ||||
|       .locator('#mouseControls') | ||||
|       .getByRole('combobox') | ||||
|     const mouseControlSuccesToast = page.getByText( | ||||
|       'Set mouse controls to "Solidworks"' | ||||
|     ) | ||||
|     const settingsCloseButton = page.getByTestId('settings-close-button') | ||||
|     const gizmo = page.locator('[aria-label*=gizmo]') | ||||
|     const resetCameraButton = page.getByRole('button', { name: 'Reset view' }) | ||||
|     const orbitMouseStart = { x: 800, y: 130 } | ||||
|     const orbitMouseEnd = { x: 0, y: 130 } | ||||
|     const mid = (v1: number, v2: number) => v1 + (v2 - v1) / 2 | ||||
|     type Point = { x: number; y: number } | ||||
|     const midPoint = (p1: Point, p2: Point) => ({ | ||||
|       x: mid(p1.x, p2.x), | ||||
|       y: mid(p1.y, p2.y), | ||||
|     }) | ||||
|   }) | ||||
|    | ||||
|   // Helper functions | ||||
|   async function resetCamera() { | ||||
|     await test.step(`Reset camera`, async () => { | ||||
|     const orbitMouseStepOne = midPoint(orbitMouseStart, orbitMouseEnd) | ||||
|     const expectedStartCamZPosition = 64.0 | ||||
|     const expectedZoomCamZPosition = 32.0 | ||||
|     const expectedOrbitCamZPosition = 64.0 | ||||
|  | ||||
|     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.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) | ||||
|       await test.step(`Set mouse controls setting to Solidworks`, async () => { | ||||
|         await settingsLink.click() | ||||
|         await expect(settingsDialogHeading).toBeVisible() | ||||
|         await userSettingsTab.click() | ||||
|         await mouseControlsSetting.selectOption({ label: 'Solidworks' }) | ||||
|         await expect(mouseControlSuccesToast).toBeVisible() | ||||
|         await settingsCloseButton.click() | ||||
|       }) | ||||
|     }) | ||||
|   } | ||||
|    | ||||
|   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 test.step(`Test scrolling zoom works`, async () => { | ||||
|       await resetCamera() | ||||
|       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 page.mouse.wheel(0, -100) | ||||
|       await test.step(`Force a refresh of the camera position`, async () => { | ||||
|         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 | ||||
|         .poll(getCameraZValue, { | ||||
|           message: 'Camera should be at expected position after orbiting', | ||||
|           message: 'Camera should be at expected position after zooming', | ||||
|         }) | ||||
|         .toEqual(expectedOrbitCamZPosition) | ||||
|       await page.mouse.up({ button: 'middle' }) | ||||
|         .toEqual(expectedZoomCamZPosition) | ||||
|     }) | ||||
|   } }) | ||||
|  | ||||
|     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
											
										
									
								
							| @ -52,15 +52,105 @@ test.describe('Testing Gizmo', () => { | ||||
|   } of cases) { | ||||
|     test(`check ${testDescription}`, async ({ page, homePage }) => { | ||||
|       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) => { | ||||
|       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() | ||||
| @ -93,15 +183,22 @@ test.describe('Testing Gizmo', () => { | ||||
|       }, | ||||
|     }) | ||||
|     await u.waitForCmdReceive('default_camera_get_settings') | ||||
|      | ||||
|  | ||||
|     // Now find and select the correct | ||||
|     // view from the context menu | ||||
|     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) | ||||
|     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.clearCommandLogs() | ||||
|      | ||||
|  | ||||
|     await u.sendCustomCmd({ | ||||
|       type: 'modeling_cmd_req', | ||||
|       cmd_id: uuidv4(), | ||||
| @ -110,135 +207,41 @@ test.describe('Testing Gizmo', () => { | ||||
|       }, | ||||
|     }) | ||||
|     await u.waitForCmdReceive('default_camera_get_settings') | ||||
|      | ||||
|     await page.waitForTimeout(400) | ||||
|  | ||||
|     await Promise.all([ | ||||
|       // position | ||||
|       expect(page.getByTestId('cam-x-position')).toHaveValue( | ||||
|         expectedCameraPosition.x.toString() | ||||
|         testCase.expectedCameraPosition.x.toString() | ||||
|       ), | ||||
|       expect(page.getByTestId('cam-y-position')).toHaveValue( | ||||
|         expectedCameraPosition.y.toString() | ||||
|         testCase.expectedCameraPosition.y.toString() | ||||
|       ), | ||||
|       expect(page.getByTestId('cam-z-position')).toHaveValue( | ||||
|         expectedCameraPosition.z.toString() | ||||
|         testCase.expectedCameraPosition.z.toString() | ||||
|       ), | ||||
|       // target | ||||
|       expect(page.getByTestId('cam-x-target')).toHaveValue( | ||||
|         expectedCameraTarget.x.toString() | ||||
|         testCase.expectedCameraTarget.x.toString() | ||||
|       ), | ||||
|       expect(page.getByTestId('cam-y-target')).toHaveValue( | ||||
|         expectedCameraTarget.y.toString() | ||||
|         testCase.expectedCameraTarget.y.toString() | ||||
|       ), | ||||
|       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 = { | ||||
|     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) => { | ||||
|     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 }, | ||||
|     }, | ||||
|     // 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() | ||||
|   }) | ||||
|   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`, () => { | ||||
| @ -252,7 +255,9 @@ test.describe(`Testing gizmo, fixture-based`, () => { | ||||
|     scene, | ||||
|   }) => { | ||||
|     await context.addInitScript(() => { | ||||
|       localStorage.setItem('persistCode', ` | ||||
|       localStorage.setItem( | ||||
|         'persistCode', | ||||
|         ` | ||||
|         const sketch002 = startSketchOn('XZ') | ||||
|           |> startProfileAt([-108.83, -57.48], %) | ||||
|           |> angledLine([0, 105.13], %, $rectangleSegmentA001) | ||||
| @ -271,7 +276,8 @@ test.describe(`Testing gizmo, fixture-based`, () => { | ||||
|                radius: 182.8 | ||||
|              }, %) | ||||
|           |> extrude(50, %) | ||||
|       `) | ||||
|       ` | ||||
|       ) | ||||
|     }) | ||||
|  | ||||
|     await page.setBodyDimensions({ width: 1000, height: 500 }) | ||||
|  | ||||
| @ -1,18 +1,10 @@ | ||||
| import { test, expect } from '@playwright/test' | ||||
| import { getUtils, setup, tearDown } from './test-utils' | ||||
| import { test, expect } from './zoo-test' | ||||
| import { getUtils } from './test-utils' | ||||
| import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates' | ||||
| 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('via command palette and toggle', async ({ page }) => { | ||||
|   test('via command palette and toggle', async ({ page, homePage }) => { | ||||
|     const u = await getUtils(page) | ||||
|  | ||||
|     // Locators and constants | ||||
| @ -40,8 +32,8 @@ test.describe('Test toggling perspective', () => { | ||||
|     }) | ||||
|  | ||||
|     await test.step('Setup', async () => { | ||||
|       await page.setViewportSize({ width: screenWidth, height: screenHeight }) | ||||
|       await u.waitForAuthSkipAppStart() | ||||
|       await page.setBodyDimensions({ width: screenWidth, height: screenHeight }) | ||||
|       await homePage.goToModelingScene() | ||||
|       await u.closeKclCodePanel() | ||||
|       await expect | ||||
|         .poll(async () => locationToHaveColor(backgroundColor), { | ||||
| @ -87,7 +79,7 @@ test.describe('Test toggling perspective', () => { | ||||
|         } | ||||
|       ) | ||||
|       await page.reload() | ||||
|       await u.waitForAuthSkipAppStart() | ||||
|       await homePage.goToModelingScene() | ||||
|       await expect | ||||
|         .poll(async () => locationToHaveColor(xzPlaneColor), { | ||||
|           timeout: 5000, | ||||
|  | ||||
| @ -7,7 +7,8 @@ import packageJson from '../package.json' | ||||
| import { MachinesListing } from 'components/MachineManagerProvider' | ||||
| 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 save = (args: any) => ipcRenderer.invoke('dialog.showSaveDialog', args) | ||||
| const openExternal = (url: any) => ipcRenderer.invoke('shell.openExternal', url) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user