* chore: saving off package.json progress unit tests fail in main * fix: implementing a one liner for unit tests * fix: renaming test:unit:local * chore: adding playwright tests * fix: making package.json not destructive to keep same pipeline commands for now * fix: reordering * fix: added tags for OS tests, moved kill-port to dev depen * fix: OS skipping at tag level * fix: lint, fmt, tsc, etc... * Look at this (photo)Graph *in the voice of Nickelback* * fix: new formatting * fix: removing the ci copy, do not like it * Look at this (photo)Graph *in the voice of Nickelback* * chore: updating readme with explanation on the commands for CI CD simulation locally * fix: package.json command for unit test, removing cached breaking cache in unit tests * fix: fixing copy and typos in README.md for CI CD section * fix: adding a duplicate command for a better name. CI CD will use it in a future PR * chore: trying to clean up the copy and commands for CI CD tests * chore: porting the bash code in the YAML to a bash script then using matrix permutations to control the runtime * fix: typos * fix: another typo, missed these went porting to the bash script logic * fix: I think I need the checkout action since it has the repo code? * fix: wrote absolute path not the relative hidden path, ope * fix: does this cache give me the yarn install of playwright? * fix: yarn cannot find the binary, use the yarn command * fix: remove all uses...? * chore: adding bash script for electron runtimes * fix: copy cleanup * fix: typo when copy and pasting the exclude logic, ope * fix: this is wrong * fix: build:wasm is a requirement for yarn tsc * fix: reorder? * fix: renaming integrations to e2e * fix: windows is complaining about a pipe issue in the bash script? * fix: escaping double quotes in windows? * chore: consolidating commands into 1 file and easier YAML configuation for electron * chore: mapped multiple OS playwright browser into a single bash script * fix: removing old bash scripts, renaming matrix jobs * fix: missed deleting this when I added the if statements. * chore: removing unused job, xstate typegen more more since v5 * fix: trying to get these two tests to pass on first try * fix: auto fixes * fix: removing old unit test command --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
		
			
				
	
	
		
			603 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			603 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { test, expect } from '@playwright/test'
 | |
| 
 | |
| import { doExport, getUtils, makeTemplate, setup, tearDown } from './test-utils'
 | |
| 
 | |
| test.beforeEach(async ({ context, page }, testInfo) => {
 | |
|   await setup(context, page, testInfo)
 | |
| })
 | |
| 
 | |
| test.afterEach(async ({ page }, testInfo) => {
 | |
|   await tearDown(page, testInfo)
 | |
| })
 | |
| 
 | |
| test('Units menu', async ({ page }) => {
 | |
|   const u = await getUtils(page)
 | |
|   await page.setViewportSize({ width: 1200, height: 500 })
 | |
|   await u.waitForAuthSkipAppStart()
 | |
| 
 | |
|   const unitsMenuButton = page.getByRole('button', {
 | |
|     name: 'Current Units',
 | |
|     exact: false,
 | |
|   })
 | |
|   await expect(unitsMenuButton).toBeVisible()
 | |
|   await expect(unitsMenuButton).toContainText('in')
 | |
| 
 | |
|   await unitsMenuButton.click()
 | |
|   const millimetersButton = page.getByRole('button', { name: 'Millimeters' })
 | |
| 
 | |
|   await expect(millimetersButton).toBeVisible()
 | |
|   await millimetersButton.click()
 | |
| 
 | |
|   // Look out for the toast message
 | |
|   const toastMessage = page.getByText(
 | |
|     `Set default unit to "mm" for this project`
 | |
|   )
 | |
|   await expect(toastMessage).toBeVisible()
 | |
| 
 | |
|   // Verify that the popover has closed
 | |
|   await expect(millimetersButton).not.toBeAttached()
 | |
| 
 | |
|   // Verify that the button label has updated
 | |
|   await expect(unitsMenuButton).toContainText('mm')
 | |
| })
 | |
