This commit is contained in:
49lf
2024-11-22 16:09:09 -05:00
parent 249e35f9e0
commit 4c28af615c
12 changed files with 2877 additions and 2675 deletions

View File

@ -9,7 +9,11 @@ import { HomePageFixture } from './fixtures/homePageFixture'
test.setTimeout(120000) test.setTimeout(120000)
async function doBasicSketch(page: Page, homePage: HomePageFixture, openPanes: string[]) { async function doBasicSketch(
page: Page,
homePage: HomePageFixture,
openPanes: string[]
) {
const u = await getUtils(page) const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio const PUR = 400 / 37.5 //pixeltoUnitRatio
@ -139,16 +143,19 @@ async function doBasicSketch(page: Page, homePage: HomePageFixture, openPanes: s
} }
test.describe('Basic sketch', () => { test.describe('Basic sketch', () => {
test('code pane open at start', async ({ page, homePage }) => { // Skip on windows it is being weird. test('code pane open at start', async ({ page, homePage }) => {
// Skip on windows it is being weird.
await doBasicSketch(page, homePage, ['code']) await doBasicSketch(page, homePage, ['code'])
}) })
test('code pane closed at start', async ({ page, homePage }) => { // Load the app with the code panes test('code pane closed at start', async ({ page, homePage }) => {
// Load the app with the code panes
await page.addInitScript(async (persistModelingContext) => { await page.addInitScript(async (persistModelingContext) => {
localStorage.setItem( localStorage.setItem(
persistModelingContext, persistModelingContext,
JSON.stringify({ openPanes: [] }) JSON.stringify({ openPanes: [] })
) )
}, PERSIST_MODELING_CONTEXT) }, PERSIST_MODELING_CONTEXT)
await doBasicSketch(page, homePage, []) }) await doBasicSketch(page, homePage, [])
})
}) })

View File

