* Resurrect this branch with an initial commit * Add telemetry to global default items * Add credit progress bar to status bar * Add selection info to status bar * Add help menu to "local" side * Rename statusBarItem utils * Delete LowerRightControls, now unused * fix lints * Update snapshots * Add test-id to network health indicator, which all E2E tests rely on * Update src/components/StatusBar/StatusBar.tsx Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com> * Fix a couple little issues with the e2e tests * Fix gizmo e2e tests (it moved) and network health test (it should not be on home page) * More tweaks to accomodate changes to network health indicator We made use of two test ID's to make Playwright aware of the state, one of which was on the icon. Now that we want to normalize usage of the status bar along a more limited API, that became a not possible. This just tweaks some test code that relied on that fact. * Fix lints * Update snapshots * Re-run CI * Update snapshots * Update snapshots * Test fixes, label logic tweaks * Update snapshots * Update snapshots * Fix up last few tests hopefully. Relative path syntax failed on windows * Relative paths are behaving badly on Windows, use the old code here * Update snapshots * Update snapshots * Tweak y-value to work on all platforms, ubuntu didn't like 438 * Fix tooltip and popover alignment on NetworkMachineIndicator * Remove dire warning comment * Update src/components/StatusBar/defaultStatusBarItems.tsx Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com> * @lee-at-zoo-corp feedback, pull hooks out of UI code * Re-run CI --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
974 lines
27 KiB
TypeScript
974 lines
27 KiB
TypeScript
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
|
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
|
import {
|
|
getUtils,
|
|
headerMasks,
|
|
lowerRightMasks,
|
|
settingsToToml,
|
|
} from '@e2e/playwright/test-utils'
|
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
|
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
|
|
|
|
test.beforeEach(async ({ page, context }) => {
|
|
// Make the user avatar image always 404
|
|
// so we see the fallback menu icon for all snapshot tests
|
|
await page.route('https://lh3.googleusercontent.com/**', async (route) => {
|
|
await route.fulfill({
|
|
status: 404,
|
|
contentType: 'text/plain',
|
|
body: 'Not Found!',
|
|
})
|
|
})
|
|
})
|
|
|
|
// Help engine-manager: tear shit down.
|
|
test.afterEach(async ({ page }) => {
|
|
await page.evaluate(() => {
|
|
window.engineCommandManager.tearDown()
|
|
})
|
|
})
|
|
|
|
test.setTimeout(60_000)
|
|
|
|
const extrudeDefaultPlane = async (
|
|
context: any,
|
|
page: any,
|
|
cmdBar: CmdBarFixture,
|
|
scene: SceneFixture,
|
|
plane: string
|
|
) => {
|
|
const code = `part001 = startSketchOn(${plane})
|
|
|> startProfile(at = [7.00, 4.40])
|
|
|> line(end = [6.60, -0.20])
|
|
|> line(end = [2.80, 5.00])
|
|
|> line(end = [-5.60, 4.40])
|
|
|> line(end = [-5.40, -3.80])
|
|
|> close()
|
|
|> extrude(length = 10.00)
|
|
`
|
|
|
|
// This probably does absolutely nothing based on my trip through here.
|
|
await page.addInitScript(async () => {
|
|
localStorage.setItem(
|
|
'SETTINGS_PERSIST_KEY',
|
|
settingsToToml({
|
|
settings: {
|
|
modeling: {
|
|
base_unit: 'in',
|
|
mouse_controls: 'zoo',
|
|
},
|
|
app: {
|
|
onboarding_status: 'dismissed',
|
|
show_debug_panel: true,
|
|
appearance: {
|
|
theme: 'dark',
|
|
},
|
|
},
|
|
project: {
|
|
default_project_name: 'untitled',
|
|
},
|
|
text_editor: {
|
|
text_wrapping: true,
|
|
},
|
|
},
|
|
})
|
|
)
|
|
})
|
|
|
|
await page.addInitScript(async (code: string) => {
|
|
localStorage.setItem('persistCode', code)
|
|
}, code)
|
|
|
|
const u = await getUtils(page)
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
await scene.settled(cmdBar)
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
await u.openKclCodePanel()
|
|
}
|
|
|
|
test.describe(
|
|
'extrude on default planes should be stable',
|
|
{ tag: '@snapshot' },
|
|
() => {
|
|
test('XY', async ({ page, context, cmdBar, scene }) => {
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, 'XY')
|
|
})
|
|
|
|
test('XZ', async ({ page, context, cmdBar, scene }) => {
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, 'XZ')
|
|
})
|
|
|
|
test('YZ', async ({ page, context, cmdBar, scene }) => {
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, 'YZ')
|
|
})
|
|
|
|
test('-XY', async ({ page, context, cmdBar, scene }) => {
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, '-XY')
|
|
})
|
|
|
|
test('-XZ', async ({ page, context, cmdBar, scene }) => {
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, '-XZ')
|
|
})
|
|
|
|
test('-YZ', async ({ page, context, cmdBar, scene }) => {
|
|
await extrudeDefaultPlane(context, page, cmdBar, scene, '-YZ')
|
|
})
|
|
}
|
|
)
|
|
|
|
test(
|
|
'Draft segments should look right',
|
|
{ tag: '@snapshot' },
|
|
async ({ page, scene, toolbar }) => {
|
|
const u = await getUtils(page)
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
const startXPx = 600
|
|
const [endOfTangentClk, endOfTangentMv] = scene.makeMouseHelpers(
|
|
startXPx + PUR * 30,
|
|
500 - PUR * 20,
|
|
{ steps: 10 }
|
|
)
|
|
const [threePointArcMidPointClk, threePointArcMidPointMv] =
|
|
scene.makeMouseHelpers(800, 250, { steps: 10 })
|
|
const [threePointArcEndPointClk, threePointArcEndPointMv] =
|
|
scene.makeMouseHelpers(750, 285, { steps: 10 })
|
|
const [arcCenterClk, arcCenterMv] = scene.makeMouseHelpers(750, 210, {
|
|
steps: 10,
|
|
})
|
|
const [arcEndClk, arcEndMv] = scene.makeMouseHelpers(750, 150, {
|
|
steps: 10,
|
|
})
|
|
|
|
// click on "Start Sketch" button
|
|
await u.doAndWaitForImageDiff(
|
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
|
200
|
|
)
|
|
|
|
// select a plane
|
|
await page.mouse.click(700, 200)
|
|
|
|
let code = `sketch001 = startSketchOn(XZ)`
|
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
|
|
|
await page.waitForTimeout(700) // TODO detect animation ending, or disable animation
|
|
|
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
|
code += `profile001 = startProfile(sketch001, at = [182.59, -246.32])`
|
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
|
await page.waitForTimeout(100)
|
|
|
|
await page.mouse.move(startXPx + PUR * 20, 500 - PUR * 10)
|
|
|
|
await page.waitForTimeout(500)
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
|
|
const lineEndClick = () =>
|
|
page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
|
await lineEndClick()
|
|
await page.waitForTimeout(500)
|
|
|
|
code += `
|
|
|> xLine(length = 184.3)`
|
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
|
|
|
await toolbar.selectTangentialArc()
|
|
|
|
// click on the end of the profile to continue it
|
|
await page.waitForTimeout(500)
|
|
await lineEndClick()
|
|
await page.waitForTimeout(500)
|
|
|
|
// click to continue profile
|
|
await page.mouse.move(813, 392, { steps: 10 })
|
|
await page.waitForTimeout(500)
|
|
|
|
await endOfTangentMv()
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
await endOfTangentClk()
|
|
|
|
await toolbar.selectThreePointArc()
|
|
await page.waitForTimeout(500)
|
|
await endOfTangentClk()
|
|
await threePointArcMidPointMv()
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
await threePointArcMidPointClk()
|
|
await page.waitForTimeout(100)
|
|
|
|
await threePointArcEndPointMv()
|
|
await page.waitForTimeout(500)
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
|
|
await threePointArcEndPointClk()
|
|
await page.waitForTimeout(100)
|
|
|
|
await toolbar.selectArc()
|
|
await page.waitForTimeout(100)
|
|
|
|
// continue the profile
|
|
await threePointArcEndPointClk()
|
|
await page.waitForTimeout(100)
|
|
await arcCenterMv()
|
|
await page.waitForTimeout(500)
|
|
await arcCenterClk()
|
|
|
|
await arcEndMv()
|
|
await page.waitForTimeout(500)
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
await arcEndClk()
|
|
}
|
|
)
|
|
|
|
test(
|
|
'Draft rectangles should look right',
|
|
{ tag: '@snapshot' },
|
|
async ({ page, context, cmdBar, scene }) => {
|
|
const u = await getUtils(page)
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
// click on "Start Sketch" button
|
|
await u.doAndWaitForImageDiff(
|
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
|
200
|
|
)
|
|
|
|
// select a plane
|
|
await page.mouse.click(700, 200)
|
|
|
|
await expect(page.locator('.cm-content')).toHaveText(
|
|
`sketch001 = startSketchOn(XZ)`
|
|
)
|
|
|
|
// Wait for camera animation
|
|
await page.waitForTimeout(2000)
|
|
|
|
const startXPx = 600
|
|
|
|
// Equip the rectangle tool
|
|
await page
|
|
.getByRole('button', { name: 'rectangle Corner rectangle', exact: true })
|
|
.click()
|
|
|
|
// Draw the rectangle
|
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 30)
|
|
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 10, { steps: 5 })
|
|
await page.waitForTimeout(800)
|
|
|
|
// Ensure the draft rectangle looks the same as it usually does
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
}
|
|
)
|
|
test(
|
|
'Draft circle should look right',
|
|
{ tag: '@snapshot' },
|
|
async ({ page, context, cmdBar, scene }) => {
|
|
const u = await getUtils(page)
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
|
200
|
|
)
|
|
|
|
// select a plane
|
|
await page.mouse.click(700, 200)
|
|
|
|
await expect(page.locator('.cm-content')).toHaveText(
|
|
`sketch001 = startSketchOn(XZ)`
|
|
)
|
|
|
|
// Wait for camera animation
|
|
await page.waitForTimeout(2000)
|
|
|
|
const startXPx = 600
|
|
|
|
// Equip the rectangle tool
|
|
// await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
|
await page.getByTestId('circle-center').click()
|
|
|
|
// Draw the rectangle
|
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
|
|
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 10, { steps: 5 })
|
|
|
|
// Ensure the draft rectangle looks the same as it usually does
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
await expect(page.locator('.cm-content')).toHaveText(
|
|
`sketch001 = startSketchOn(XZ)profile001 = circle(sketch001, center = [366.89, -62.01], radius = 1)`
|
|
)
|
|
}
|
|
)
|
|
|
|
test.describe(
|
|
'Client side scene scale should match engine scale',
|
|
{ tag: '@snapshot' },
|
|
() => {
|
|
test('Inch scale', async ({ page, cmdBar, scene, toolbar }) => {
|
|
const u = await getUtils(page)
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
|
200
|
|
)
|
|
|
|
// select a plane
|
|
await page.mouse.click(700, 200)
|
|
|
|
let code = `sketch001 = startSketchOn(XZ)`
|
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
|
|
|
// Wait for camera animation
|
|
await page.waitForTimeout(2000)
|
|
|
|
const startXPx = 600
|
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
|
code += `profile001 = startProfile(sketch001, at = [182.59, -246.32])`
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
await page.waitForTimeout(100)
|
|
|
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
|
await page.waitForTimeout(100)
|
|
|
|
code += `
|
|
|> xLine(length = 184.3)`
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
await toolbar.selectTangentialArc()
|
|
await page.waitForTimeout(200)
|
|
|
|
// click to continue profile
|
|
await page.mouse.click(813, 392)
|
|
await page.waitForTimeout(300)
|
|
|
|
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
|
|
|
code += `
|
|
|> tangentialArc(end = [184.31, 184.31])`
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
// click tangential arc tool again to unequip it
|
|
// it will be available directly in the toolbar since it was last equipped
|
|
await toolbar.tangentialArcBtn.click()
|
|
await page.waitForTimeout(1000)
|
|
|
|
// screen shot should show the sketch
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
() => page.getByRole('button', { name: 'Exit Sketch' }).click(),
|
|
200
|
|
)
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
// second screen shot should look almost identical, i.e. scale should be the same.
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
})
|
|
|
|
test('Millimeter scale', async ({
|
|
page,
|
|
context,
|
|
cmdBar,
|
|
scene,
|
|
toolbar,
|
|
}) => {
|
|
await context.addInitScript(
|
|
async ({ settingsKey, settings }) => {
|
|
localStorage.setItem(settingsKey, settings)
|
|
},
|
|
{
|
|
settingsKey: TEST_SETTINGS_KEY,
|
|
settings: settingsToToml({
|
|
settings: {
|
|
...TEST_SETTINGS,
|
|
modeling: {
|
|
...TEST_SETTINGS.modeling,
|
|
base_unit: 'mm',
|
|
},
|
|
},
|
|
}),
|
|
}
|
|
)
|
|
const u = await getUtils(page)
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await u.doAndWaitForImageDiff(
|
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
|
200
|
|
)
|
|
|
|
// select a plane
|
|
await page.mouse.click(700, 200)
|
|
|
|
let code = `sketch001 = startSketchOn(XZ)`
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
// Wait for camera animation
|
|
await page.waitForTimeout(2000)
|
|
|
|
const startXPx = 600
|
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
|
code += `profile001 = startProfile(sketch001, at = [182.59, -246.32])`
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
await page.waitForTimeout(100)
|
|
|
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
|
|
await page.waitForTimeout(100)
|
|
|
|
code += `
|
|
|> xLine(length = 184.3)`
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
await toolbar.selectTangentialArc()
|
|
await page.waitForTimeout(200)
|
|
|
|
// click to continue profile
|
|
await page.mouse.click(813, 392)
|
|
await page.waitForTimeout(300)
|
|
|
|
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
|
|
|
code += `
|
|
|> tangentialArc(end = [184.31, 184.31])`
|
|
await expect(u.codeLocator).toHaveText(code)
|
|
|
|
await toolbar.tangentialArcBtn.click()
|
|
await page.waitForTimeout(1000)
|
|
|
|
// screen shot should show the sketch
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
|
|
// exit sketch
|
|
await u.doAndWaitForImageDiff(
|
|
() => page.getByRole('button', { name: 'Exit Sketch' }).click(),
|
|
200
|
|
)
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
// second screen shot should look almost identical, i.e. scale should be the same.
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
})
|
|
}
|
|
)
|
|
|
|
test(
|
|
'Sketch on face with none z-up',
|
|
{ tag: '@snapshot' },
|
|
async ({ page, context, cmdBar, scene }) => {
|
|
const u = await getUtils(page)
|
|
await context.addInitScript(async (KCL_DEFAULT_LENGTH) => {
|
|
localStorage.setItem(
|
|
'persistCode',
|
|
`part001 = startSketchOn(-XZ)
|
|
|> startProfile(at = [1.4, 2.47])
|
|
|> line(end = [9.31, 10.55], tag = $seg01)
|
|
|> line(end = [11.91, -10.42])
|
|
|> close()
|
|
|> extrude(length = ${KCL_DEFAULT_LENGTH})
|
|
part002 = startSketchOn(part001, face = seg01)
|
|
|> startProfile(at = [8, 8])
|
|
|> line(end = [4.68, 3.05])
|
|
|> line(end = [0, -7.79])
|
|
|> close()
|
|
|> extrude(length = ${KCL_DEFAULT_LENGTH})
|
|
`
|
|
)
|
|
}, KCL_DEFAULT_LENGTH)
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
// Wait for the second extrusion to appear
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
// rendering, because an execution-done message is not sufficient.
|
|
await page.waitForTimeout(1000)
|
|
|
|
await expect(
|
|
page.getByRole('button', { name: 'Start Sketch' })
|
|
).not.toBeDisabled()
|
|
|
|
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
|
let previousCodeContent = await page.locator('.cm-content').innerText()
|
|
|
|
// click at 641, 135
|
|
await page.mouse.click(641, 135)
|
|
await expect(page.locator('.cm-content')).not.toHaveText(
|
|
previousCodeContent
|
|
)
|
|
previousCodeContent = await page.locator('.cm-content').innerText()
|
|
|
|
await page.waitForTimeout(300)
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
}
|
|
)
|
|
|
|
test(
|
|
'Zoom to fit on load - solid 2d',
|
|
{ tag: '@snapshot' },
|
|
async ({ page, context, cmdBar, scene }) => {
|
|
const u = await getUtils(page)
|
|
await context.addInitScript(async () => {
|
|
localStorage.setItem(
|
|
'persistCode',
|
|
`part001 = startSketchOn(XY)
|
|
|> startProfile(at = [-10, -10])
|
|
|> line(end = [20, 0])
|
|
|> line(end = [0, 20])
|
|
|> line(end = [-20, 0])
|
|
|> close()
|
|
`
|
|
)
|
|
}, KCL_DEFAULT_LENGTH)
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
// Wait for the second extrusion to appear
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
// rendering, because an execution-done message is not sufficient.
|
|
await page.waitForTimeout(2000)
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
}
|
|
)
|
|
|
|
test(
|
|
'Zoom to fit on load - solid 3d',
|
|
{ tag: '@snapshot' },
|
|
async ({ page, context, cmdBar, scene }) => {
|
|
const u = await getUtils(page)
|
|
await context.addInitScript(async () => {
|
|
localStorage.setItem(
|
|
'persistCode',
|
|
`part001 = startSketchOn(XY)
|
|
|> startProfile(at = [-10, -10])
|
|
|> line(end = [20, 0])
|
|
|> line(end = [0, 20])
|
|
|> line(end = [-20, 0])
|
|
|> close()
|
|
|> extrude(length = 10)
|
|
`
|
|
)
|
|
}, KCL_DEFAULT_LENGTH)
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
// Wait for the second extrusion to appear
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
// rendering, because an execution-done message is not sufficient.
|
|
await page.waitForTimeout(2000)
|
|
|
|
await expect(page).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
}
|
|
)
|
|
|
|
test.describe('Grid visibility', { tag: '@snapshot' }, () => {
|
|
test('Grid turned off to on via command bar', async ({
|
|
page,
|
|
cmdBar,
|
|
scene,
|
|
}) => {
|
|
const u = await getUtils(page)
|
|
const stream = page.getByTestId('stream')
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
await page.goto('/')
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await u.closeKclCodePanel()
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
// rendering, because an execution-done message is not sufficient.
|
|
await page.waitForTimeout(1000)
|
|
|
|
// Open the command bar.
|
|
await page
|
|
.getByRole('button', { name: 'Commands', exact: false })
|
|
.or(page.getByRole('button', { name: '⌘K' }))
|
|
.click()
|
|
const commandName = 'show scale grid'
|
|
const commandOption = page.getByRole('option', {
|
|
name: commandName,
|
|
exact: false,
|
|
})
|
|
const cmdSearchBar = page.getByPlaceholder('Search commands')
|
|
// This selector changes after we set the setting
|
|
await cmdSearchBar.fill(commandName)
|
|
await expect(commandOption).toBeVisible()
|
|
await commandOption.click()
|
|
|
|
const toggleInput = page.getByPlaceholder('Off')
|
|
await expect(toggleInput).toBeVisible()
|
|
await expect(toggleInput).toBeFocused()
|
|
|
|
// Select On
|
|
await page.keyboard.press('ArrowDown')
|
|
await expect(page.getByRole('option', { name: 'Off' })).toHaveAttribute(
|
|
'data-headlessui-state',
|
|
'active selected'
|
|
)
|
|
await page.keyboard.press('ArrowUp')
|
|
await expect(page.getByRole('option', { name: 'On' })).toHaveAttribute(
|
|
'data-headlessui-state',
|
|
'active'
|
|
)
|
|
await page.keyboard.press('Enter')
|
|
|
|
// Check the toast appeared
|
|
await expect(
|
|
page.getByText(`Set show scale grid to "true" as a user default`)
|
|
).toBeVisible()
|
|
|
|
await expect(stream).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: [...headerMasks(page), ...lowerRightMasks(page)],
|
|
})
|
|
})
|
|
|
|
test('Grid turned off', async ({ page, cmdBar, scene }) => {
|
|
const u = await getUtils(page)
|
|
const stream = page.getByTestId('stream')
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
await page.goto('/')
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await u.closeKclCodePanel()
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
// rendering, because an execution-done message is not sufficient.
|
|
await page.waitForTimeout(1000)
|
|
|
|
await expect(stream).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: [...headerMasks(page), ...lowerRightMasks(page)],
|
|
})
|
|
})
|
|
|
|
test('Grid turned on', async ({ page, context, cmdBar, scene }) => {
|
|
await context.addInitScript(
|
|
async ({ settingsKey, settings }) => {
|
|
localStorage.setItem(settingsKey, settings)
|
|
},
|
|
{
|
|
settingsKey: TEST_SETTINGS_KEY,
|
|
settings: settingsToToml({
|
|
settings: {
|
|
...TEST_SETTINGS,
|
|
modeling: {
|
|
...TEST_SETTINGS.modeling,
|
|
show_scale_grid: true,
|
|
},
|
|
},
|
|
}),
|
|
}
|
|
)
|
|
|
|
const u = await getUtils(page)
|
|
const stream = page.getByTestId('stream')
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
await page.goto('/')
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await u.closeKclCodePanel()
|
|
// TODO: Find a way to truly know that the objects have finished
|
|
// rendering, because an execution-done message is not sufficient.
|
|
await page.waitForTimeout(1000)
|
|
|
|
await expect(stream).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: [...headerMasks(page), ...lowerRightMasks(page)],
|
|
})
|
|
})
|
|
})
|
|
|
|
test('theme persists', async ({ page, context, homePage }) => {
|
|
const u = await getUtils(page)
|
|
await context.addInitScript(async () => {
|
|
localStorage.setItem(
|
|
'persistCode',
|
|
`part001 = startSketchOn(XY)
|
|
|> startProfile(at = [-10, -10])
|
|
|> line(end = [20, 0])
|
|
|> line(end = [0, 20])
|
|
|> line(end = [-20, 0])
|
|
|> close()
|
|
|> extrude(length = 10)
|
|
`
|
|
)
|
|
}, KCL_DEFAULT_LENGTH)
|
|
|
|
await page.setViewportSize({ width: 1200, height: 500 })
|
|
|
|
await homePage.goToModelingScene()
|
|
await page.waitForTimeout(500)
|
|
|
|
// await page.getByRole('link', { name: 'Settings Settings (tooltip)' }).click()
|
|
await expect(page.getByTestId('settings-link')).toBeVisible()
|
|
await page.getByTestId('settings-link').click()
|
|
|
|
// open user settingns
|
|
await page.getByRole('radio', { name: 'person User' }).click()
|
|
|
|
await page.getByTestId('app-theme').selectOption('light')
|
|
|
|
await page.getByTestId('settings-close-button').click()
|
|
|
|
const networkToggle = page.getByTestId(/network-toggle/)
|
|
|
|
// 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,
|
|
})
|
|
|
|
// Disconnect and reconnect to check the theme persists through a reload
|
|
|
|
// Expect the network to be down
|
|
await expect(networkToggle).toContainText('Problem')
|
|
|
|
// 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,
|
|
})
|
|
|
|
await expect(networkToggle).toContainText('Network health (Strong)')
|
|
|
|
await expect(page.getByText('building scene')).not.toBeVisible()
|
|
|
|
await expect(page, 'expect screenshot to have light theme').toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
})
|
|
|
|
test.describe('code color goober', { tag: '@snapshot' }, () => {
|
|
test('code color goober', async ({ page, context, scene, cmdBar }) => {
|
|
const u = await getUtils(page)
|
|
await context.addInitScript(async () => {
|
|
localStorage.setItem(
|
|
'persistCode',
|
|
`// Create a pipe using a sweep.
|
|
|
|
// Create a path for the sweep.
|
|
sweepPath = startSketchOn(XZ)
|
|
|> startProfile(at = [0.05, 0.05])
|
|
|> line(end = [0, 7])
|
|
|> tangentialArc(angle = 90, radius = 5)
|
|
|> line(end = [-3, 0])
|
|
|> tangentialArc(angle = -90, radius = 5)
|
|
|> line(end = [0, 7])
|
|
|
|
sweepSketch = startSketchOn(XY)
|
|
|> startProfile(at = [2, 0])
|
|
|> arc(angleStart = 0, angleEnd = 360, radius = 2)
|
|
|> sweep(path = sweepPath)
|
|
|> appearance(
|
|
color = "#bb00ff",
|
|
metalness = 90,
|
|
roughness = 90
|
|
)
|
|
`
|
|
)
|
|
})
|
|
|
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await expect(page, 'expect small color widget').toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
})
|
|
test('code color goober works with single quotes', async ({
|
|
page,
|
|
context,
|
|
scene,
|
|
cmdBar,
|
|
}) => {
|
|
const u = await getUtils(page)
|
|
await context.addInitScript(async () => {
|
|
localStorage.setItem(
|
|
'persistCode',
|
|
`// Create a pipe using a sweep.
|
|
|
|
// Create a path for the sweep.
|
|
sweepPath = startSketchOn(XZ)
|
|
|> startProfile(at = [0.05, 0.05])
|
|
|> line(end = [0, 7])
|
|
|> tangentialArc(angle = 90, radius = 5)
|
|
|> line(end = [-3, 0])
|
|
|> tangentialArc(angle = -90, radius = 5)
|
|
|> line(end = [0, 7])
|
|
|
|
sweepSketch = startSketchOn(XY)
|
|
|> startProfile(at = [2, 0])
|
|
|> arc(angleStart = 0, angleEnd = 360, radius = 2)
|
|
|> sweep(path = sweepPath)
|
|
|> appearance(
|
|
color = '#bb00ff',
|
|
metalness = 90,
|
|
roughness = 90
|
|
)
|
|
`
|
|
)
|
|
})
|
|
|
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await expect(page, 'expect small color widget').toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
})
|
|
|
|
test('code color goober opening window', async ({
|
|
page,
|
|
context,
|
|
scene,
|
|
cmdBar,
|
|
}) => {
|
|
const u = await getUtils(page)
|
|
await context.addInitScript(async () => {
|
|
localStorage.setItem(
|
|
'persistCode',
|
|
`// Create a pipe using a sweep.
|
|
|
|
// Create a path for the sweep.
|
|
sweepPath = startSketchOn(XZ)
|
|
|> startProfile(at = [0.05, 0.05])
|
|
|> line(end = [0, 7])
|
|
|> tangentialArc(angle = 90, radius = 5)
|
|
|> line(end = [-3, 0])
|
|
|> tangentialArc(angle = -90, radius = 5)
|
|
|> line(end = [0, 7])
|
|
|
|
sweepSketch = startSketchOn(XY)
|
|
|> startProfile(at = [2, 0])
|
|
|> arc(angleStart = 0, angleEnd = 360, radius = 2)
|
|
|> sweep(path = sweepPath)
|
|
|> appearance(
|
|
color = "#bb00ff",
|
|
metalness = 90,
|
|
roughness = 90
|
|
)
|
|
`
|
|
)
|
|
})
|
|
|
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
|
await u.waitForAuthSkipAppStart()
|
|
|
|
await scene.settled(cmdBar)
|
|
|
|
await expect(page.locator('.cm-css-color-picker-wrapper')).toBeVisible()
|
|
|
|
// Click the color widget
|
|
await page.locator('.cm-css-color-picker-wrapper input').click()
|
|
|
|
await expect(
|
|
page,
|
|
'expect small color widget to have window open'
|
|
).toHaveScreenshot({
|
|
maxDiffPixels: 100,
|
|
mask: lowerRightMasks(page),
|
|
})
|
|
})
|
|
})
|