| 
 | |
| test('Successful export shows a success toast', async ({ page }) => {
 | |
|   // FYI this test doesn't work with only engine running locally
 | |
|   // And you will need to have the KittyCAD CLI installed
 | |
|   const u = await getUtils(page)
 | |
|   await page.addInitScript(async () => {
 | |
|     ;(window as any).playwrightSkipFilePicker = true
 | |
|     localStorage.setItem(
 | |
|       'persistCode',
 | |
|       `topAng = 25
 | |
| bottomAng = 35
 | |
| baseLen = 3.5
 | |
| baseHeight = 1
 | |
| totalHeightHalf = 2
 | |
| armThick = 0.5
 | |
| totalLen = 9.5
 | |
| part001 = startSketchOn('-XZ')
 | |
|   |> startProfileAt([0, 0], %)
 | |
|   |> yLine(baseHeight, %)
 | |
|   |> xLine(baseLen, %)
 | |
|   |> angledLineToY({
 | |
|         angle: topAng,
 | |
|         to: totalHeightHalf,
 | |
|       }, %, $seg04)
 | |
|   |> xLineTo(totalLen, %, $seg03)
 | |
|   |> yLine(-armThick, %, $seg01)
 | |
|   |> angledLineThatIntersects({
 | |
|         angle: HALF_TURN,
 | |
|         offset: -armThick,
 | |
|         intersectTag: seg04
 | |
|       }, %)
 | |
|   |> angledLineToY([segAng(seg04) + 180, ZERO], %)
 | |
|   |> angledLineToY({
 | |
|         angle: -bottomAng,
 | |
|         to: -totalHeightHalf - armThick,
 | |
|       }, %, $seg02)
 | |
|   |> xLineTo(segEndX(seg03) + 0, %)
 | |
|   |> yLine(-segLen(seg01), %)
 | |
|   |> angledLineThatIntersects({
 | |
|         angle: HALF_TURN,
 | |
|         offset: -armThick,
 | |
|         intersectTag: seg02
 | |
|       }, %)
 | |
|   |> angledLineToY([segAng(seg02) + 180, -baseHeight], %)
 | |
|   |> xLineTo(ZERO, %)
 | |
|   |> close(%)
 | |
|   |> extrude(4, %)`
 | |
|     )
 | |
|   })
 | |
|   await page.setViewportSize({ width: 1200, height: 500 })
 | |
| 
 | |
|   await u.waitForAuthSkipAppStart()
 | |
|   await u.openDebugPanel()
 | |
|   await u.expectCmdLog('[data-message-type="execution-done"]')
 | |
|   await u.waitForCmdReceive('extrude')
 | |
|   await page.waitForTimeout(1000)
 | |
|   await u.clearAndCloseDebugPanel()
 | |
| 
 | |
|   await doExport(
 | |
|     {
 | |
|       type: 'gltf',
 | |
|       storage: 'embedded',
 | |
|       presentation: 'pretty',
 | |
|     },
 | |
|     page
 | |
|   )
 | |
| 
 | |
|   // This is the main thing we're testing,
 | |
|   // We test the export functionality across all
 | |
|   // file types in snapshot-tests.spec.ts
 | |
|   await expect(page.getByText('Exported successfully')).toBeVisible()
 | |
| })
 | |
| 
 | |