@ -84,7 +84,8 @@ test.describe('Can create sketches on all planes and their back sides', () => {
'XY', 'XY',
{ x: 600, y: 388 } // red plane { x: 600, y: 388 } // red plane
// { x: 600, y: 400 }, // red plane // clicks grid helper and that causes problems, should fix so that these coords work too. // { x: 600, y: 400 }, // red plane // clicks grid helper and that causes problems, should fix so that these coords work too.
) }) )
})
test('YZ', async ({ page, homePage }) => { test('YZ', async ({ page, homePage }) => {
await sketchOnPlaneAndBackSideTest(page, homePage, 'YZ', { x: 700, y: 250 }) // green plane await sketchOnPlaneAndBackSideTest(page, homePage, 'YZ', { x: 700, y: 250 }) // green plane
@ -95,11 +96,17 @@ test.describe('Can create sketches on all planes and their back sides', () => {
}) })
test('-XY', async ({ page, homePage }) => { test('-XY', async ({ page, homePage }) => {
await sketchOnPlaneAndBackSideTest(page, homePage, '-XY', { x: 600, y: 118 }) // back of red plane await sketchOnPlaneAndBackSideTest(page, homePage, '-XY', {
x: 600,
y: 118,
}) // back of red plane
}) })
test('-YZ', async ({ page, homePage }) => { test('-YZ', async ({ page, homePage }) => {
await sketchOnPlaneAndBackSideTest(page, homePage, '-YZ', { x: 700, y: 219 }) // back of green plan await sketchOnPlaneAndBackSideTest(page, homePage, '-YZ', {
x: 700,
y: 219,
}) // back of green plan
}) })
test('-XZ', async ({ page, homePage }) => { test('-XZ', async ({ page, homePage }) => {

View File

@ -1,16 +1,17 @@
import { test, expect } from './zoo-test' import { test, expect } from './zoo-test'
import { import { getUtils, executorInputPath } from './test-utils'
getUtils,
executorInputPath,
} from './test-utils'
import { join } from 'path' import { join } from 'path'
import { bracket } from 'lib/exampleKcl' import { bracket } from 'lib/exampleKcl'
import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from './storageStates' import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from './storageStates'
import fsp from 'fs/promises' import fsp from 'fs/promises'
test.describe('Code pane and errors', () => { test.describe('Code pane and errors', () => {
test('Typing KCL errors induces a badge on the code pane button', async ({ page, homePage }) => { const u = await getUtils(page) test('Typing KCL errors induces a badge on the code pane button', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
// Load the app with the working starter code // Load the app with the working starter code
await page.addInitScript(() => { await page.addInitScript(() => {
@ -45,10 +46,13 @@ test.describe('Code pane and errors', () => {
await page.keyboard.press('Backspace') await page.keyboard.press('Backspace')
// Ensure that a badge appears on the button // Ensure that a badge appears on the button
await expect(codePaneButtonHolder).toContainText('notification') }) await expect(codePaneButtonHolder).toContainText('notification')
})
test('Opening and closing the code pane will consistently show error diagnostics', async ({ page, homePage }) => {
test('Opening and closing the code pane will consistently show error diagnostics', async ({
page,
homePage,
}) => {
const u = await getUtils(page) const u = await getUtils(page)
// Load the app with the working starter code // Load the app with the working starter code
@ -108,9 +112,15 @@ test.describe('Code pane and errors', () => {
// error text on hover // error text on hover
await page.hover('.cm-lint-marker-error') await page.hover('.cm-lint-marker-error')
await expect(page.locator('.cm-tooltip').first()).toBeVisible() }) await expect(page.locator('.cm-tooltip').first()).toBeVisible()
})
test('When error is not in view you can click the badge to scroll to it', async ({ page, homePage, context }) => { const u = await getUtils(page) test('When error is not in view you can click the badge to scroll to it', async ({
page,
homePage,
context,
}) => {
const u = await getUtils(page)
// Load the app with the working starter code // Load the app with the working starter code
await context.addInitScript((code) => { await context.addInitScript((code) => {
@ -145,9 +155,15 @@ test.describe('Code pane and errors', () => {
'Modeling command failed: [ApiError { error_code: InternalEngine, message: "Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis" }]' 'Modeling command failed: [ApiError { error_code: InternalEngine, message: "Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis" }]'
) )
.first() .first()
).toBeVisible() }) ).toBeVisible()
})
test('When error is not in view WITH LINTS you can click the badge to scroll to it', async ({ context, page, homePage }) => { const u = await getUtils(page) test('When error is not in view WITH LINTS you can click the badge to scroll to it', async ({
context,
page,
homePage,
}) => {
const u = await getUtils(page)
// Load the app with the working starter code // Load the app with the working starter code
await context.addInitScript((code) => { await context.addInitScript((code) => {
@ -208,7 +224,8 @@ test.describe('Code pane and errors', () => {
'sketch profile must lie entirely on one side of the revolution axis' 'sketch profile must lie entirely on one side of the revolution axis'
) )
.first() .first()
).toBeVisible() }) ).toBeVisible()
})
}) })
test( test(
@ -287,7 +304,7 @@ test(
{ tag: '@electron' }, { tag: '@electron' },
async ({ context, browserName, page }, testInfo) => { async ({ context, browserName, page }, testInfo) => {
const PROJECT_DIR_NAME = 'lee-was-here' const PROJECT_DIR_NAME = 'lee-was-here'
const { dir: projectsDir, } = await context.folderSetupFn(async (dir) => { const { dir: projectsDir } = await context.folderSetupFn(async (dir) => {
const aProjectDir = join(dir, PROJECT_DIR_NAME) const aProjectDir = join(dir, PROJECT_DIR_NAME)
await fsp.mkdir(aProjectDir, { recursive: true }) await fsp.mkdir(aProjectDir, { recursive: true })
}) })

View File

@ -5,7 +5,11 @@ import { KCL_DEFAULT_LENGTH } from 'lib/constants'
import { normalizeLineEndings } from 'lib/codeEditor' import { normalizeLineEndings } from 'lib/codeEditor'
test.describe('Command bar tests', () => { test.describe('Command bar tests', () => {
test('Extrude from command bar selects extrude line after', async ({ page, homePage }) => { await page.addInitScript(async () => { test('Extrude from command bar selects extrude line after', async ({
page,
homePage,
}) => {
await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn('XY') `sketch001 = startSketchOn('XY')
@ -39,9 +43,11 @@ test.describe('Command bar tests', () => {
await page.waitForTimeout(200) await page.waitForTimeout(200)
await expect(page.locator('.cm-activeLine')).toHaveText( await expect(page.locator('.cm-activeLine')).toHaveText(
`extrude001 = extrude(${KCL_DEFAULT_LENGTH}, sketch001)` `extrude001 = extrude(${KCL_DEFAULT_LENGTH}, sketch001)`
) }) )
})
test('Fillet from command bar', async ({ page, homePage }) => { await page.addInitScript(async () => { test('Fillet from command bar', async ({ page, homePage }) => {
await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn('XY') `sketch001 = startSketchOn('XY')
@ -76,9 +82,14 @@ test.describe('Command bar tests', () => {
await page.waitForTimeout(100) await page.waitForTimeout(100)
await expect(page.locator('.cm-activeLine')).toContainText( await expect(page.locator('.cm-activeLine')).toContainText(
`fillet({ radius: ${KCL_DEFAULT_LENGTH}, tags: [seg01] }, %)` `fillet({ radius: ${KCL_DEFAULT_LENGTH}, tags: [seg01] }, %)`
) }) )
})
test('Command bar can change a setting, and switch back and forth between arguments', async ({ page, homePage }) => { const u = await getUtils(page) test('Command bar can change a setting, and switch back and forth between arguments', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
@ -153,9 +164,14 @@ test.describe('Command bar tests', () => {
// Test case for https://github.com/KittyCAD/modeling-app/issues/2881 // Test case for https://github.com/KittyCAD/modeling-app/issues/2881
await commandThemeArgButton.click() await commandThemeArgButton.click()
await expect(commandThemeArgButton).toBeDisabled() await expect(commandThemeArgButton).toBeDisabled()
await expect(commandLevelArgButton).toHaveText('level: project') }) await expect(commandLevelArgButton).toHaveText('level: project')
})
test('Command bar keybinding works from code editor and can change a setting', async ({ page, homePage }) => { const u = await getUtils(page) test('Command bar keybinding works from code editor and can change a setting', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
@ -198,9 +214,11 @@ test.describe('Command bar tests', () => {
page.getByText(`Set theme to "system" as a user default`) page.getByText(`Set theme to "system" as a user default`)
).toBeVisible() ).toBeVisible()
// Check that the theme changed // Check that the theme changed
await expect(page.locator('body')).not.toHaveClass(`body-bg dark`) }) await expect(page.locator('body')).not.toHaveClass(`body-bg dark`)
})
test('Can extrude from the command bar', async ({ page, homePage }) => { await page.addInitScript(async () => { test('Can extrude from the command bar', async ({ page, homePage }) => {
await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`distance = sqrt(20) `distance = sqrt(20)
@ -273,11 +291,16 @@ test.describe('Command bar tests', () => {
await u.waitForCmdReceive('extrude') await u.waitForCmdReceive('extrude')
await expect(page.locator('.cm-content')).toContainText('extrude001 = extrude(distance001, sketch001)') await expect(page.locator('.cm-content')).toContainText(
'extrude001 = extrude(distance001, sketch001)'
)
}) })
test('Can switch between sketch tools via command bar', async ({ page, homePage }) => { const u = await getUtils(page) test('Can switch between sketch tools via command bar', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
@ -323,5 +346,6 @@ test.describe('Command bar tests', () => {
// switch to tangential arc via command bar // switch to tangential arc via command bar
await cmdBarButton.click() await cmdBarButton.click()
await arcToolCommand.click() await arcToolCommand.click()
await expect(arcToolButton).toHaveAttribute('aria-pressed', 'true') }) await expect(arcToolButton).toHaveAttribute('aria-pressed', 'true')
})
}) })

View File

@ -1,23 +1,16 @@
import { test, expect } from '@playwright/test' import { test, expect } from './zoo-test'
import { getUtils, setup, tearDown } from './test-utils' import { getUtils } from './test-utils'
test.beforeEach(async ({ context, page }, testInfo) => {
await setup(context, page, testInfo)
})
test.afterEach(async ({ page }, testInfo) => {
await tearDown(page, testInfo)
})
test.describe('Copilot ghost text', () => { test.describe('Copilot ghost text', () => {
// eslint-disable-next-line jest/valid-title // eslint-disable-next-line jest/valid-title
test.skip(true, 'Needs to get covered again') test.skip(true, 'Needs to get covered again')
test('completes code in empty file', async ({ page }) => { test('completes code in empty file', async ({ page, homePage }) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -55,9 +48,9 @@ test.describe('Copilot ghost text', () => {
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -101,12 +94,13 @@ test.describe('Copilot ghost text', () => {
test('copilot disabled in sketch mode after selecting plane', async ({ test('copilot disabled in sketch mode after selecting plane', async ({
page, page,
homePage,
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -184,12 +178,12 @@ test.describe('Copilot ghost text', () => {
await expect(page.locator('.cm-ghostText')).not.toBeVisible() await expect(page.locator('.cm-ghostText')).not.toBeVisible()
}) })
test('ArrowUp in code rejects the suggestion', async ({ page }) => { test('ArrowUp in code rejects the suggestion', async ({ page, homePage }) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -212,12 +206,15 @@ test.describe('Copilot ghost text', () => {
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
}) })
test('ArrowDown in code rejects the suggestion', async ({ page }) => { test('ArrowDown in code rejects the suggestion', async ({
page,
homePage,
}) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -240,12 +237,15 @@ test.describe('Copilot ghost text', () => {
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
}) })
test('ArrowLeft in code rejects the suggestion', async ({ page }) => { test('ArrowLeft in code rejects the suggestion', async ({
page,
homePage,
}) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -268,12 +268,15 @@ test.describe('Copilot ghost text', () => {
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
}) })
test('ArrowRight in code rejects the suggestion', async ({ page }) => { test('ArrowRight in code rejects the suggestion', async ({
page,
homePage,
}) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -296,12 +299,12 @@ test.describe('Copilot ghost text', () => {
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
}) })
test('Enter in code scoots it down', async ({ page }) => { test('Enter in code scoots it down', async ({ page, homePage }) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -326,12 +329,15 @@ test.describe('Copilot ghost text', () => {
) )
}) })
test('Ctrl+shift+z in code rejects the suggestion', async ({ page }) => { test('Ctrl+shift+z in code rejects the suggestion', async ({
page,
homePage,
}) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -360,12 +366,13 @@ test.describe('Copilot ghost text', () => {
test('Ctrl+z in code rejects the suggestion and undos the last code', async ({ test('Ctrl+z in code rejects the suggestion and undos the last code', async ({
page, page,
homePage,
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await page.waitForTimeout(800) await page.waitForTimeout(800)
await u.codeLocator.click() await u.codeLocator.click()
@ -420,15 +427,17 @@ test.describe('Copilot ghost text', () => {
await expect(page.locator('.cm-ghostText').first()).not.toBeVisible() await expect(page.locator('.cm-ghostText').first()).not.toBeVisible()
// TODO when we make codemirror a widget, we can test this. // TODO when we make codemirror a widget, we can test this.
//await expect(page.locator('.cm-content')).toHaveText(``) //await expect(page.locator('.cm-content')).toHaveText(``) })
})
test('delete in code rejects the suggestion', async ({ page }) => { test('delete in code rejects the suggestion', async ({
page,
homePage,
}) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -453,12 +462,15 @@ test.describe('Copilot ghost text', () => {
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
}) })
test('backspace in code rejects the suggestion', async ({ page }) => { test('backspace in code rejects the suggestion', async ({
page,
homePage,
}) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -483,12 +495,15 @@ test.describe('Copilot ghost text', () => {
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
}) })
test('focus outside code pane rejects the suggestion', async ({ page }) => { test('focus outside code pane rejects the suggestion', async ({
page,
homePage,
}) => {
const u = await getUtils(page) const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio // const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart() await homePage.goToModelingScene()
await u.codeLocator.click() await u.codeLocator.click()
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
@ -514,4 +529,5 @@ test.describe('Copilot ghost text', () => {
await expect(page.locator('.cm-content')).toHaveText(``) await expect(page.locator('.cm-content')).toHaveText(``)
}) })
})
}) })

View File

@ -65,7 +65,7 @@ export class AuthenticatedTronApp {
public readonly testInfo: TestInfo public readonly testInfo: TestInfo
public electronApp?: ElectronApplication public electronApp?: ElectronApplication
public readonly viewPortSize = { width: 1200, height: 500 } public readonly viewPortSize = { width: 1200, height: 500 }
public dir: string = "" public dir: string = ''
constructor(context: BrowserContext, page: Page, testInfo: TestInfo) { constructor(context: BrowserContext, page: Page, testInfo: TestInfo) {
this._page = page this._page = page

View File

@ -12,11 +12,13 @@ import {
} from './test-utils' } from './test-utils'
import { uuidv4, roundOff } from 'lib/utils' import { uuidv4, roundOff } from 'lib/utils'
test.describe('Sketch tests', () => { test.describe('Sketch tests', () => {
test('multi-sketch file shows multiple Edit Sketch buttons', async ({ page, context, test('multi-sketch file shows multiple Edit Sketch buttons', async ({
homePage }) => { const u = await getUtils(page) page,
context,
homePage,
}) => {
const u = await getUtils(page)
const selectionsSnippets = { const selectionsSnippets = {
startProfileAt1: startProfileAt1:
'|> startProfileAt([-width / 4 + screwRadius, height / 2], %)', '|> startProfileAt([-width / 4 + screwRadius, height / 2], %)',
@ -97,9 +99,14 @@ test.describe('Sketch tests', () => {
await expect(page.getByRole('button', { name: 'Extrude' })).toBeDisabled() await expect(page.getByRole('button', { name: 'Extrude' })).toBeDisabled()
await expect( await expect(
page.getByRole('button', { name: 'Edit Sketch' }) page.getByRole('button', { name: 'Edit Sketch' })
).toBeVisible() }) ).toBeVisible()
test('Can delete most of a sketch and the line tool will still work', async ({ page, center, })
homePage }) => { const u = await getUtils(page) test('Can delete most of a sketch and the line tool will still work', async ({
page,
center,
homePage,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -140,16 +147,21 @@ test.describe('Sketch tests', () => {
await page.mouse.move(700, 200, { step: 25 }) await page.mouse.move(700, 200, { step: 25 })
await page.mouse.click(700, 200) await page.mouse.click(700, 200)
await expect.poll(u.crushKclCodeIntoOneLineAndThenMaybeSome, { timeout: 1000 }) await expect
.toBe(`sketch001 = startSketchOn('XZ') .poll(u.crushKclCodeIntoOneLineAndThenMaybeSome, { timeout: 1000 })
.toBe(
`sketch001 = startSketchOn('XZ')
|> startProfileAt([4.61,-14.01], %) |> startProfileAt([4.61,-14.01], %)
|> yLine(15.95, %) |> yLine(15.95, %)
`.replaceAll(' ', '').replaceAll("\n", '')) `
.replaceAll(' ', '')
.replaceAll('\n', '')
)
}).toPass({ timeout: 40_000, intervals: [1_000] }) }).toPass({ timeout: 40_000, intervals: [1_000] })
}) })
test('Can exit selection of face', async ({ page, homePage }) => { // Load the app with the code panes test('Can exit selection of face', async ({ page, homePage }) => {
// Load the app with the code panes
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem('persistCode', ``) localStorage.setItem('persistCode', ``)
}) })
@ -169,7 +181,8 @@ test.describe('Sketch tests', () => {
await page.keyboard.press('Escape') await page.keyboard.press('Escape')
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible() }) ).toBeVisible()
})
test.describe('Can edit segments by dragging their handles', () => { test.describe('Can edit segments by dragging their handles', () => {
const doEditSegmentsByDraggingHandle = async ( const doEditSegmentsByDraggingHandle = async (
page: Page, page: Page,
@ -304,7 +317,8 @@ test.describe('Sketch tests', () => {
|> line([1.97, 2.06], %) |> line([1.97, 2.06], %)
|> close(%)`) |> close(%)`)
} }
test('code pane open at start-handles', async ({ page, homePage }) => { // Load the app with the code panes test('code pane open at start-handles', async ({ page, homePage }) => {
// Load the app with the code panes
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'store', 'store',
@ -316,19 +330,26 @@ test.describe('Sketch tests', () => {
}) })
) )
}) })
await doEditSegmentsByDraggingHandle(page, homePage, ['code']) }) await doEditSegmentsByDraggingHandle(page, homePage, ['code'])
})
test('code pane closed at start-handles', async ({ page, homePage }) => { // Load the app with the code panes test('code pane closed at start-handles', async ({ page, homePage }) => {
// Load the app with the code panes
await page.addInitScript(async (persistModelingContext) => { await page.addInitScript(async (persistModelingContext) => {
localStorage.setItem( localStorage.setItem(
persistModelingContext, persistModelingContext,
JSON.stringify({ openPanes: [] }) JSON.stringify({ openPanes: [] })
) )
}, PERSIST_MODELING_CONTEXT) }, PERSIST_MODELING_CONTEXT)
await doEditSegmentsByDraggingHandle(page, homePage, []) }) await doEditSegmentsByDraggingHandle(page, homePage, [])
})
}) })
test('Can edit a circle center and radius by dragging its handles', async ({ page, homePage }) => { const u = await getUtils(page) test('Can edit a circle center and radius by dragging its handles', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -408,8 +429,13 @@ test.describe('Sketch tests', () => {
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content'))
.toHaveText(`sketch001 = startSketchOn('XZ') .toHaveText(`sketch001 = startSketchOn('XZ')
|> circle({ center: [7.26, -2.37], radius: 11.44 }, %) |> circle({ center: [7.26, -2.37], radius: 11.44 }, %)
`) }) `)
test('Can edit a sketch that has been extruded in the same pipe', async ({ page, homePage }) => { const u = await getUtils(page) })
test('Can edit a sketch that has been extruded in the same pipe', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -505,9 +531,14 @@ test.describe('Sketch tests', () => {
|> tangentialArcTo([24.89, 0.68], %) |> tangentialArcTo([24.89, 0.68], %)
|> close(%) |> close(%)
|> extrude(5, %) |> extrude(5, %)
`) }) `)
})
test('Can edit a sketch that has been revolved in the same pipe', async ({ page, homePage }) => { const u = await getUtils(page) test('Can edit a sketch that has been revolved in the same pipe', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -602,8 +633,10 @@ test.describe('Sketch tests', () => {
|> tangentialArcTo([24.95, -5.38], %) |> tangentialArcTo([24.95, -5.38], %)
|> line([1.97, 2.06], %) |> line([1.97, 2.06], %)
|> close(%) |> close(%)
|> revolve({ axis: "X" }, %)`) }) |> revolve({ axis: "X" }, %)`)
test('Can add multiple sketches', async ({ page, homePage }) => { const u = await getUtils(page) })
test('Can add multiple sketches', async ({ page, homePage }) => {
const u = await getUtils(page)
const viewportSize = { width: 1200, height: 500 } const viewportSize = { width: 1200, height: 500 }
await page.setBodyDimensions(viewportSize) await page.setBodyDimensions(viewportSize)
@ -694,7 +727,8 @@ test.describe('Sketch tests', () => {
await page.getByRole('button', { name: 'Exit Sketch' }).click() await page.getByRole('button', { name: 'Exit Sketch' }).click()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.updateCamPosition([100, 100, 100]) await u.updateCamPosition([100, 100, 100])
await u.clearCommandLogs() }) await u.clearCommandLogs()
})
test.describe('Snap to close works (at any scale)', () => { test.describe('Snap to close works (at any scale)', () => {
const doSnapAtDifferentScales = async ( const doSnapAtDifferentScales = async (
page: any, page: any,
@ -785,13 +819,21 @@ test.describe('Sketch tests', () => {
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.removeCurrentCode() await u.removeCurrentCode()
} }
test('[0, 100, 100]', async ({ page, homePage }) => { await homePage.goToModelingScene() test('[0, 100, 100]', async ({ page, homePage }) => {
await doSnapAtDifferentScales(page, [0, 100, 100], 0.01) }) await homePage.goToModelingScene()
await doSnapAtDifferentScales(page, [0, 100, 100], 0.01)
test('[0, 10000, 10000]', async ({ page, homePage }) => { await homePage.goToModelingScene()
await doSnapAtDifferentScales(page, [0, 10000, 10000]) })
}) })
test('exiting a close extrude, has the extrude button enabled ready to go', async ({ page, homePage }) => { // this was a regression https://github.com/KittyCAD/modeling-app/issues/2832
test('[0, 10000, 10000]', async ({ page, homePage }) => {
await homePage.goToModelingScene()
await doSnapAtDifferentScales(page, [0, 10000, 10000])
})
})
test('exiting a close extrude, has the extrude button enabled ready to go', async ({
page,
homePage,
}) => {
// this was a regression https://github.com/KittyCAD/modeling-app/issues/2832
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -843,8 +885,13 @@ test.describe('Sketch tests', () => {
page.getByRole('button', { name: 'selection : 1 face', exact: false }) page.getByRole('button', { name: 'selection : 1 face', exact: false })
).toBeVisible({ ).toBeVisible({
timeout: 10_000, timeout: 10_000,
}) }) })
test("Existing sketch with bad code delete user's code", async ({ page, homePage }) => { // this was a regression https://github.com/KittyCAD/modeling-app/issues/2832 })
test("Existing sketch with bad code delete user's code", async ({
page,
homePage,
}) => {
// this was a regression https://github.com/KittyCAD/modeling-app/issues/2832
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -899,8 +946,13 @@ test.describe('Sketch tests', () => {
sketch002 = startSketchOn(extrude001, 'END') sketch002 = startSketchOn(extrude001, 'END')
|> |>
`.replace(/\s/g, '') `.replace(/\s/g, '')
) }) )
test('empty-scene default-planes act as expected', async ({ page, homePage }) => { /** })
test('empty-scene default-planes act as expected', async ({
page,
homePage,
}) => {
/**
* Tests the following things * Tests the following things
* 1) The the planes are there on load because the scene is empty * 1) The the planes are there on load because the scene is empty
* 2) The planes don't changes color when hovered initially * 2) The planes don't changes color when hovered initially
@ -995,9 +1047,11 @@ test.describe('Sketch tests', () => {
// expect there to be no planes on load since there's something in the scene // expect there to be no planes on load since there's something in the scene
expect( expect(
await u.getGreatestPixDiff(XYPlanePoint, noPlanesColor) await u.getGreatestPixDiff(XYPlanePoint, noPlanesColor)
).toBeLessThan(3) }) ).toBeLessThan(3)
})
test('Can attempt to sketch on revolved face', async ({ page, homePage }) => { const u = await getUtils(page) test('Can attempt to sketch on revolved face', async ({ page, homePage }) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await page.addInitScript(async () => { await page.addInitScript(async () => {
@ -1050,9 +1104,14 @@ test.describe('Sketch tests', () => {
await expect( await expect(
page.getByRole('button', { name: 'line Line', exact: true }) page.getByRole('button', { name: 'line Line', exact: true })
).toHaveAttribute('aria-pressed', 'true') ).toHaveAttribute('aria-pressed', 'true')
}).toPass({ timeout: 40_000, intervals: [1_000] }) }) }).toPass({ timeout: 40_000, intervals: [1_000] })
})
test('Can sketch on face when user defined function was used in the sketch', async ({ page, homePage }) => { const u = await getUtils(page) test('Can sketch on face when user defined function was used in the sketch', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
// Checking for a regression that performs a sketch when a user defined function // Checking for a regression that performs a sketch when a user defined function
@ -1142,7 +1201,8 @@ test.describe('Sketch tests', () => {
// Check execution is done // Check execution is done
await u.openDebugPanel() await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel() }) await u.closeDebugPanel()
})
}) })
test.describe('Sketch mode should be toleratant to syntax errors', () => { test.describe('Sketch mode should be toleratant to syntax errors', () => {
@ -1213,9 +1273,14 @@ test.describe('Sketch mode should be toleratant to syntax errors', () => {
}) })
test.describe(`Sketching with offset planes`, () => { test.describe(`Sketching with offset planes`, () => {
test( test(`Can select an offset plane to sketch on`, async ({
`Can select an offset plane to sketch on`, context,
async ({ context, page, scene, toolbar, editor, homePage }) => { page,
scene,
toolbar,
editor,
homePage,
}) => {
// We seed the scene with a single offset plane // We seed the scene with a single offset plane
await context.addInitScript(() => { await context.addInitScript(() => {
localStorage.setItem( localStorage.setItem(
@ -1240,9 +1305,7 @@ test.describe(`Sketching with offset planes`, () => {
}) })
}) })
await test.step( await test.step(`Clicking should select the plane and enter sketch mode`, async () => {
`Clicking should select the plane and enter sketch mode`,
async () => {
await planeClick() await planeClick()
// Have to wait for engine-side animation to finish // Have to wait for engine-side animation to finish
await page.waitForTimeout(600) await page.waitForTimeout(600)
@ -1253,9 +1316,7 @@ test.describe(`Sketching with offset planes`, () => {
diagnostics: [], diagnostics: [],
highlightedCode: '', highlightedCode: '',
}) })
}
)
}) })
} })
) })
}) })

View File

@ -418,7 +418,7 @@ export async function getUtils(page: Page, test_?: typeof test) {
codeLocator: page.locator('.cm-content'), codeLocator: page.locator('.cm-content'),
crushKclCodeIntoOneLineAndThenMaybeSome: async () => { crushKclCodeIntoOneLineAndThenMaybeSome: async () => {
const code = await page.locator('.cm-content').innerText() const code = await page.locator('.cm-content').innerText()
return code.replaceAll(' ', '').replaceAll("\n", '') return code.replaceAll(' ', '').replaceAll('\n', '')
}, },
normalisedEditorCode: async () => { normalisedEditorCode: async () => {
const code = await page.locator('.cm-content').innerText() const code = await page.locator('.cm-content').innerText()
@ -687,14 +687,16 @@ const moveDownloadedFileTo = async (page: Page, toLocation: string) => {
const downloadDir = path.resolve( const downloadDir = path.resolve(
page.TEST_SETTINGS_FILE_KEY, page.TEST_SETTINGS_FILE_KEY,
"downloads-during-playwright" 'downloads-during-playwright'
) )
// Expect there to be at least one file // Expect there to be at least one file
expect.poll(async () => { expect
.poll(async () => {
const files = await fsp.readdir(downloadDir) const files = await fsp.readdir(downloadDir)
return files.length return files.length
}).toBe(1) })
.toBe(1)
// Go through the downloads dir and move files to new location // Go through the downloads dir and move files to new location
const files = await fsp.readdir(downloadDir) const files = await fsp.readdir(downloadDir)
@ -832,7 +834,13 @@ export async function setup(
testInfo?: TestInfo testInfo?: TestInfo
) { ) {
await context.addInitScript( await context.addInitScript(
async ({ token, settingsKey, settings, IS_PLAYWRIGHT_KEY, PLAYWRIGHT_TEST_DIR }) => { async ({
token,
settingsKey,
settings,
IS_PLAYWRIGHT_KEY,
PLAYWRIGHT_TEST_DIR,
}) => {
localStorage.clear() localStorage.clear()
localStorage.setItem('TOKEN_PERSIST_KEY', token) localStorage.setItem('TOKEN_PERSIST_KEY', token)
localStorage.setItem('persistCode', ``) localStorage.setItem('persistCode', ``)

View File

@ -1,13 +1,17 @@
import { test, expect } from './zoo-test' import { test, expect } from './zoo-test'
import { commonPoints, getUtils, } from './test-utils' import { commonPoints, getUtils } from './test-utils'
import { Coords2d } from 'lang/std/sketch' import { Coords2d } from 'lang/std/sketch'
import { KCL_DEFAULT_LENGTH } from 'lib/constants' import { KCL_DEFAULT_LENGTH } from 'lib/constants'
import { uuidv4 } from 'lib/utils' import { uuidv4 } from 'lib/utils'
test.describe('Testing selections', () => { test.describe('Testing selections', () => {
test.setTimeout(90_000) test.setTimeout(90_000)
test('Selections work on fresh and edited sketch', { tag: ['@skipWin'] }, async ({ page, homePage }) => { // Skip on windows its being weird. test(
'Selections work on fresh and edited sketch',
{ tag: ['@skipWin'] },
async ({ page, homePage }) => {
// Skip on windows its being weird.
test.skip(process.platform === 'win32', 'Skip on windows') test.skip(process.platform === 'win32', 'Skip on windows')
// tests mapping works on fresh sketch and edited sketch // tests mapping works on fresh sketch and edited sketch
@ -248,9 +252,12 @@ test.describe('Testing selections', () => {
await test.step(`Test hovering and selecting on edited sketch`, async () => { await test.step(`Test hovering and selecting on edited sketch`, async () => {
await selectionSequence() await selectionSequence()
}) }) })
}
)
test('Solids should be select and deletable', async ({ page, homePage }) => { test.setTimeout(90_000) test('Solids should be select and deletable', async ({ page, homePage }) => {
test.setTimeout(90_000)
const u = await getUtils(page) const u = await getUtils(page)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
@ -414,8 +421,13 @@ test.describe('Testing selections', () => {
await page.keyboard.press('Backspace') await page.keyboard.press('Backspace')
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000) await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
await page.waitForTimeout(200) await page.waitForTimeout(200)
await expect(u.codeLocator).not.toContainText(`sketch005 = startSketchOn({`) }) await expect(u.codeLocator).not.toContainText(`sketch005 = startSketchOn({`)
test("Deleting solid that the AST mod can't handle results in a toast message", async ({ page, homePage }) => { const u = await getUtils(page) })
test("Deleting solid that the AST mod can't handle results in a toast message", async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -474,8 +486,13 @@ test.describe('Testing selections', () => {
await u.clearCommandLogs() await u.clearCommandLogs()
await page.keyboard.press('Backspace') await page.keyboard.press('Backspace')
await expect(page.getByText('Unable to delete part')).toBeVisible() }) await expect(page.getByText('Unable to delete part')).toBeVisible()
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({ page, homePage }) => { const u = await getUtils(page) })
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => { await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -810,8 +827,13 @@ test.describe('Testing selections', () => {
adjacentChamfer2, adjacentChamfer2,
`angledLine([segAng(rectangleSegmentA001),-segLen(rectangleSegmentA001)],%,$yo)chamfer({length:30,tags:[seg01,getNextAdjacentEdge(yo),getNextAdjacentEdge(seg02),getOppositeEdge(seg01)]},%)`, `angledLine([segAng(rectangleSegmentA001),-segLen(rectangleSegmentA001)],%,$yo)chamfer({length:30,tags:[seg01,getNextAdjacentEdge(yo),getNextAdjacentEdge(seg02),getOppositeEdge(seg01)]},%)`,
'}, %)' '}, %)'
) }) )
test("Extrude button should be disabled if there's no extrudable geometry when nothing is selected", async ({ page, homePage }) => { const u = await getUtils(page) })
test("Extrude button should be disabled if there's no extrudable geometry when nothing is selected", async ({
page,
homePage,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -874,9 +896,11 @@ test.describe('Testing selections', () => {
// there's not extrudable geometry, so button should be enabled // there's not extrudable geometry, so button should be enabled
await expect( await expect(
page.getByRole('button', { name: 'Extrude' }) page.getByRole('button', { name: 'Extrude' })
).not.toBeDisabled() }) ).not.toBeDisabled()
})
test('Fillet button states test', async ({ page, homePage }) => { const u = await getUtils(page) test('Fillet button states test', async ({ page, homePage }) => {
const u = await getUtils(page)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -916,7 +940,8 @@ test.describe('Testing selections', () => {
await selectClose() await selectClose()
await expect(page.getByRole('button', { name: 'Fillet' })).toBeDisabled() await expect(page.getByRole('button', { name: 'Fillet' })).toBeDisabled()
await clickEmpty() await clickEmpty()
await expect(page.getByRole('button', { name: 'Fillet' })).toBeEnabled() }) await expect(page.getByRole('button', { name: 'Fillet' })).toBeEnabled()
})
const removeAfterFirstParenthesis = (inputString: string) => { const removeAfterFirstParenthesis = (inputString: string) => {
const index = inputString.indexOf('(') const index = inputString.indexOf('(')
@ -926,7 +951,11 @@ test.describe('Testing selections', () => {
return inputString // return the original string if '(' is not found return inputString // return the original string if '(' is not found
} }
test('Testing selections (and hovers) work on sketches when NOT in sketch mode', async ({ page, homePage }) => { const cases = [ test('Testing selections (and hovers) work on sketches when NOT in sketch mode', async ({
page,
homePage,
}) => {
const cases = [
{ {
pos: [694, 185], pos: [694, 185],
expectedCode: 'line([74.36, 130.4], %, $seg01)', expectedCode: 'line([74.36, 130.4], %, $seg01)',
@ -988,8 +1017,13 @@ test.describe('Testing selections', () => {
await expect(page.locator('.cm-activeLine')).toHaveText( await expect(page.locator('.cm-activeLine')).toHaveText(
'|> ' + expectedCode '|> ' + expectedCode
) )
} }) }
test("Hovering and selection of extruded faces works, and is not overridden shortly after user's click", async ({ page, homePage }) => { await page.addInitScript(async () => { })
test("Hovering and selection of extruded faces works, and is not overridden shortly after user's click", async ({
page,
homePage,
}) => {
await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn('XZ') `sketch001 = startSketchOn('XZ')
@ -1084,8 +1118,13 @@ test.describe('Testing selections', () => {
await expect(await u.getGreatestPixDiff(cap, selectColor)).toBeLessThan(15) await expect(await u.getGreatestPixDiff(cap, selectColor)).toBeLessThan(15)
await page.waitForTimeout(1000) await page.waitForTimeout(1000)
// check color stays there, i.e. not overridden (this was a bug previously) // check color stays there, i.e. not overridden (this was a bug previously)
await expect(await u.getGreatestPixDiff(cap, selectColor)).toBeLessThan(15) }) await expect(await u.getGreatestPixDiff(cap, selectColor)).toBeLessThan(15)
test("Various pipe expressions should and shouldn't allow edit and or extrude", async ({ page, homePage }) => { const u = await getUtils(page) })
test("Various pipe expressions should and shouldn't allow edit and or extrude", async ({
page,
homePage,
}) => {
const u = await getUtils(page)
const selectionsSnippets = { const selectionsSnippets = {
extrudeAndEditBlocked: '|> startProfileAt([10.81, 32.99], %)', extrudeAndEditBlocked: '|> startProfileAt([10.81, 32.99], %)',
extrudeAndEditBlockedInFunction: '|> startProfileAt(pos, %)', extrudeAndEditBlockedInFunction: '|> startProfileAt(pos, %)',
@ -1176,9 +1215,14 @@ test.describe('Testing selections', () => {
await expect(page.getByRole('button', { name: 'Extrude' })).toBeDisabled() await expect(page.getByRole('button', { name: 'Extrude' })).toBeDisabled()
await expect( await expect(
page.getByRole('button', { name: 'Edit Sketch' }) page.getByRole('button', { name: 'Edit Sketch' })
).not.toBeVisible() }) ).not.toBeVisible()
})
test('Deselecting line tool should mean nothing happens on click', async ({ page, homePage }) => { /** test('Deselecting line tool should mean nothing happens on click', async ({
page,
homePage,
}) => {
/**
* If the line tool is clicked when the state is 'No Points' it will exit Sketch mode. * If the line tool is clicked when the state is 'No Points' it will exit Sketch mode.
* This is the same exact workflow as pressing ESC. * This is the same exact workflow as pressing ESC.
* *
@ -1257,5 +1301,6 @@ test.describe('Testing selections', () => {
await expect(page.locator('.cm-content')).not.toHaveText( await expect(page.locator('.cm-content')).not.toHaveText(
previousCodeContent previousCodeContent
) )
previousCodeContent = await page.locator('.cm-content').innerText() }) previousCodeContent = await page.locator('.cm-content').innerText()
})
}) })

View File

@ -4,38 +4,40 @@ import { doExport, getUtils, makeTemplate } from './test-utils'
test.fixme('Units menu', async ({ page, homePage }) => { test.fixme('Units menu', async ({ page, homePage }) => {
const u = await getUtils(page) const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
const unitsMenuButton = page.getByRole('button', { const unitsMenuButton = page.getByRole('button', {
name: 'Current Units', name: 'Current Units',
exact: false, exact: false,
}) })
await expect(unitsMenuButton).toBeVisible() await expect(unitsMenuButton).toBeVisible()
await expect(unitsMenuButton).toContainText('in') await expect(unitsMenuButton).toContainText('in')
await unitsMenuButton.click() await unitsMenuButton.click()
const millimetersButton = page.getByRole('button', { name: 'Millimeters' }) const millimetersButton = page.getByRole('button', { name: 'Millimeters' })
await expect(millimetersButton).toBeVisible() await expect(millimetersButton).toBeVisible()
await millimetersButton.click() await millimetersButton.click()
// Look out for the toast message // Look out for the toast message
const toastMessage = page.getByText( const toastMessage = page.getByText(
`Set default unit to "mm" for this project` `Set default unit to "mm" for this project`
) )
await expect(toastMessage).toBeVisible() await expect(toastMessage).toBeVisible()
// Verify that the popover has closed // Verify that the popover has closed
await expect(millimetersButton).not.toBeAttached() await expect(millimetersButton).not.toBeAttached()
// Verify that the button label has updated // Verify that the button label has updated
await expect(unitsMenuButton).toContainText('mm') }) await expect(unitsMenuButton).toContainText('mm')
})
test('Successful export shows a success toast', async ({ page, homePage }) => { // FYI this test doesn't work with only engine running locally test('Successful export shows a success toast', async ({ page, homePage }) => {
// And you will need to have the KittyCAD CLI installed // FYI this test doesn't work with only engine running locally
const u = await getUtils(page) // And you will need to have the KittyCAD CLI installed
await page.addInitScript(async () => { const u = await getUtils(page)
await page.addInitScript(async () => {
;(window as any).playwrightSkipFilePicker = true ;(window as any).playwrightSkipFilePicker = true
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
@ -78,157 +80,171 @@ part001 = startSketchOn('-XZ')
|> close(%) |> close(%)
|> extrude(4, %)` |> extrude(4, %)`
) )
}) })
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await u.openDebugPanel() await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.waitForCmdReceive('extrude') await u.waitForCmdReceive('extrude')
await page.waitForTimeout(1000) await page.waitForTimeout(1000)
await u.clearAndCloseDebugPanel() await u.clearAndCloseDebugPanel()
await doExport( await doExport(
{ {
type: 'gltf', type: 'gltf',
storage: 'embedded', storage: 'embedded',
presentation: 'pretty', presentation: 'pretty',
}, },
page page
) )
}) })
test('Paste should not work unless an input is focused', async ({ page, browserName, homePage }) => { // To run this test locally, uncomment Firefox in playwright.config.ts test('Paste should not work unless an input is focused', async ({
test.skip( page,
browserName,
homePage,
}) => {
// To run this test locally, uncomment Firefox in playwright.config.ts
test.skip(
browserName !== 'firefox', browserName !== 'firefox',
"This bug is really Firefox-only, which we don't run in CI." "This bug is really Firefox-only, which we don't run in CI."
) )
const u = await getUtils(page) const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await page await page
.getByRole('button', { name: 'Start Sketch' }) .getByRole('button', { name: 'Start Sketch' })
.waitFor({ state: 'visible' }) .waitFor({ state: 'visible' })
const codeEditorText = page.locator('.cm-content') const codeEditorText = page.locator('.cm-content')
const pasteContent = `// was this pasted?` const pasteContent = `// was this pasted?`
const typeContent = `// this should be typed` const typeContent = `// this should be typed`
// Load text into the clipboard // Load text into the clipboard
await page.evaluate((t) => navigator.clipboard.writeText(t), pasteContent) await page.evaluate((t) => navigator.clipboard.writeText(t), pasteContent)
// Focus the text editor // Focus the text editor
await codeEditorText.focus() await codeEditorText.focus()
// Show that we can type into it // Show that we can type into it
await page.keyboard.type(typeContent) await page.keyboard.type(typeContent)
await page.keyboard.press('Enter') await page.keyboard.press('Enter')
// Paste without the code pane focused // Paste without the code pane focused
await codeEditorText.blur() await codeEditorText.blur()
await page.keyboard.press('ControlOrMeta+KeyV') await page.keyboard.press('ControlOrMeta+KeyV')
// Show that the paste didn't work but typing did // Show that the paste didn't work but typing did
await expect(codeEditorText).not.toContainText(pasteContent) await expect(codeEditorText).not.toContainText(pasteContent)
await expect(codeEditorText).toContainText(typeContent) await expect(codeEditorText).toContainText(typeContent)
// Paste with the code editor focused // Paste with the code editor focused
// Following this guidance: https://github.com/microsoft/playwright/issues/8114 // Following this guidance: https://github.com/microsoft/playwright/issues/8114
await codeEditorText.focus() await codeEditorText.focus()
await page.keyboard.press('ControlOrMeta+KeyV') await page.keyboard.press('ControlOrMeta+KeyV')
await expect( await expect(
await page.evaluate( await page.evaluate(
() => document.querySelector('.cm-content')?.textContent () => document.querySelector('.cm-content')?.textContent
) )
).toContain(pasteContent) }) ).toContain(pasteContent)
})
test('Keyboard shortcuts can be viewed through the help menu', async ({ page, homePage }) => { const u = await getUtils(page) test('Keyboard shortcuts can be viewed through the help menu', async ({
await page.setBodyDimensions({ width: 1200, height: 500 }) page,
await homePage.goToModelingScene() homePage,
}) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await page.waitForURL('file:///**', { waitUntil: 'domcontentloaded' }) await page.waitForURL('file:///**', { waitUntil: 'domcontentloaded' })
await page await page
.getByRole('button', { name: 'Start Sketch' }) .getByRole('button', { name: 'Start Sketch' })
.waitFor({ state: 'visible' }) .waitFor({ state: 'visible' })
// Open the help menu // Open the help menu
await page.getByRole('button', { name: 'Help and resources' }).click() await page.getByRole('button', { name: 'Help and resources' }).click()
// Open the keyboard shortcuts // Open the keyboard shortcuts
await page.getByRole('button', { name: 'Keyboard Shortcuts' }).click() await page.getByRole('button', { name: 'Keyboard Shortcuts' }).click()
// Verify the URL and that you can see a list of shortcuts // Verify the URL and that you can see a list of shortcuts
await expect.poll(() => page.url()).toContain('?tab=keybindings') await expect.poll(() => page.url()).toContain('?tab=keybindings')
await expect( await expect(
page.getByRole('heading', { name: 'Enter Sketch Mode' }) page.getByRole('heading', { name: 'Enter Sketch Mode' })
).toBeAttached() ).toBeAttached()
}) })
test('First escape in tool pops you out of tool, second exits sketch mode', async ({ page, homePage }) => { // Wait for the app to be ready for use test('First escape in tool pops you out of tool, second exits sketch mode', async ({
const u = await getUtils(page) page,
await page.setBodyDimensions({ width: 1200, height: 500 }) homePage,
}) => {
// Wait for the app to be ready for use
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
await u.openDebugPanel() await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel() await u.closeDebugPanel()
const lineButton = page.getByRole('button', { const lineButton = page.getByRole('button', {
name: 'line Line', name: 'line Line',
exact: true, exact: true,
}) })
const arcButton = page.getByRole('button', { const arcButton = page.getByRole('button', {
name: 'arc Tangential Arc', name: 'arc Tangential Arc',
exact: true, exact: true,
}) })
// Test these hotkeys perform actions when // Test these hotkeys perform actions when
// focus is on the canvas // focus is on the canvas
await page.mouse.move(600, 250) await page.mouse.move(600, 250)
await page.mouse.click(600, 250) await page.mouse.click(600, 250)
// Start a sketch // Start a sketch
await page.keyboard.press('s') await page.keyboard.press('s')
await page.mouse.move(800, 300) await page.mouse.move(800, 300)
await page.mouse.click(800, 300) await page.mouse.click(800, 300)
await page.waitForTimeout(1000) await page.waitForTimeout(1000)
await expect(lineButton).toBeVisible() await expect(lineButton).toBeVisible()
await expect(lineButton).toHaveAttribute('aria-pressed', 'true') await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
// Draw a line // Draw a line
await page.mouse.move(700, 200, { steps: 5 }) await page.mouse.move(700, 200, { steps: 5 })
await page.mouse.click(700, 200) await page.mouse.click(700, 200)
await page.mouse.move(800, 250, { steps: 5 }) await page.mouse.move(800, 250, { steps: 5 })
await page.mouse.click(800, 250) await page.mouse.click(800, 250)
// Unequip line tool // Unequip line tool
await page.keyboard.press('Escape') await page.keyboard.press('Escape')
// Make sure we didn't pop out of sketch mode. // 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: 'Exit Sketch' })).toBeVisible()
await expect(lineButton).not.toHaveAttribute('aria-pressed', 'true') await expect(lineButton).not.toHaveAttribute('aria-pressed', 'true')
// Equip arc tool // Equip arc tool
await page.keyboard.press('a') await page.keyboard.press('a')
await expect(arcButton).toHaveAttribute('aria-pressed', 'true') await expect(arcButton).toHaveAttribute('aria-pressed', 'true')
await page.mouse.move(1000, 100, { steps: 5 }) await page.mouse.move(1000, 100, { steps: 5 })
await page.mouse.click(1000, 100) await page.mouse.click(1000, 100)
await page.keyboard.press('Escape') await page.keyboard.press('Escape')
await page.keyboard.press('l') await page.keyboard.press('l')
await expect(lineButton).toHaveAttribute('aria-pressed', 'true') await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
// Do not close the sketch. // Do not close the sketch.
// On close it will exit sketch mode. // On close it will exit sketch mode.
// Unequip line tool // Unequip line tool
await page.keyboard.press('Escape') await page.keyboard.press('Escape')
await expect(lineButton).toHaveAttribute('aria-pressed', 'false') await expect(lineButton).toHaveAttribute('aria-pressed', 'false')
await expect(arcButton).toHaveAttribute('aria-pressed', 'false') await expect(arcButton).toHaveAttribute('aria-pressed', 'false')
// Make sure we didn't pop out of sketch mode. // 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: 'Exit Sketch' })).toBeVisible()
// Exit sketch // Exit sketch
await page.keyboard.press('Escape') await page.keyboard.press('Escape')
await expect( await expect(
page.getByRole('button', { name: 'Exit Sketch' }) page.getByRole('button', { name: 'Exit Sketch' })
).not.toBeVisible() }) ).not.toBeVisible()
})
test.fixme( test.fixme(
'Basic default modeling and sketch hotkeys work', 'Basic default modeling and sketch hotkeys work',
@ -412,34 +428,35 @@ test.fixme(
) )
test('Delete key does not navigate back', async ({ page, homePage }) => { test('Delete key does not navigate back', async ({ page, homePage }) => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.waitForURL('file:///**', { waitUntil: 'domcontentloaded' })
await homePage.goToModelingScene();
await page.waitForURL('file:///**', { waitUntil: 'domcontentloaded' }) const settingsButton = page.getByRole('link', {
const settingsButton = page.getByRole('link', {
name: 'Settings', name: 'Settings',
exact: false, exact: false,
})
const settingsCloseButton = page.getByTestId('settings-close-button')
await settingsButton.click()
await expect.poll(() => page.url()).toContain('/settings')
// Make sure that delete doesn't go back from settings
await page.keyboard.press('Delete')
await expect.poll(() => page.url()).toContain('/settings')
// Now close the settings and try delete again,
// make sure it doesn't go back to settings
await settingsCloseButton.click()
await page.keyboard.press('Delete')
await expect.poll(() => page.url()).not.toContain('/settings')
}) })
const settingsCloseButton = page.getByTestId('settings-close-button')
await settingsButton.click() test('Sketch on face', async ({ page, homePage }) => {
await expect.poll(() => page.url()).toContain('/settings') test.setTimeout(90_000)
const u = await getUtils(page)
// Make sure that delete doesn't go back from settings await page.addInitScript(async () => {
await page.keyboard.press('Delete')
await expect.poll(() => page.url()).toContain('/settings')
// Now close the settings and try delete again,
// make sure it doesn't go back to settings
await settingsCloseButton.click()
await page.keyboard.press('Delete')
await expect.poll(() => page.url()).not.toContain('/settings') })
test('Sketch on face', async ({ page, homePage }) => { test.setTimeout(90_000)
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`sketch001 = startSketchOn('XZ') `sketch001 = startSketchOn('XZ')
@ -457,59 +474,59 @@ await page.addInitScript(async () => {
|> close(%) |> close(%)
extrude001 = extrude(5 + 7, sketch001)` extrude001 = extrude(5 + 7, sketch001)`
) )
}) })
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
// wait for execution done // wait for execution done
await u.openDebugPanel() await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel() await u.closeDebugPanel()
await expect( await expect(
page.getByRole('button', { name: 'Start Sketch' }) page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled() ).not.toBeDisabled()
await page.getByRole('button', { name: 'Start Sketch' }).click() await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(300) await page.waitForTimeout(300)
let previousCodeContent = await page.locator('.cm-content').innerText() let previousCodeContent = await page.locator('.cm-content').innerText()
await u.openAndClearDebugPanel() await u.openAndClearDebugPanel()
await u.doAndWaitForCmd( await u.doAndWaitForCmd(
() => page.mouse.click(625, 165), () => page.mouse.click(625, 165),
'default_camera_get_settings', 'default_camera_get_settings',
true true
) )
await page.waitForTimeout(150) await page.waitForTimeout(150)
await u.closeDebugPanel() await u.closeDebugPanel()
const firstClickPosition = [612, 238] const firstClickPosition = [612, 238]
const secondClickPosition = [661, 242] const secondClickPosition = [661, 242]
const thirdClickPosition = [609, 267] const thirdClickPosition = [609, 267]
await page.mouse.click(firstClickPosition[0], firstClickPosition[1]) await page.mouse.click(firstClickPosition[0], firstClickPosition[1])
await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent) await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent)
previousCodeContent = await page.locator('.cm-content').innerText() previousCodeContent = await page.locator('.cm-content').innerText()
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(secondClickPosition[0], secondClickPosition[1]) await page.mouse.click(secondClickPosition[0], secondClickPosition[1])
await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent) await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent)
previousCodeContent = await page.locator('.cm-content').innerText() previousCodeContent = await page.locator('.cm-content').innerText()
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(thirdClickPosition[0], thirdClickPosition[1]) await page.mouse.click(thirdClickPosition[0], thirdClickPosition[1])
await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent) await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent)
previousCodeContent = await page.locator('.cm-content').innerText() previousCodeContent = await page.locator('.cm-content').innerText()
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(firstClickPosition[0], firstClickPosition[1]) await page.mouse.click(firstClickPosition[0], firstClickPosition[1])
await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent) await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent)
previousCodeContent = await page.locator('.cm-content').innerText() previousCodeContent = await page.locator('.cm-content').innerText()
await expect.poll(u.normalisedEditorCode).toContain( await expect.poll(u.normalisedEditorCode).toContain(
u.normalisedCode(`sketch002 = startSketchOn(extrude001, seg01) u.normalisedCode(`sketch002 = startSketchOn(extrude001, seg01)
|> startProfileAt([-12.94, 6.6], %) |> startProfileAt([-12.94, 6.6], %)
|> line([2.45, -0.2], %) |> line([2.45, -0.2], %)
@ -517,65 +534,66 @@ await expect.poll(u.normalisedEditorCode).toContain(
|> lineTo([profileStartX(%), profileStartY(%)], %) |> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%) |> close(%)
`) `)
) )
await u.openAndClearDebugPanel() await u.openAndClearDebugPanel()
await page.getByRole('button', { name: 'Exit Sketch' }).click() await page.getByRole('button', { name: 'Exit Sketch' }).click()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.updateCamPosition([1049, 239, 686]) await u.updateCamPosition([1049, 239, 686])
await u.closeDebugPanel() await u.closeDebugPanel()
await page.getByText('startProfileAt([-12').click() await page.getByText('startProfileAt([-12').click()
await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeVisible() await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeVisible()
await page.getByRole('button', { name: 'Edit Sketch' }).click() await page.getByRole('button', { name: 'Edit Sketch' }).click()
await page.waitForTimeout(400) await page.waitForTimeout(400)
await page.waitForTimeout(150) await page.waitForTimeout(150)
await page.setBodyDimensions({ width: 1200, height: 1200 }) await page.setBodyDimensions({ width: 1200, height: 1200 })
await u.openAndClearDebugPanel() await u.openAndClearDebugPanel()
await u.updateCamPosition([452, -152, 1166]) await u.updateCamPosition([452, -152, 1166])
await u.closeDebugPanel() await u.closeDebugPanel()
await page.waitForTimeout(200) await page.waitForTimeout(200)
const pointToDragFirst = [787, 565] const pointToDragFirst = [787, 565]
await page.mouse.move(pointToDragFirst[0], pointToDragFirst[1]) await page.mouse.move(pointToDragFirst[0], pointToDragFirst[1])
await page.mouse.down() await page.mouse.down()
await page.mouse.move(pointToDragFirst[0] - 20, pointToDragFirst[1], { await page.mouse.move(pointToDragFirst[0] - 20, pointToDragFirst[1], {
steps: 5, steps: 5,
}) })
await page.mouse.up() await page.mouse.up()
await page.waitForTimeout(100) await page.waitForTimeout(100)
await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent) await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent)
previousCodeContent = await page.locator('.cm-content').innerText() previousCodeContent = await page.locator('.cm-content').innerText()
const result = makeTemplate`sketch002 = startSketchOn(extrude001, seg01) const result = makeTemplate`sketch002 = startSketchOn(extrude001, seg01)
|> startProfileAt([-12.83, 6.7], %) |> startProfileAt([-12.83, 6.7], %)
|> line([${[2.28, 2.35]}, -${0.07}], %) |> line([${[2.28, 2.35]}, -${0.07}], %)
|> line([-3.05, -1.47], %) |> line([-3.05, -1.47], %)
|> lineTo([profileStartX(%), profileStartY(%)], %) |> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)` |> close(%)`
await expect(page.locator('.cm-content')).toHaveText(result.regExp) await expect(page.locator('.cm-content')).toHaveText(result.regExp)
// exit sketch // exit sketch
await u.openAndClearDebugPanel() await u.openAndClearDebugPanel()
await page.getByRole('button', { name: 'Exit Sketch' }).click() await page.getByRole('button', { name: 'Exit Sketch' }).click()
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await page.getByText('startProfileAt([-12').click() await page.getByText('startProfileAt([-12').click()
await expect(page.getByRole('button', { name: 'Extrude' })).not.toBeDisabled() await expect(page.getByRole('button', { name: 'Extrude' })).not.toBeDisabled()
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.getByRole('button', { name: 'Extrude' }).click() await page.getByRole('button', { name: 'Extrude' }).click()
await expect(page.getByTestId('command-bar')).toBeVisible() await expect(page.getByTestId('command-bar')).toBeVisible()
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.getByRole('button', { name: 'arrow right Continue' }).click() await page.getByRole('button', { name: 'arrow right Continue' }).click()
await page.waitForTimeout(100) await page.waitForTimeout(100)
await expect(page.getByText('Confirm Extrude')).toBeVisible() await expect(page.getByText('Confirm Extrude')).toBeVisible()
await page.getByRole('button', { name: 'checkmark Submit command' }).click() await page.getByRole('button', { name: 'checkmark Submit command' }).click()
const result2 = result.genNext` const result2 = result.genNext`
const sketch002 = extrude(${[5, 5]} + 7, sketch002)` const sketch002 = extrude(${[5, 5]} + 7, sketch002)`
await expect(page.locator('.cm-content')).toHaveText(result2.regExp) }) await expect(page.locator('.cm-content')).toHaveText(result2.regExp)
})

View File

@ -10,7 +10,6 @@ export { expect, Page, BrowserContext, TestInfo } from '@playwright/test'
// switch between web and electron if needed. // switch between web and electron if needed.
const pwTestFnWithFixtures = playwrightTestFn.extend<Fixtures>(fixtures) const pwTestFnWithFixtures = playwrightTestFn.extend<Fixtures>(fixtures)
// In JavaScript you cannot replace a function's body only (despite functions // In JavaScript you cannot replace a function's body only (despite functions
// are themselves objects, which you'd expect a body property or something...) // are themselves objects, which you'd expect a body property or something...)
// So we must redefine the function and then re-attach properties. // So we must redefine the function and then re-attach properties.
@ -61,7 +60,7 @@ export function test(desc, objOrFn, fnMaybe) {
// We need to expose this in order for some tests that require folder // We need to expose this in order for some tests that require folder
// creation. Before they used to do this by their own electronSetup({...}) // creation. Before they used to do this by their own electronSetup({...})
// calls. // calls.
tronApp.context.folderSetupFn = function(fn) { tronApp.context.folderSetupFn = function (fn) {
return fn(tronApp.dir).then(() => ({ dir: tronApp.dir })) return fn(tronApp.dir).then(() => ({ dir: tronApp.dir }))
} }

View File

@ -20,7 +20,7 @@ const save_ = async (file: ModelingAppFile, toastId: string) => {
// Skip file picker, save to the test dir downloads directory // Skip file picker, save to the test dir downloads directory
const downloadDir = window.electron.join( const downloadDir = window.electron.join(
window.electron.process.env.TEST_SETTINGS_FILE_KEY, window.electron.process.env.TEST_SETTINGS_FILE_KEY,
"downloads-during-playwright", 'downloads-during-playwright'
) )
await window.electron.mkdir(downloadDir, { recursive: true }) await window.electron.mkdir(downloadDir, { recursive: true })
await window.electron.writeFile( await window.electron.writeFile(