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

This commit is contained in:
49lf
2024-11-29 14:12:19 -05:00
parent 9a3075533b
commit 7a448760e7
12 changed files with 2076 additions and 1959 deletions

View File

@ -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) => {

View File

@ -130,9 +130,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')
@ -278,7 +276,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, '')

View File

@ -7,27 +7,42 @@ import path from 'node:path'
// test file is for testing point an click code gen functionality that's not sketch mode related
test(
'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 ({

View File

@ -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()
}
)
@ -477,7 +473,6 @@ test(
await page.hover('.cm-lint-marker-error')
const crypticErrorText = `Expected a tag declarator`
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
}
)
@ -569,7 +564,6 @@ test.describe('Can export from electron app', () => {
// clean up exported file
await fsp.rm(filepath)
})
}
)
}
@ -577,7 +571,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(
@ -770,7 +764,6 @@ test(
// expect the name not to have changed
await expect(page.getByText('bracket')).toBeVisible()
})
}
)
@ -799,7 +792,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()
}
)
@ -862,7 +854,6 @@ test.describe(`Project management commands`, () => {
await expect(projectHomeLink.first()).toBeVisible()
await expect(projectHomeLink.first()).toContainText(projectRenamedName)
})
}
)
@ -915,7 +906,6 @@ test.describe(`Project management commands`, () => {
await test.step(`Check the project was deleted and we navigated home`, async () => {
await expect(noProjectsMessage).toBeVisible()
})
}
)
test(
@ -971,7 +961,6 @@ test.describe(`Project management commands`, () => {
).toBeVisible()
await expect(projectHomeLink).not.toHaveText(projectName)
})
}
)
test(
@ -1021,7 +1010,6 @@ test.describe(`Project management commands`, () => {
await expect(projectHomeLink).not.toBeVisible()
await expect(noProjectsMessage).toBeVisible()
})
}
)
})
@ -1067,7 +1055,6 @@ test(
await expect(u.codeLocator).toContainText(
'A mounting bracket for the Focusrite Scarlett Solo audio interface'
)
}
)
@ -1123,10 +1110,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()
}
}
)
@ -1205,7 +1193,6 @@ test.fixme(
page.getByTestId('project-link').filter({ hasText: 'project-000' })
).toBeVisible()
})
}
)
@ -1243,7 +1230,6 @@ test(
await expect(u.codeLocator).toContainText('routerDiameter')
await expect(u.codeLocator).toContainText('templateGap')
await expect(u.codeLocator).toContainText('minClampingDistance')
}
)
@ -1351,7 +1337,6 @@ test(
)
}
})
}
)
@ -1540,7 +1525,6 @@ test(
await expect(page.getByText('router-template-slate')).toBeVisible()
await expect(page.getByText('New Project')).toBeVisible()
})
}
)
@ -1600,9 +1584,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()
@ -1620,7 +1604,6 @@ test(
await page.getByTestId('project-directory-settings-link').click()
const handleFile = electronApp.evaluate(
async ({ dialog }, filePaths) => {
dialog.showOpenDialog = () =>
@ -1698,7 +1681,6 @@ test(
await expect(page.getByText(name)).toBeVisible()
}
})
}
)
@ -1804,7 +1786,6 @@ test(
false
)
})
}
)
@ -1863,7 +1844,6 @@ test(
expect(selectedText.length).toBe(0)
await expect(u.codeLocator).toHaveText('')
})
}
)
@ -1883,7 +1863,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 () => {
@ -1892,7 +1871,6 @@ test(
page.on('console', console.log)
await expect(page.getByTestId('app-theme')).toHaveValue('light')
})
}
)
@ -1934,6 +1912,5 @@ test.fixme(
await expect(projectLink).toContainText(projectNames[index])
}
})
}
)

File diff suppressed because it is too large Load Diff

View File

@ -3,210 +3,221 @@ import { test, expect } from './zoo-test'
import { commonPoints, getUtils } from './test-utils'
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()
})
})

View File

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

View File

@ -1,30 +1,118 @@
import { test, expect } from './zoo-test'
import { 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,418 +134,283 @@ 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',
})
await callback()
await page.mouse.move(orbitMouseEnd.x, orbitMouseEnd.y, {

File diff suppressed because it is too large Load Diff

View File

@ -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 })

View File

@ -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,

View File

@ -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)