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 253556d6c7
commit 4f5766d423
12 changed files with 2137 additions and 1962 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

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

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

View File

@ -1,55 +1,62 @@
import { test, expect, Page } from './zoo-test'
import path from 'path'
import * as fsp from 'fs/promises'
import {
getUtils,
executorInputPath,
} from './test-utils'
import { getUtils, executorInputPath } from './test-utils'
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates'
import { bracket } from 'lib/exampleKcl'
test.describe('Regression tests', () => {
// bugs we found that don't fit neatly into other categories
test('bad model has inline error #3251', async ({ context, page, homePage }) => { // because the model has `line([0,0]..` it is valid code, but the model is invalid
// regression test for https://github.com/KittyCAD/modeling-app/issues/3251
// Since the bad model also found as issue with the artifact graph, which in tern blocked the editor diognostics
const u = await getUtils(page)
await context.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch2 = startSketchOn("XY")
test('bad model has inline error #3251', async ({
context,
page,
homePage,
}) => {
// because the model has `line([0,0]..` it is valid code, but the model is invalid
// regression test for https://github.com/KittyCAD/modeling-app/issues/3251
// Since the bad model also found as issue with the artifact graph, which in tern blocked the editor diognostics
const u = await getUtils(page)
await context.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch2 = startSketchOn("XY")
sketch001 = startSketchAt([-0, -0])
|> line([0, 0], %)
|> line([-4.84, -5.29], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)`
)
)
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
// error in guter
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
// error text on hover
await page.hover('.cm-lint-marker-error')
// this is a cryptic error message, fact that all the lines are co-linear from the `line([0,0])` is the issue why
// the close doesn't work
// when https://github.com/KittyCAD/modeling-app/issues/3268 is closed
// this test will need updating
const crypticErrorText = `ApiError`
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
// error in guter
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
// error text on hover
await page.hover('.cm-lint-marker-error')
// this is a cryptic error message, fact that all the lines are co-linear from the `line([0,0])` is the issue why
// the close doesn't work
// when https://github.com/KittyCAD/modeling-app/issues/3268 is closed
// this test will need updating
const crypticErrorText = `ApiError`
await expect(page.getByText(crypticErrorText).first()).toBeVisible() })
test('user should not have to press down twice in cmdbar', async ({ page, homePage }) => { // because the model has `line([0,0]..` it is valid code, but the model is invalid
// regression test for https://github.com/KittyCAD/modeling-app/issues/3251
// Since the bad model also found as issue with the artifact graph, which in tern blocked the editor diognostics
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('XY')
test('user should not have to press down twice in cmdbar', async ({
page,
homePage,
}) => {
// because the model has `line([0,0]..` it is valid code, but the model is invalid
// regression test for https://github.com/KittyCAD/modeling-app/issues/3251
// Since the bad model also found as issue with the artifact graph, which in tern blocked the editor diognostics
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('XY')
|> startProfileAt([82.33, 238.21], %)
|> angledLine([0, 288.63], %, $rectangleSegmentA001)
|> angledLine([
@ -64,114 +71,121 @@ test.describe('Regression tests', () => {
|> close(%)
extrude001 = extrude(50, sketch001)
`
)
)
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await test.step('Check arrow down works', async () => {
await page.getByTestId('command-bar-open-button').hover()
await page.getByTestId('command-bar-open-button').click()
const floppy = page.getByRole('option', {
name: 'floppy disk arrow Export',
})
await floppy.click()
// press arrow down key twice
await page.keyboard.press('ArrowDown')
await page.waitForTimeout(100)
await page.keyboard.press('ArrowDown')
// STL is the third option, which makes sense for two arrow downs
await expect(page.locator('[data-headlessui-state="active"]')).toHaveText(
'STL'
)
await page.keyboard.press('Escape')
await page.waitForTimeout(200)
await page.keyboard.press('Escape')
await page.waitForTimeout(200)
})
await test.step('Check arrow up works', async () => {
// theme in test is dark, which is the second option, which means we can test arrow up
await page.getByTestId('command-bar-open-button').click()
await page.getByText('The overall appearance of the').click()
await page.keyboard.press('ArrowUp')
await page.waitForTimeout(100)
await expect(page.locator('[data-headlessui-state="active"]')).toHaveText(
'light'
)
})
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await test.step('Check arrow down works', async () => {
await page.getByTestId('command-bar-open-button').hover()
await page.getByTestId('command-bar-open-button').click()
const floppy = page
.getByRole('option', { name: 'floppy disk arrow Export' })
await floppy.click()
// press arrow down key twice
await page.keyboard.press('ArrowDown')
await page.waitForTimeout(100)
await page.keyboard.press('ArrowDown')
// STL is the third option, which makes sense for two arrow downs
await expect(page.locator('[data-headlessui-state="active"]')).toHaveText(
'STL'
)
await page.keyboard.press('Escape')
await page.waitForTimeout(200)
await page.keyboard.press('Escape')
await page.waitForTimeout(200)
})
await test.step('Check arrow up works', async () => {
// theme in test is dark, which is the second option, which means we can test arrow up
await page.getByTestId('command-bar-open-button').click()
await page.getByText('The overall appearance of the').click()
await page.keyboard.press('ArrowUp')
await page.waitForTimeout(100)
await expect(page.locator('[data-headlessui-state="active"]')).toHaveText(
'light'
)
}) })
test('executes on load', async ({ page, homePage }) => { const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('-XZ')
test('executes on load', async ({ page, homePage }) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('-XZ')
|> startProfileAt([-6.95, 4.98], %)
|> line([25.1, 0.41], %)
|> line([0.73, -14.93], %)
|> line([-23.44, 0.52], %)`
)
)
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
// expand variables section
const variablesTabButton = page.getByTestId('variables-pane-button')
await variablesTabButton.click()
// can find sketch001 in the variables summary (pretty-json-container, makes sure we're not looking in the code editor)
// sketch001 only shows up in the variables summary if it's been executed
await page.waitForFunction(() => {
const variablesElement = document.querySelector(
'.pretty-json-container'
) as HTMLDivElement
return variablesElement.innerHTML.includes('sketch001')
})
await expect(
page.locator('.pretty-json-container >> text=sketch001')
).toBeVisible()
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
test('re-executes', async ({ page, homePage }) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem('persistCode', `myVar = 5`)
})
await page.setBodyDimensions({ width: 1000, height: 500 })
// expand variables section
const variablesTabButton = page.getByTestId('variables-pane-button')
await variablesTabButton.click()
await homePage.goToModelingScene()
await u.waitForPageLoad()
// can find sketch001 in the variables summary (pretty-json-container, makes sure we're not looking in the code editor)
// sketch001 only shows up in the variables summary if it's been executed
await page.waitForFunction(() => {
const variablesElement = document.querySelector(
'.pretty-json-container'
) as HTMLDivElement
return variablesElement.innerHTML.includes('sketch001')
const variablesTabButton = page.getByTestId('variables-pane-button')
await variablesTabButton.click()
// expect to see "myVar:5"
await expect(
page.locator('.pretty-json-container >> text=myVar:5')
).toBeVisible()
// change 5 to 67
await page.locator('#code-mirror-override').getByText('myVar').click()
await page.keyboard.press('End')
await page.keyboard.press('Backspace')
await page.keyboard.type('67')
await expect(
page.locator('.pretty-json-container >> text=myVar:67')
).toBeVisible()
})
await expect(
page.locator('.pretty-json-container >> text=sketch001')
).toBeVisible() })
test('re-executes', async ({ page, homePage }) => { const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem('persistCode', `myVar = 5`)
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
const variablesTabButton = page.getByTestId('variables-pane-button')
await variablesTabButton.click()
// expect to see "myVar:5"
await expect(
page.locator('.pretty-json-container >> text=myVar:5')
).toBeVisible()
// change 5 to 67
await page.locator('#code-mirror-override').getByText('myVar').click()
await page.keyboard.press('End')
await page.keyboard.press('Backspace')
await page.keyboard.type('67')
await expect(
page.locator('.pretty-json-container >> text=myVar:67')
).toBeVisible() })
test('ProgramMemory can be serialised', async ({ page, homePage }) => { const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`part = startSketchOn('XY')
test('ProgramMemory can be serialised', async ({ page, homePage }) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`part = startSketchOn('XY')
|> startProfileAt([0, 0], %)
|> line([0, 1], %)
|> line([1, 0], %)
@ -183,51 +197,61 @@ extrude001 = extrude(50, sketch001)
repetitions: 3,
distance: 6
}, %)`
)
})
await page.setBodyDimensions({ width: 1000, height: 500 })
const messages: string[] = []
// Listen for all console events and push the message text to an array
page.on('console', (message) => messages.push(message.text()))
await homePage.goToModelingScene()
await u.waitForPageLoad()
// wait for execution done
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
const forbiddenMessages = ['cannot serialize tagged newtype variant']
forbiddenMessages.forEach((forbiddenMessage) => {
messages.forEach((message) => {
expect(message).not.toContain(forbiddenMessage)
)
})
}) })
await page.setBodyDimensions({ width: 1000, height: 500 })
const messages: string[] = []
// Listen for all console events and push the message text to an array
page.on('console', (message) => messages.push(message.text()))
await homePage.goToModelingScene()
await u.waitForPageLoad()
// wait for execution done
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
const forbiddenMessages = ['cannot serialize tagged newtype variant']
forbiddenMessages.forEach((forbiddenMessage) => {
messages.forEach((message) => {
expect(message).not.toContain(forbiddenMessage)
})
})
})
// Not relevant to us anymore, or at least for the time being.
test.skip('ensure the Zoo logo is not a link in browser app', async ({ page, homePage }) => { const u = await getUtils(page)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
test.skip('ensure the Zoo logo is not a link in browser app', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
const zooLogo = page.locator('[data-testid="app-logo"]')
// Make sure it's not a link
await expect(zooLogo).not.toHaveAttribute('href') })
const zooLogo = page.locator('[data-testid="app-logo"]')
// Make sure it's not a link
await expect(zooLogo).not.toHaveAttribute('href')
})
test('Position _ Is Out Of Range... regression test', { tag: ['@skipWin'] }, async ({ context, page, homePage }) => { // SKip on windows, its being weird.
test.skip(
process.platform === 'win32',
'This test is being weird on windows'
)
test(
'Position _ Is Out Of Range... regression test',
{ tag: ['@skipWin'] },
async ({ context, page, homePage }) => {
// SKip on windows, its being weird.
test.skip(
process.platform === 'win32',
'This test is being weird on windows'
)
const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setBodyDimensions({ width: 1200, height: 500 })
await context.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`exampleSketch = startSketchOn("XZ")
const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setBodyDimensions({ width: 1200, height: 500 })
await context.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`exampleSketch = startSketchOn("XZ")
|> startProfileAt([0, 0], %)
|> angledLine({ angle: 50, length: 45 }, %)
|> yLineTo(0, %)
@ -236,55 +260,54 @@ extrude001 = extrude(50, sketch001)
example = extrude(5, exampleSketch)
shell({ faces: ['end'], thickness: 0.25 }, exampleSketch)`
)
})
)
})
await expect(async () => {
await expect(async () => {
await homePage.goToModelingScene()
await u.waitForPageLoad()
await homePage.goToModelingScene()
await u.waitForPageLoad()
// error in guter
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
timeout: 1_000,
})
await page.waitForTimeout(200)
// expect it still to be there (sometimes it just clears for a bit?)
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
timeout: 1_000,
})
}).toPass({ timeout: 40_000, intervals: [1_000] })
// error in guter
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
timeout: 1_000,
})
await page.waitForTimeout(200)
// expect it still to be there (sometimes it just clears for a bit?)
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
timeout: 1_000,
})
}).toPass({ timeout: 40_000, intervals: [1_000] })
// error text on hover
await page.hover('.cm-lint-marker-error')
await expect(page.getByText('Unexpected token: |').first()).toBeVisible()
// error text on hover
await page.hover('.cm-lint-marker-error')
await expect(page.getByText('Unexpected token: |').first()).toBeVisible()
// Okay execution finished, let's start editing text below the error.
await u.codeLocator.click()
// Go to the end of the editor
// This bug happens when there is a diagnostic in the editor and you try to
// edit text below it.
// Or delete a huge chunk of text and then try to edit below it.
await page.keyboard.press('End')
await page.keyboard.down('Shift')
await page.keyboard.press('ArrowUp')
await page.keyboard.press('ArrowUp')
await page.keyboard.press('ArrowUp')
await page.keyboard.press('ArrowUp')
await page.keyboard.press('ArrowUp')
await page.keyboard.press('End')
await page.keyboard.up('Shift')
await page.keyboard.press('Backspace')
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// Okay execution finished, let's start editing text below the error.
await u.codeLocator.click()
// Go to the end of the editor
// This bug happens when there is a diagnostic in the editor and you try to
// edit text below it.
// Or delete a huge chunk of text and then try to edit below it.
await page.keyboard.press('End')
await page.keyboard.down('Shift')
await page.keyboard.press('ArrowUp')
await page.keyboard.press('ArrowUp')
await page.keyboard.press('ArrowUp')
await page.keyboard.press('ArrowUp')
await page.keyboard.press('ArrowUp')
await page.keyboard.press('End')
await page.keyboard.up('Shift')
await page.keyboard.press('Backspace')
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
await page.keyboard.press('Enter')
await page.keyboard.press('Enter')
await page.keyboard.type('thing: "blah"', { delay: 100 })
await page.keyboard.press('Enter')
await page.keyboard.press('ArrowLeft')
await page.keyboard.press('Enter')
await page.keyboard.press('Enter')
await page.keyboard.type('thing: "blah"', { delay: 100 })
await page.keyboard.press('Enter')
await page.keyboard.press('ArrowLeft')
await expect(page.locator('.cm-content'))
.toContainText(`exampleSketch = startSketchOn("XZ")
await expect(page.locator('.cm-content'))
.toContainText(`exampleSketch = startSketchOn("XZ")
|> startProfileAt([0, 0], %)
|> angledLine({ angle: 50, length: 45 }, %)
|> yLineTo(0, %)
@ -292,128 +315,27 @@ extrude001 = extrude(50, sketch001)
thing: "blah"`)
await expect(page.locator('.cm-lint-marker-error')).toBeVisible() })
test('when engine fails export we handle the failure and alert the user', async ({ page, homePage }) => { const u = await getUtils(page)
await page.addInitScript(
async ({ code }) => {
localStorage.setItem('persistCode', code)
;(window as any).playwrightSkipFilePicker = true
},
{ code: TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR }
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
}
)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
// wait for execution done
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
// expect zero errors in guter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// export the model
const exportButton = page.getByTestId('export-pane-button')
await expect(exportButton).toBeVisible()
// Click the export button
await exportButton.click()
// Click the stl.
const stlOption = page.getByText('glTF')
await expect(stlOption).toBeVisible()
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.keyboard.press('Enter')
// Find the toast.
// Look out for the toast message
const exportingToastMessage = page.getByText(`Exporting...`)
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
await expect(engineErrorToastMessage).toBeVisible()
// Make sure the exporting toast is gone
await expect(exportingToastMessage).not.toBeVisible()
// Click the code editor
await page.locator('.cm-content').click()
await page.waitForTimeout(2000)
// Expect the toast to be gone
await expect(errorToastMessage).not.toBeVisible()
await expect(engineErrorToastMessage).not.toBeVisible()
// Now add in code that works.
await page.locator('.cm-content').fill(bracket)
await page.keyboard.press('End')
await page.keyboard.press('Enter')
// wait for execution done
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
// Now try exporting
// Click the export button
await exportButton.click()
// Click the stl.
await expect(stlOption).toBeVisible()
await page.keyboard.press('Enter')
// Click the checkbox
await expect(submitButton).toBeVisible()
await page.keyboard.press('Enter')
// Find the toast.
// Look out for the toast message
await expect(exportingToastMessage).toBeVisible()
// Expect it to succeed.
await expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 })
await expect(errorToastMessage).not.toBeVisible()
await expect(engineErrorToastMessage).not.toBeVisible()
const successToastMessage = page.getByText(`Exported successfully`)
await expect(successToastMessage).toBeVisible() })
test('ensure you can not export while an export is already going', { tag: ['@skipLinux', '@skipWin'] }, async ({ page, homePage }) => { // This is being weird on ubuntu and windows.
test.skip(
// eslint-disable-next-line jest/valid-title
process.platform === 'linux' || process.platform === 'win32',
'This test is being weird on ubuntu'
)
const u = await getUtils(page)
await test.step('Set up the code and durations', async () => {
test('when engine fails export we handle the failure and alert the user', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.addInitScript(
async ({ code }) => {
localStorage.setItem('persistCode', code)
;(window as any).playwrightSkipFilePicker = true
},
{
code: bracket,
}
{ code: TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR }
)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await u.waitForPageLoad()
// wait for execution done
await u.openDebugPanel()
@ -422,61 +344,175 @@ extrude001 = extrude(50, sketch001)
// expect zero errors in guter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
})
const errorToastMessage = page.getByText(`Error while exporting`)
const exportingToastMessage = page.getByText(`Exporting...`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
const successToastMessage = page.getByText(`Exported successfully`)
// export the model
const exportButton = page.getByTestId('export-pane-button')
await expect(exportButton).toBeVisible()
await test.step('Blocked second export', async () => {
await clickExportButton(page)
// Click the export button
await exportButton.click()
await expect(exportingToastMessage).toBeVisible()
// Click the stl.
const stlOption = page.getByText('glTF')
await expect(stlOption).toBeVisible()
await clickExportButton(page)
await page.keyboard.press('Enter')
await test.step('The second export is blocked', async () => {
// Find the toast.
// Look out for the toast message
await Promise.all([
expect(exportingToastMessage.first()).toBeVisible(),
expect(alreadyExportingToastMessage).toBeVisible(),
])
})
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await test.step('The first export still succeeds', async () => {
await Promise.all([
expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 }),
expect(errorToastMessage).not.toBeVisible(),
expect(engineErrorToastMessage).not.toBeVisible(),
expect(successToastMessage).toBeVisible({ timeout: 15_000 }),
expect(alreadyExportingToastMessage).not.toBeVisible({
timeout: 15_000,
}),
])
})
})
await page.keyboard.press('Enter')
await test.step('Successful, unblocked export', async () => {
// Try exporting again.
await clickExportButton(page)
// Find the toast.
// Look out for the toast message
const exportingToastMessage = page.getByText(`Exporting...`)
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
await expect(engineErrorToastMessage).toBeVisible()
// Make sure the exporting toast is gone
await expect(exportingToastMessage).not.toBeVisible()
// Click the code editor
await page.locator('.cm-content').click()
await page.waitForTimeout(2000)
// Expect the toast to be gone
await expect(errorToastMessage).not.toBeVisible()
await expect(engineErrorToastMessage).not.toBeVisible()
// Now add in code that works.
await page.locator('.cm-content').fill(bracket)
await page.keyboard.press('End')
await page.keyboard.press('Enter')
// wait for execution done
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
// Now try exporting
// Click the export button
await exportButton.click()
// Click the stl.
await expect(stlOption).toBeVisible()
await page.keyboard.press('Enter')
// Click the checkbox
await expect(submitButton).toBeVisible()
await page.keyboard.press('Enter')
// Find the toast.
// Look out for the toast message
await expect(exportingToastMessage).toBeVisible()
// Expect it to succeed.
await Promise.all([
expect(exportingToastMessage).not.toBeVisible(),
expect(errorToastMessage).not.toBeVisible(),
expect(engineErrorToastMessage).not.toBeVisible(),
expect(alreadyExportingToastMessage).not.toBeVisible(),
])
await expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 })
await expect(errorToastMessage).not.toBeVisible()
await expect(engineErrorToastMessage).not.toBeVisible()
const successToastMessage = page.getByText(`Exported successfully`)
await expect(successToastMessage).toBeVisible()
}) })
})
test(
'ensure you can not export while an export is already going',
{ tag: ['@skipLinux', '@skipWin'] },
async ({ page, homePage }) => {
// This is being weird on ubuntu and windows.
test.skip(
// eslint-disable-next-line jest/valid-title
process.platform === 'linux' || process.platform === 'win32',
'This test is being weird on ubuntu'
)
const u = await getUtils(page)
await test.step('Set up the code and durations', async () => {
await page.addInitScript(
async ({ code }) => {
localStorage.setItem('persistCode', code)
;(window as any).playwrightSkipFilePicker = true
},
{
code: bracket,
}
)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
// wait for execution done
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
// expect zero errors in guter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
})
const errorToastMessage = page.getByText(`Error while exporting`)
const exportingToastMessage = page.getByText(`Exporting...`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
const successToastMessage = page.getByText(`Exported successfully`)
await test.step('Blocked second export', async () => {
await clickExportButton(page)
await expect(exportingToastMessage).toBeVisible()
await clickExportButton(page)
await test.step('The second export is blocked', async () => {
// Find the toast.
// Look out for the toast message
await Promise.all([
expect(exportingToastMessage.first()).toBeVisible(),
expect(alreadyExportingToastMessage).toBeVisible(),
])
})
await test.step('The first export still succeeds', async () => {
await Promise.all([
expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 }),
expect(errorToastMessage).not.toBeVisible(),
expect(engineErrorToastMessage).not.toBeVisible(),
expect(successToastMessage).toBeVisible({ timeout: 15_000 }),
expect(alreadyExportingToastMessage).not.toBeVisible({
timeout: 15_000,
}),
])
})
})
await test.step('Successful, unblocked export', async () => {
// Try exporting again.
await clickExportButton(page)
// Find the toast.
// Look out for the toast message
await expect(exportingToastMessage).toBeVisible()
// Expect it to succeed.
await Promise.all([
expect(exportingToastMessage).not.toBeVisible(),
expect(errorToastMessage).not.toBeVisible(),
expect(engineErrorToastMessage).not.toBeVisible(),
expect(alreadyExportingToastMessage).not.toBeVisible(),
])
await expect(successToastMessage).toBeVisible()
})
}
)
test(
`Network health indicator only appears in modeling view`,
@ -520,57 +556,62 @@ extrude001 = extrude(50, sketch001)
}
)
test(`View gizmo stays visible even when zoomed out all the way`, async ({ page, homePage }) => { const u = await getUtils(page)
test(`View gizmo stays visible even when zoomed out all the way`, async ({
page,
homePage,
}) => {
const u = await getUtils(page)
// Constants and locators
const planeColor: [number, number, number] = [170, 220, 170]
const bgColor: [number, number, number] = [27, 27, 27]
const middlePixelIsColor = async (color: [number, number, number]) => {
return u.getGreatestPixDiff({ x: 600, y: 250 }, color)
}
const gizmo = page.locator('[aria-label*=gizmo]')
await test.step(`Load an empty file`, async () => {
await page.addInitScript(async () => {
localStorage.setItem('persistCode', '')
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await u.closeKclCodePanel()
})
await test.step(`Zoom out until you can't see the default planes`, async () => {
await expect
.poll(async () => middlePixelIsColor(planeColor), {
timeout: 5000,
message: 'Plane color is visible',
})
.toBeLessThan(15)
let maxZoomOuts = 10
let middlePixelIsBackgroundColor =
(await middlePixelIsColor(bgColor)) < 10
while (!middlePixelIsBackgroundColor && maxZoomOuts > 0) {
await page.keyboard.down('Control')
await page.mouse.move(600, 460)
await page.mouse.down({ button: 'right' })
await page.mouse.move(600, 50, { steps: 20 })
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Control')
await page.waitForTimeout(100)
maxZoomOuts--
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 10
// Constants and locators
const planeColor: [number, number, number] = [170, 220, 170]
const bgColor: [number, number, number] = [27, 27, 27]
const middlePixelIsColor = async (color: [number, number, number]) => {
return u.getGreatestPixDiff({ x: 600, y: 250 }, color)
}
const gizmo = page.locator('[aria-label*=gizmo]')
expect(middlePixelIsBackgroundColor, {
message: 'We no longer the default planes',
}).toBeTruthy()
await test.step(`Load an empty file`, async () => {
await page.addInitScript(async () => {
localStorage.setItem('persistCode', '')
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await u.closeKclCodePanel()
})
await test.step(`Zoom out until you can't see the default planes`, async () => {
await expect
.poll(async () => middlePixelIsColor(planeColor), {
timeout: 5000,
message: 'Plane color is visible',
})
.toBeLessThan(15)
let maxZoomOuts = 10
let middlePixelIsBackgroundColor =
(await middlePixelIsColor(bgColor)) < 10
while (!middlePixelIsBackgroundColor && maxZoomOuts > 0) {
await page.keyboard.down('Control')
await page.mouse.move(600, 460)
await page.mouse.down({ button: 'right' })
await page.mouse.move(600, 50, { steps: 20 })
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Control')
await page.waitForTimeout(100)
maxZoomOuts--
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 10
}
expect(middlePixelIsBackgroundColor, {
message: 'We no longer the default planes',
}).toBeTruthy()
})
await test.step(`Check that the gizmo is still visible`, async () => {
await expect(gizmo).toBeVisible()
})
})
await test.step(`Check that the gizmo is still visible`, async () => {
await expect(gizmo).toBeVisible()
}) })
})
async function clickExportButton(page: Page) {

View File

@ -3,190 +3,200 @@ 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 })
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()
await homePage.goToModelingScene()
const networkToggle = page.getByTestId('network-toggle')
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 })
// 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 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()
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')
// (First check) Expect the network to be up
await expect(networkToggle).toContainText('Connected')
// Click the network widget
await networkWidget.click()
// Click the network widget
await networkWidget.click()
// Check the modal opened.
await expect(networkPopover).toBeVisible()
// Check the modal opened.
await expect(networkPopover).toBeVisible()
// Click off the modal.
await page.mouse.click(100, 100)
await expect(networkPopover).not.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,
// 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')
})
// Expect the network to be down
await expect(networkToggle).toContainText('Problem')
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')
// Click the network widget
await networkWidget.click()
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
// Check the modal opened.
await expect(networkPopover).toBeVisible()
await homePage.goToModelingScene()
await u.waitForPageLoad()
// Click off the modal.
await page.mouse.click(0, 0)
await expect(networkPopover).not.toBeVisible()
await u.openDebugPanel()
// click on "Start Sketch" button
await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(100)
// 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,
})
// select a plane
await page.mouse.click(700, 200)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled({ timeout: 15000 })
await expect(page.locator('.cm-content')).toHaveText(
`sketch001 = startSketchOn('XZ')`
)
await u.closeDebugPanel()
// (Second check) expect the network to be up
await expect(networkToggle).toContainText('Connected') })
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
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')
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.waitForTimeout(100)
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
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 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')
// 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,
})
// 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')
// 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()
// 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,
})
// 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 })
// 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()
// 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)
// Click off the code pane.
await page.mouse.click(100, 100)
// select a line
await page.getByText(`startProfileAt(${commonPoints.startAt}, %)`).click()
// 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)
// 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()
// Click the line tool
await page.getByRole('button', { name: 'line Line', exact: true }).click()
await page.waitForTimeout(150)
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')
// 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 page.waitForTimeout(100)
await page.mouse.click(startXPx, 500 - PUR * 20)
await expect.poll(u.normalisedEditorCode)
.toBe(`sketch001 = startSketchOn('XZ')
await expect.poll(u.normalisedEditorCode)
.toBe(`sketch001 = startSketchOn('XZ')
|> startProfileAt([12.34, -12.34], %)
|> xLine(12.34, %)
|> line([-12.34, 12.34], %)
@ -194,19 +204,20 @@ test.describe('Test network and connection issues', () => {
`)
// 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')
// 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() })
// 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,29 +1,117 @@
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 })
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.openAndClearDebugPanel()
await u.closeKclCodePanel()
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 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',
@ -47,420 +135,343 @@ test.describe('Testing Camera Movement', () => {
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(100)
// const yo = page.getByTestId('cam-x-position').inputValue()
await page.waitForTimeout(200)
// zoom
await u.doAndWaitForImageDiff(async () => {
await mouseActions()
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.openAndClearDebugPanel()
await u.openDebugPanel()
await page.waitForTimeout(300)
await u.clearCommandLogs()
await u.closeDebugPanel()
await page.waitForTimeout(100)
}, 300)
// zoom with scroll
await u.openAndClearDebugPanel()
await page.getByTestId('cam-x-position').isVisible()
// 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)
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 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(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)
let y = 350,
x = 948
await u.clearCommandLogs()
await u.closeDebugPanel()
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)
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(200)
// click the line button
await page.getByRole('button', { name: 'line Line', exact: true }).click()
// 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')
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 u.openDebugPanel()
await page.waitForTimeout(300)
await u.clearCommandLogs()
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
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({
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 expect(page.getByTestId('hover-highlight')).not.toBeVisible()
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 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 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,
})
// click exit sketch
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(400)
await hoverOverNothing()
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,
})
// click exit sketch
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(400)
await hoverOverNothing()
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,
})
// hover over vertical line
await page.mouse.move(x, 325)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(x, 325)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
// 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 hoverOverNothing()
await expect(
page.getByRole('button', { name: 'Edit Sketch' })
).toBeVisible()
await hoverOverNothing()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
// 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 page.waitForTimeout(400)
await expect(
page.getByRole('button', { name: 'Edit Sketch' })
).toBeVisible()
await hoverOverNothing()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
x = 975
y = 468
await page.waitForTimeout(400)
await page.waitForTimeout(100)
await page.mouse.move(x, 419, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
x = 975
y = 468
await hoverOverNothing()
await page.waitForTimeout(100)
await page.mouse.move(x, 419, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(200)
await hoverOverNothing()
await hoverOverNothing()
await page.waitForTimeout(200)
await page.getByRole('button', { name: 'Exit Sketch' }).click()
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.waitForTimeout(200)
await hoverOverNothing()
await page.mouse.move(x, 419)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
}) })
test(`Zoom by scroll should not fire while orbiting`, async ({ page, homePage }) => { /**
* 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 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),
})
})
const orbitMouseStepOne = midPoint(orbitMouseStart, orbitMouseEnd)
const expectedStartCamZPosition = 64.0
const expectedZoomCamZPosition = 32.0
const expectedOrbitCamZPosition = 64.0
// Helper functions
async function resetCamera() {
await test.step(`Reset camera`, async () => {
await test.step(`Test setup`, async () => {
await homePage.goToModelingScene()
await u.closeKclCodePanel()
// This test requires the mouse controls to be set to Solidworks
await u.openDebugPanel()
await u.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 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)
})
})
await test.step(`Verify orbit`, async () => {
await expect
.poll(getCameraZValue, {
message: 'Camera should be at expected position after orbiting',
// 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,
})
.toEqual(expectedOrbitCamZPosition)
await page.mouse.up({ button: 'middle' })
})
} })
await callback()
await page.mouse.move(orbitMouseEnd.x, orbitMouseEnd.y, {
steps: 3,
})
})
await test.step(`Verify orbit`, async () => {
await expect
.poll(getCameraZValue, {
message: 'Camera should be at expected position after orbiting',
})
.toEqual(expectedOrbitCamZPosition)
await page.mouse.up({ button: 'middle' })
})
}
})
})

File diff suppressed because it is too large Load Diff

View File

@ -52,15 +52,105 @@ test.describe('Testing Gizmo', () => {
} of cases) {
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()
@ -94,13 +184,20 @@ 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',
@ -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)