| test('Paste should not work unless an input is focused', async ({
 | |
|   page,
 | |
|   browserName,
 | |
| }) => {
 | |
|   // To run this test locally, uncomment Firefox in playwright.config.ts
 | |
|   test.skip(
 | |
|     browserName !== 'firefox',
 | |
|     "This bug is really Firefox-only, which we don't run in CI."
 | |
|   )
 | |
|   const u = await getUtils(page)
 | |
|   await page.setViewportSize({ width: 1200, height: 500 })
 | |
|   await u.waitForAuthSkipAppStart()
 | |
|   await page
 | |
|     .getByRole('button', { name: 'Start Sketch' })
 | |
|     .waitFor({ state: 'visible' })
 | |
| 
 | |
|   const codeEditorText = page.locator('.cm-content')
 | |
|   const pasteContent = `// was this pasted?`
 | |
|   const typeContent = `// this should be typed`
 | |
| 
 | |
|   // Load text into the clipboard
 | |
|   await page.evaluate((t) => navigator.clipboard.writeText(t), pasteContent)
 | |
| 
 | |
|   // Focus the text editor
 | |
|   await codeEditorText.focus()
 | |
| 
 | |
|   // Show that we can type into it
 | |
|   await page.keyboard.type(typeContent)
 | |
|   await page.keyboard.press('Enter')
 | |
| 
 | |
|   // Paste without the code pane focused
 | |
|   await codeEditorText.blur()
 | |
|   await page.keyboard.press('ControlOrMeta+KeyV')
 | |
| 
 | |
|   // Show that the paste didn't work but typing did
 | |
|   await expect(codeEditorText).not.toContainText(pasteContent)
 | |
|   await expect(codeEditorText).toContainText(typeContent)
 | |
| 
 | |
|   // Paste with the code editor focused
 | |
|   // Following this guidance: https://github.com/microsoft/playwright/issues/8114
 | |
|   await codeEditorText.focus()
 | |
|   await page.keyboard.press('ControlOrMeta+KeyV')
 | |
|   await expect(
 | |
|     await page.evaluate(
 | |
|       () => document.querySelector('.cm-content')?.textContent
 | |
|     )
 | |
|   ).toContain(pasteContent)
 | |
| })
 | |
| 
 | |
| test('Keyboard shortcuts can be viewed through the help menu', async ({
 | |
|   page,
 | |
| }) => {
 | |
|   const u = await getUtils(page)
 | |
|   await page.setViewportSize({ width: 1200, height: 500 })
 | |
|   await u.waitForAuthSkipAppStart()
 | |
| 
 | |
|   await page.waitForURL('**/file/**', { waitUntil: 'domcontentloaded' })
 | |
|   await page
 | |
|     .getByRole('button', { name: 'Start Sketch' })
 | |
|     .waitFor({ state: 'visible' })
 | |
| 
 | |
|   // Open the help menu
 | |
|   await page.getByRole('button', { name: 'Help and resources' }).click()
 | |
| 
 | |
|   // Open the keyboard shortcuts
 | |
|   await page.getByRole('button', { name: 'Keyboard Shortcuts' }).click()
 | |
| 
 | |
|   // Verify the URL and that you can see a list of shortcuts
 | |
|   await expect(page.url()).toContain('?tab=keybindings')
 | |
|   await expect(
 | |
|     page.getByRole('heading', { name: 'Enter Sketch Mode' })
 | |
|   ).toBeAttached()
 | |
| })
 | |
| 
 | |
