Part of #4600. PR: https://github.com/KittyCAD/modeling-app/pull/4826 # Changes to KCL stdlib - `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)` - `close(sketch, tag?)` is now `close(@sketch, tag?)` - `extrude(length, sketch)` is now `extrude(@sketch, length)` Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this: ``` sketch = startSketchAt([0, 0]) line(sketch, end = [3, 3], tag = $hi) ``` Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as ``` sketch = startSketchAt([0, 0]) |> line(end = [3, 3], tag = $hi) ``` Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are: ``` line\(([^=]*), %\) line(end = $1) line\((.*), %, (.*)\) line(end = $1, tag = $2) lineTo\((.*), %\) line(endAbsolute = $1) lineTo\((.*), %, (.*)\) line(endAbsolute = $1, tag = $2) extrude\((.*), %\) extrude(length = $1) extrude\(([^=]*), ([a-zA-Z0-9]+)\) extrude($2, length = $1) close\(%, (.*)\) close(tag = $1) ``` # Selected notes from commits before I squash them all * Fix test 'yRelative to horizontal distance' Fixes: - Make a lineTo helper - Fix pathToNode to go through the labeled arg .arg property * Fix test by changing lookups into transformMap Parts of the code assumed that `line` is always a relative call. But actually now it might be absolute, if it's got an `endAbsolute` parameter. So, change whether to look up `line` or `lineTo` and the relevant absolute or relative line types based on that parameter. * Stop asserting on exact source ranges When I changed line to kwargs, all the source ranges we assert on became slightly different. I find these assertions to be very very low value. So I'm removing them. * Fix more tests: getConstraintType calls weren't checking if the 'line' fn was absolute or relative. * Fixed another queryAst test There were 2 problems: - Test was looking for the old style of `line` call to choose an offset for pathToNode - Test assumed that the `tag` param was always the third one, but in a kwarg call, you have to look it up by label * Fix test: traverse was not handling CallExpressionKw * Fix another test, addTagKw addTag helper was not aware of kw args. * Convert close from positional to kwargs If the close() call has 0 args, or a single unlabeled arg, the parser interprets it as a CallExpression (positional) not a CallExpressionKw. But then if a codemod wants to add a tag to it, it tries adding a kwarg called 'tag', which fails because the CallExpression doesn't need kwargs inserted into it. The fix is: change the node from CallExpression to CallExpressionKw, and update getNodeFromPath to take a 'replacement' arg, so we can replace the old node with the new node in the AST. * Fix the last test Test was looking for `lineTo` as a substring of the input KCL program. But there's no more lineTo function, so I changed it to look for line() with an endAbsolute arg, which is the new equivalent. Also changed the getConstraintInfo code to look up the lineTo if using line with endAbsolute. * Fix many bad regex find-replaces I wrote a regex find-and-replace which converted `line` calls from positional to keyword calls. But it was accidentally applied to more places than it should be, for example, angledLine, xLine and yLine calls. Fixes this. * Fixes test 'Basic sketch › code pane closed at start' Problem was, the getNodeFromPath call might not actually find a callExpressionKw, it might find a callExpression. So the `giveSketchFnCallTag` thought it was modifying a kwargs call, but it was actually modifying a positional call. This meant it tried to push a labeled argument in, rather than a normal arg, and a lot of other problems. Fixed by doing runtime typechecking. * Fix: Optional args given with wrong type were silently ignored Optional args don't have to be given. But if the user gives them, they should be the right type. Bug: if the KCL interpreter found an optional arg, which was given, but was the wrong type, it would ignore it and pretend the arg was never given at all. This was confusing for users. Fix: Now if you give an optional arg, but it's the wrong type, KCL will emit a type error just like it would for a mandatory argument. --------- Signed-off-by: Nick Cameron <nrc@ncameron.org> Co-authored-by: Nick Cameron <nrc@ncameron.org> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Frank Noirot <frank@kittycad.io> Co-authored-by: Kevin Nadro <kevin@zoo.dev> Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
515 lines
17 KiB
TypeScript
515 lines
17 KiB
TypeScript
import { test, expect } from './zoo-test'
|
|
import { EngineCommand } from 'lang/std/artifactGraph'
|
|
import { uuidv4 } from 'lib/utils'
|
|
import { getUtils } from './test-utils'
|
|
|
|
test.describe('Testing Camera Movement', () => {
|
|
test('Can move camera reliably', async ({ page, context, homePage }) => {
|
|
// TODO: fix this test on windows too after the electron migration
|
|
const winOrMac =
|
|
process.platform === 'win32' || process.platform === 'darwin'
|
|
// eslint-disable-next-line
|
|
test.skip(winOrMac, 'Skip on windows')
|
|
const u = await getUtils(page)
|
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
|
|
|
await homePage.goToModelingScene()
|
|
await u.waitForPageLoad()
|
|
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(),
|
|
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])
|
|
})
|
|
|
|
// TODO: fix after electron migration is merged
|
|
test.fixme(
|
|
'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
|
|
|
|
const u = await getUtils(page)
|
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
|
|
|
await homePage.goToModelingScene()
|
|
await u.waitForPageLoad()
|
|
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(end = [11.18, 0])`
|
|
// await expect(u.codeLocator).toHaveText(code)
|
|
await u.canvasLocator.click({ position: { x, y: 275 } })
|
|
code += `\n |> line(end = [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 page.waitForTimeout(200)
|
|
|
|
await hoverOverNothing()
|
|
await page.waitForTimeout(200)
|
|
// hover over vertical line
|
|
await u.canvasLocator.hover({ position: { x, y: 325 } })
|
|
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
|
timeout: 10_000,
|
|
})
|
|
|
|
await hoverOverNothing()
|
|
|
|
// click exit sketch
|
|
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
|
await page.waitForTimeout(400)
|
|
|
|
await hoverOverNothing()
|
|
await page.waitForTimeout(200)
|
|
// hover over horizontal line
|
|
await page.mouse.move(858, y, { steps: 5 })
|
|
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
|
timeout: 10_000,
|
|
})
|
|
|
|
await hoverOverNothing()
|
|
|
|
// hover over vertical line
|
|
await page.mouse.move(x, 325)
|
|
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
|
timeout: 10_000,
|
|
})
|
|
|
|
await hoverOverNothing()
|
|
|
|
// hover over vertical line
|
|
await page.mouse.move(857, y)
|
|
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
|
timeout: 10_000,
|
|
})
|
|
// now click it
|
|
await page.mouse.click(857, y)
|
|
|
|
await expect(
|
|
page.getByRole('button', { name: 'Edit Sketch' })
|
|
).toBeVisible()
|
|
await hoverOverNothing()
|
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
|
|
|
await page.waitForTimeout(400)
|
|
|
|
x = 975
|
|
y = 468
|
|
|
|
await page.waitForTimeout(100)
|
|
await page.mouse.move(x, 419, { steps: 5 })
|
|
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
|
timeout: 10_000,
|
|
})
|
|
|
|
await hoverOverNothing()
|
|
|
|
await page.mouse.move(855, y)
|
|
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
|
timeout: 10_000,
|
|
})
|
|
|
|
await hoverOverNothing()
|
|
|
|
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
|
await page.waitForTimeout(200)
|
|
|
|
await hoverOverNothing()
|
|
await page.waitForTimeout(200)
|
|
|
|
await page.mouse.move(x, 419)
|
|
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
|
timeout: 10_000,
|
|
})
|
|
|
|
await hoverOverNothing()
|
|
|
|
await page.mouse.move(855, y)
|
|
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
|
|
timeout: 10_000,
|
|
})
|
|
}
|
|
)
|
|
|
|
test(`Zoom by scroll should not fire while orbiting`, async ({
|
|
homePage,
|
|
page,
|
|
}) => {
|
|
// TODO: fix this test on windows after the electron migration
|
|
test.skip(process.platform === 'win32', 'Skip on windows')
|
|
/**
|
|
* 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.waitForPageLoad()
|
|
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 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')
|
|
})
|
|
|
|
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)
|
|
})
|
|
})
|
|
|
|
// 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' })
|
|
})
|
|
}
|
|
})
|
|
|
|
test('Right-click opens context menu when not dragged', async ({
|
|
homePage,
|
|
page,
|
|
}) => {
|
|
const u = await getUtils(page)
|
|
|
|
await homePage.goToModelingScene()
|
|
await u.waitForPageLoad()
|
|
|
|
await test.step(`The menu should not show if we drag the mouse`, async () => {
|
|
await page.mouse.move(900, 200)
|
|
await page.mouse.down({ button: 'right' })
|
|
await page.mouse.move(900, 300)
|
|
await page.mouse.up({ button: 'right' })
|
|
|
|
await expect(page.getByTestId('view-controls-menu')).not.toBeVisible()
|
|
})
|
|
|
|
await test.step(`The menu should show if we don't drag the mouse`, async () => {
|
|
await page.mouse.move(900, 200)
|
|
await page.mouse.down({ button: 'right' })
|
|
await page.mouse.up({ button: 'right' })
|
|
|
|
await expect(page.getByTestId('view-controls-menu')).toBeVisible()
|
|
})
|
|
})
|
|
})
|