| test('First escape in tool pops you out of tool, second exits sketch mode', async ({
 | |
|   page,
 | |
| }) => {
 | |
|   // Wait for the app to be ready for use
 | |
|   const u = await getUtils(page)
 | |
|   await page.setViewportSize({ width: 1200, height: 500 })
 | |
| 
 | |
|   await u.waitForAuthSkipAppStart()
 | |
|   await u.openDebugPanel()
 | |
|   await u.expectCmdLog('[data-message-type="execution-done"]')
 | |
|   await u.closeDebugPanel()
 | |
| 
 | |
|   const lineButton = page.getByRole('button', {
 | |
|     name: 'line Line',
 | |
|     exact: true,
 | |
|   })
 | |
|   const arcButton = page.getByRole('button', {
 | |
|     name: 'arc Tangential Arc',
 | |
|     exact: true,
 | |
|   })
 | |
| 
 | |
|   // Test these hotkeys perform actions when
 | |
|   // focus is on the canvas
 | |
|   await page.mouse.move(600, 250)
 | |
|   await page.mouse.click(600, 250)
 | |
| 
 | |
|   // Start a sketch
 | |
|   await page.keyboard.press('s')
 | |
|   await page.mouse.move(800, 300)
 | |
|   await page.mouse.click(800, 300)
 | |
|   await page.waitForTimeout(1000)
 | |
|   await expect(lineButton).toBeVisible()
 | |
|   await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
 | |
| 
 | |
|   // Draw a line
 | |
|   await page.mouse.move(700, 200, { steps: 5 })
 | |
|   await page.mouse.click(700, 200)
 | |
|   await page.mouse.move(800, 250, { steps: 5 })
 | |
|   await page.mouse.click(800, 250)
 | |
|   // Unequip line tool
 | |
|   await page.keyboard.press('Escape')
 | |
|   // Make sure we didn't pop out of sketch mode.
 | |
|   await expect(page.getByRole('button', { name: 'Exit Sketch' })).toBeVisible()
 | |
|   await expect(lineButton).not.toHaveAttribute('aria-pressed', 'true')
 | |
|   // Equip arc tool
 | |
|   await page.keyboard.press('a')
 | |
|   await expect(arcButton).toHaveAttribute('aria-pressed', 'true')
 | |
|   await page.mouse.move(1000, 100, { steps: 5 })
 | |
|   await page.mouse.click(1000, 100)
 | |
|   await page.keyboard.press('Escape')
 | |
|   await page.keyboard.press('l')
 | |
|   await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
 | |
| 
 | |
|   // Do not close the sketch.
 | |
|   // On close it will exit sketch mode.
 | |
| 
 | |
|   // Unequip line tool
 | |
|   await page.keyboard.press('Escape')
 | |
|   await expect(lineButton).toHaveAttribute('aria-pressed', 'false')
 | |
|   await expect(arcButton).toHaveAttribute('aria-pressed', 'false')
 | |
|   // Make sure we didn't pop out of sketch mode.
 | |
|   await expect(page.getByRole('button', { name: 'Exit Sketch' })).toBeVisible()
 | |
|   // Exit sketch
 | |
|   await page.keyboard.press('Escape')
 | |
|   await expect(
 | |
|     page.getByRole('button', { name: 'Exit Sketch' })
 | |
|   ).not.toBeVisible()
 | |
| })
 | |
| 
 | |
| test('Basic default modeling and sketch hotkeys work', async ({ page }) => {
 | |
|   const u = await getUtils(page)
 | |
| 
 | |
|   // This test can run long if it takes a little too long to load
 | |
|   // the engine.
 | |
|   test.setTimeout(90000)
 | |
|   // This test has a weird bug on ubuntu
 | |
|   test.skip(
 | |
|     process.platform === 'linux',
 | |
|     'weird playwright bug on ubuntu https://github.com/KittyCAD/modeling-app/issues/2444'
 | |
|   )
 | |
|   // Load the app with the code pane open
 | |
| 
 | |
|   await test.step(`Set up test`, async () => {
 | |
|     await page.addInitScript(async () => {
 | |
|       localStorage.setItem(
 | |
|         'store',
 | |
|         JSON.stringify({
 | |
|           state: {
 | |
|             openPanes: ['code'],
 | |
|           },
 | |
|           version: 0,
 | |
|         })
 | |
|       )
 | |
|     })
 | |
|     await page.setViewportSize({ width: 1200, height: 500 })
 | |
|     await u.waitForAuthSkipAppStart()
 | |
|     await u.openDebugPanel()
 | |
|     await u.expectCmdLog('[data-message-type="execution-done"]')
 | |
|     await u.closeDebugPanel()
 | |
|   })
 | |
| 
 | |
|   const codePane = page.locator('.cm-content')
 | |
|   const lineButton = page.getByRole('button', {
 | |
|     name: 'line Line',
 | |
|     exact: true,
 | |
|   })
 | |
|   const arcButton = page.getByRole('button', {
 | |
|     name: 'arc Tangential Arc',
 | |
|     exact: true,
 | |
|   })
 | |
|   const extrudeButton = page.getByRole('button', { name: 'Extrude' })
 | |
|   const commandBarComboBox = page.getByPlaceholder('Search commands')
 | |
|   const exitSketchButton = page.getByRole('button', { name: 'Exit Sketch' })
 | |
| 
 | |
|   await test.step(`Type code with modeling hotkeys, shouldn't fire`, async () => {
 | |
|     await codePane.click()
 | |
|     await page.keyboard.type('//')
 | |
|     await page.keyboard.press('s')
 | |
|     await expect(commandBarComboBox).not.toBeVisible()
 | |
|     await page.keyboard.press('e')
 | |
|     await expect(commandBarComboBox).not.toBeVisible()
 | |
|     await expect(codePane).toHaveText('//se')
 | |
|   })
 | |
| 
 | |
|   // Blur focus from the code editor, use the s command to sketch
 | |
|   await test.step(`Blur editor focus, enter sketch`, async () => {
 | |
|     /**
 | |
|      * TODO: There is a bug somewhere that causes this test to fail
 | |
|      * if you toggle the codePane closed before your trigger the
 | |
|      * start of the sketch.
 | |
|      * and a separate Safari-only bug that causes the test to fail
 | |
|      * if the pane is open the entire test. The maintainer of CodeMirror
 | |
|      * has pinpointed this to the unusual browser behavior:
 | |
|      * https://discuss.codemirror.net/t/how-to-force-unfocus-of-the-codemirror-element-in-safari/8095/3
 | |
|      */
 | |
|     await blurCodeEditor()
 | |
|     await page.waitForTimeout(1000)
 | |
|     await page.keyboard.press('s')
 | |
|     await page.waitForTimeout(1000)
 | |
|     await page.mouse.move(800, 300, { steps: 5 })
 | |
|     await page.mouse.click(800, 300)
 | |
|     await page.waitForTimeout(1000)
 | |
|     await expect(lineButton).toHaveAttribute('aria-pressed', 'true', {
 | |
|       timeout: 15_000,
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   // Use some sketch hotkeys to create a sketch (l and a for now)
 | |
|   await test.step(`Incomplete sketch with hotkeys`, async () => {
 | |
|     await test.step(`Draw a line`, async () => {
 | |
|       await page.mouse.move(700, 200, { steps: 5 })
 | |
|       await page.mouse.click(700, 200)
 | |
|       await page.mouse.move(800, 250, { steps: 5 })
 | |
|       await page.mouse.click(800, 250)
 | |
|     })
 | |
| 
 | |
|     await test.step(`Unequip line tool`, async () => {
 | |
|       await page.keyboard.press('l')
 | |
|       await expect(lineButton).not.toHaveAttribute('aria-pressed', 'true')
 | |
|     })
 | |
| 
 | |
|     await test.step(`Draw a tangential arc`, async () => {
 | |
|       await page.keyboard.press('a')
 | |
|       await expect(arcButton).toHaveAttribute('aria-pressed', 'true', {
 | |
|         timeout: 10_000,
 | |
|       })
 | |
|       await page.mouse.move(1000, 100, { steps: 5 })
 | |
|       await page.mouse.click(1000, 100)
 | |
|     })
 | |
| 
 | |
|     await test.step(`Unequip with escape, equip line tool`, async () => {
 | |
|       await page.keyboard.press('Escape')
 | |
|       await page.keyboard.press('l')
 | |
|       await page.waitForTimeout(50)
 | |
|       await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   await test.step(`Type code with sketch hotkeys, shouldn't fire`, async () => {
 | |
|     // Since there's code now, we have to get to the end of the line
 | |
|     await page.locator('.cm-line').last().click()
 | |
|     await page.keyboard.down('ControlOrMeta')
 | |
|     await page.keyboard.press('ArrowRight')
 | |
|     await page.keyboard.up('ControlOrMeta')
 | |
| 
 | |
|     await page.keyboard.press('Enter')
 | |
|     await page.keyboard.type('//')
 | |
|     await page.keyboard.press('l')
 | |
|     await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
 | |
|     await page.keyboard.press('a')
 | |
|     await expect(lineButton).toHaveAttribute('aria-pressed', 'true')
 | |
|     await expect(codePane).toContainText('//la')
 | |
|     await page.keyboard.press('Backspace')
 | |
|     await page.keyboard.press('Backspace')
 | |
|     await page.keyboard.press('Backspace')
 | |
|     await page.keyboard.press('Backspace')
 | |
|   })
 | |
| 
 | |
|   await test.step(`Close profile and exit sketch`, async () => {
 | |
|     await blurCodeEditor()
 | |
|     await page.mouse.move(700, 200, { steps: 5 })
 | |
|     await page.mouse.click(700, 200)
 | |
|     // On  close it will unequip the line tool.
 | |
|     await expect(lineButton).toHaveAttribute('aria-pressed', 'false')
 | |
|     await expect(exitSketchButton).toBeEnabled()
 | |
|     await page.keyboard.press('Escape')
 | |
|     await expect(
 | |
|       page.getByRole('button', { name: 'Exit Sketch' })
 | |
|     ).not.toBeVisible()
 | |
|   })
 | |
| 
 | |
|   // Extrude with e
 | |
|   await test.step(`Extrude the sketch`, async () => {
 | |
|     await page.mouse.click(750, 150)
 | |
|     await blurCodeEditor()
 | |
|     await expect(extrudeButton).toBeEnabled()
 | |
|     await page.keyboard.press('e')
 | |
|     await page.waitForTimeout(500)
 | |
|     await page.mouse.move(800, 200, { steps: 5 })
 | |
|     await page.mouse.click(800, 200)
 | |
|     await expect(page.getByRole('button', { name: 'Continue' })).toBeVisible({
 | |
|       timeout: 20_000,
 | |
|     })
 | |
|     await page.getByRole('button', { name: 'Continue' }).click()
 | |
|     await expect(
 | |
|       page.getByRole('button', { name: 'Submit command' })
 | |
|     ).toBeVisible()
 | |
|     await page.getByRole('button', { name: 'Submit command' }).click()
 | |
|     await expect(page.locator('.cm-content')).toContainText('extrude(')
 | |
|   })
 | |
| 
 | |
|   // await codePaneButton.click()
 | |
|   // await expect(u.codeLocator).not.toBeVisible()
 | |
| 
 | |
|   /**
 | |
|    * work-around: to stop `keyboard.press()` from typing in the editor even when it should be blurred
 | |
|    */
 | |
|   async function blurCodeEditor() {
 | |
|     await page.getByRole('button', { name: 'Commands' }).click()
 | |
|     await page.waitForTimeout(100)
 | |
|     await page.keyboard.press('Escape')
 | |
|     await page.waitForTimeout(100)
 | |
|   }
 | |
| })
 | |
| 
 | |
| test('Delete key does not navigate back', async ({ page }) => {
 | |
|   await page.setViewportSize({ width: 1200, height: 500 })
 | |
|   await page.goto('/')
 | |
|   await page.waitForURL('**/file/**', { waitUntil: 'domcontentloaded' })
 | |
| 
 | |
|   const settingsButton = page.getByRole('link', {
 | |
|     name: 'Settings',
 | |
|     exact: false,
 | |
|   })
 | |
|   const settingsCloseButton = page.getByTestId('settings-close-button')
 | |
| 
 | |
|   await settingsButton.click()
 | |
|   await expect(page.url()).toContain('/settings')
 | |
| 
 | |
|   // Make sure that delete doesn't go back from settings
 | |
|   await page.keyboard.press('Delete')
 | |
|   await expect(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(page.url()).not.toContain('/settings')
 | |
| })
 | |
| 
 | |
| test('Sketch on face', async ({ page }) => {
 | |
|   test.setTimeout(90_000)
 | |
|   const u = await getUtils(page)
 | |
|   await page.addInitScript(async () => {
 | |
|     localStorage.setItem(
 | |
|       'persistCode',
 | |
|       `sketch001 = startSketchOn('XZ')
 | |
|   |> startProfileAt([3.29, 7.86], %)
 | |
|   |> line([2.48, 2.44], %)
 | |
|   |> line([2.66, 1.17], %)
 | |
|   |> line([3.75, 0.46], %)
 | |
|   |> line([4.99, -0.46], %)
 | |
|   |> line([3.3, -2.12], %)
 | |
|   |> line([2.16, -3.33], %)
 | |
|   |> line([0.85, -3.08], %)
 | |
|   |> line([-0.18, -3.36], %)
 | |
|   |> line([-3.86, -2.73], %)
 | |
|   |> line([-17.67, 0.85], %)
 | |
|   |> close(%)
 | |
|   extrude001 = extrude(5 + 7, sketch001)`
 | |
|     )
 | |
|   })
 | |
| 
 | |
|   await page.setViewportSize({ width: 1200, height: 500 })
 | |
| 
 | |
|   await u.waitForAuthSkipAppStart()
 | |
| 
 | |
|   // wait for execution done
 | |
|   await u.openDebugPanel()
 | |
|   await u.expectCmdLog('[data-message-type="execution-done"]')
 | |
|   await u.closeDebugPanel()
 | |
| 
 | |
|   await expect(
 | |
|     page.getByRole('button', { name: 'Start Sketch' })
 | |
|   ).not.toBeDisabled()
 | |
| 
 | |
|   await page.getByRole('button', { name: 'Start Sketch' }).click()
 | |
|   await page.waitForTimeout(300)
 | |
| 
 | |
|   let previousCodeContent = await page.locator('.cm-content').innerText()
 | |
| 
 | |
|   await u.openAndClearDebugPanel()
 | |
|   await u.doAndWaitForCmd(
 | |
|     () => page.mouse.click(625, 165),
 | |
|     'default_camera_get_settings',
 | |
|     true
 | |
|   )
 | |
|   await page.waitForTimeout(150)
 | |
|   await u.closeDebugPanel()
 | |
| 
 | |
|   const firstClickPosition = [612, 238]
 | |
|   const secondClickPosition = [661, 242]
 | |
|   const thirdClickPosition = [609, 267]
 | |
| 
 | |
|   await page.mouse.click(firstClickPosition[0], firstClickPosition[1])
 | |
|   await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent)
 | |
|   previousCodeContent = await page.locator('.cm-content').innerText()
 | |
| 
 | |
|   await page.waitForTimeout(100)
 | |
|   await page.mouse.click(secondClickPosition[0], secondClickPosition[1])
 | |
|   await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent)
 | |
|   previousCodeContent = await page.locator('.cm-content').innerText()
 | |
| 
 | |
|   await page.waitForTimeout(100)
 | |
|   await page.mouse.click(thirdClickPosition[0], thirdClickPosition[1])
 | |
|   await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent)
 | |
|   previousCodeContent = await page.locator('.cm-content').innerText()
 | |
| 
 | |
|   await page.waitForTimeout(100)
 | |
|   await page.mouse.click(firstClickPosition[0], firstClickPosition[1])
 | |
|   await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent)
 | |
|   previousCodeContent = await page.locator('.cm-content').innerText()
 | |
| 
 | |
|   await expect.poll(u.normalisedEditorCode).toContain(
 | |
|     u.normalisedCode(`sketch002 = startSketchOn(extrude001, seg01)
 | |
|   |> startProfileAt([-12.94, 6.6], %)
 | |
|   |> line([2.45, -0.2], %)
 | |
|   |> line([-2.6, -1.25], %)
 | |
|   |> lineTo([profileStartX(%), profileStartY(%)], %)
 | |
|   |> close(%)`)
 | |
|   )
 | |
| 
 | |
|   await u.openAndClearDebugPanel()
 | |
|   await page.getByRole('button', { name: 'Exit Sketch' }).click()
 | |
|   await u.expectCmdLog('[data-message-type="execution-done"]')
 | |
| 
 | |
|   await u.updateCamPosition([1049, 239, 686])
 | |
|   await u.closeDebugPanel()
 | |
| 
 | |
|   await page.getByText('startProfileAt([-12').click()
 | |
|   await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeVisible()
 | |
|   await page.getByRole('button', { name: 'Edit Sketch' }).click()
 | |
|   await page.waitForTimeout(400)
 | |
|   await page.waitForTimeout(150)
 | |
|   await page.setViewportSize({ width: 1200, height: 1200 })
 | |
|   await u.openAndClearDebugPanel()
 | |
|   await u.updateCamPosition([452, -152, 1166])
 | |
|   await u.closeDebugPanel()
 | |
|   await page.waitForTimeout(200)
 | |
| 
 | |
|   const pointToDragFirst = [787, 565]
 | |
|   await page.mouse.move(pointToDragFirst[0], pointToDragFirst[1])
 | |
|   await page.mouse.down()
 | |
|   await page.mouse.move(pointToDragFirst[0] - 20, pointToDragFirst[1], {
 | |
|     steps: 5,
 | |
|   })
 | |
|   await page.mouse.up()
 | |
|   await page.waitForTimeout(100)
 | |
|   await expect(page.locator('.cm-content')).not.toHaveText(previousCodeContent)
 | |
|   previousCodeContent = await page.locator('.cm-content').innerText()
 | |
| 
 | |
|   const result = makeTemplate`sketch002 = startSketchOn(extrude001, seg01)
 | |
|   |> startProfileAt([-12.83, 6.7], %)
 | |
|   |> line([${[2.28, 2.35]}, -${0.07}], %)
 | |
|   |> line([-3.05, -1.47], %)
 | |
|   |> lineTo([profileStartX(%), profileStartY(%)], %)
 | |
|   |> close(%)`
 | |
| 
 | |
|   await expect(page.locator('.cm-content')).toHaveText(result.regExp)
 | |
| 
 | |
|   // exit sketch
 | |
|   await u.openAndClearDebugPanel()
 | |
|   await page.getByRole('button', { name: 'Exit Sketch' }).click()
 | |
|   await u.expectCmdLog('[data-message-type="execution-done"]')
 | |
| 
 | |
|   await page.getByText('startProfileAt([-12').click()
 | |
| 
 | |
|   await expect(page.getByRole('button', { name: 'Extrude' })).not.toBeDisabled()
 | |
|   await page.waitForTimeout(100)
 | |
|   await page.getByRole('button', { name: 'Extrude' }).click()
 | |
| 
 | |
|   await expect(page.getByTestId('command-bar')).toBeVisible()
 | |
|   await page.waitForTimeout(100)
 | |
| 
 | |
|   await page.getByRole('button', { name: 'arrow right Continue' }).click()
 | |
|   await page.waitForTimeout(100)
 | |
|   await expect(page.getByText('Confirm Extrude')).toBeVisible()
 | |
|   await page.getByRole('button', { name: 'checkmark Submit command' }).click()
 | |
| 
 | |
|   const result2 = result.genNext`
 | |
|   const sketch002 = extrude(${[5, 5]} + 7, sketch002)`
 | |
|   await expect(page.locator('.cm-content')).toHaveText(result2.regExp)
 | |
| })
 |