Opt-in tests that cover Windows-specific capabilities (#6489)
* Opt-in tests that cover Windows-specific capabilities * Remove unnecessary quotes
This commit is contained in:
		@ -155,7 +155,7 @@ async function doBasicSketch(
 | 
			
		||||
  |> xLine(length = -segLen(seg01))`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
test.describe('Basic sketch', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Basic sketch', () => {
 | 
			
		||||
  test('code pane open at start', async ({ page, homePage }) => {
 | 
			
		||||
    test.fixme(orRunWhenFullSuiteEnabled())
 | 
			
		||||
    await doBasicSketch(page, homePage, ['code'])
 | 
			
		||||
 | 
			
		||||
@ -8,130 +8,126 @@ import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
 | 
			
		||||
import { getUtils } from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe(
 | 
			
		||||
  'Can create sketches on all planes and their back sides',
 | 
			
		||||
  { tag: ['@skipWin'] },
 | 
			
		||||
  () => {
 | 
			
		||||
    const sketchOnPlaneAndBackSideTest = async (
 | 
			
		||||
      page: Page,
 | 
			
		||||
      homePage: HomePageFixture,
 | 
			
		||||
      scene: SceneFixture,
 | 
			
		||||
      toolbar: ToolbarFixture,
 | 
			
		||||
      plane: string,
 | 
			
		||||
      clickCoords: { x: number; y: number }
 | 
			
		||||
    ) => {
 | 
			
		||||
      const u = await getUtils(page)
 | 
			
		||||
      await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
test.describe('Can create sketches on all planes and their back sides', () => {
 | 
			
		||||
  const sketchOnPlaneAndBackSideTest = async (
 | 
			
		||||
    page: Page,
 | 
			
		||||
    homePage: HomePageFixture,
 | 
			
		||||
    scene: SceneFixture,
 | 
			
		||||
    toolbar: ToolbarFixture,
 | 
			
		||||
    plane: string,
 | 
			
		||||
    clickCoords: { x: number; y: number }
 | 
			
		||||
  ) => {
 | 
			
		||||
    const u = await getUtils(page)
 | 
			
		||||
    await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
 | 
			
		||||
      await homePage.goToModelingScene()
 | 
			
		||||
      const XYPlanRed: [number, number, number] = [98, 50, 51]
 | 
			
		||||
      await scene.expectPixelColor(XYPlanRed, { x: 700, y: 300 }, 15)
 | 
			
		||||
    await homePage.goToModelingScene()
 | 
			
		||||
    const XYPlanRed: [number, number, number] = [98, 50, 51]
 | 
			
		||||
    await scene.expectPixelColor(XYPlanRed, { x: 700, y: 300 }, 15)
 | 
			
		||||
 | 
			
		||||
      await u.openDebugPanel()
 | 
			
		||||
    await u.openDebugPanel()
 | 
			
		||||
 | 
			
		||||
      const coord =
 | 
			
		||||
        plane === '-XY' || plane === '-YZ' || plane === 'XZ' ? -100 : 100
 | 
			
		||||
      const camCommand: EngineCommand = {
 | 
			
		||||
        type: 'modeling_cmd_req',
 | 
			
		||||
        cmd_id: uuidv4(),
 | 
			
		||||
        cmd: {
 | 
			
		||||
          type: 'default_camera_look_at',
 | 
			
		||||
          center: { x: 0, y: 0, z: 0 },
 | 
			
		||||
          vantage: { x: coord, y: coord, z: coord },
 | 
			
		||||
          up: { x: 0, y: 0, z: 1 },
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
      const updateCamCommand: EngineCommand = {
 | 
			
		||||
        type: 'modeling_cmd_req',
 | 
			
		||||
        cmd_id: uuidv4(),
 | 
			
		||||
        cmd: {
 | 
			
		||||
          type: 'default_camera_get_settings',
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const code = `@settings(defaultLengthUnit = in)sketch001 = startSketchOn(${plane})profile001 = startProfileAt([0.91, -1.22], sketch001)`
 | 
			
		||||
 | 
			
		||||
      await u.openDebugPanel()
 | 
			
		||||
 | 
			
		||||
      await u.clearCommandLogs()
 | 
			
		||||
      await page.getByRole('button', { name: 'Start Sketch' }).click()
 | 
			
		||||
 | 
			
		||||
      await u.sendCustomCmd(camCommand)
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
      await u.sendCustomCmd(updateCamCommand)
 | 
			
		||||
 | 
			
		||||
      await u.closeDebugPanel()
 | 
			
		||||
 | 
			
		||||
      await page.mouse.click(clickCoords.x, clickCoords.y)
 | 
			
		||||
      await page.waitForTimeout(600) // wait for animation
 | 
			
		||||
 | 
			
		||||
      await toolbar.waitUntilSketchingReady()
 | 
			
		||||
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'line Line', exact: true })
 | 
			
		||||
      ).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      await u.closeDebugPanel()
 | 
			
		||||
      await page.mouse.click(707, 393)
 | 
			
		||||
 | 
			
		||||
      await expect(page.locator('.cm-content')).toHaveText(code)
 | 
			
		||||
 | 
			
		||||
      await page
 | 
			
		||||
        .getByRole('button', { name: 'line Line', exact: true })
 | 
			
		||||
        .first()
 | 
			
		||||
        .click()
 | 
			
		||||
      await u.openAndClearDebugPanel()
 | 
			
		||||
      await page.getByRole('button', { name: 'Exit Sketch' }).click()
 | 
			
		||||
      await u.expectCmdLog('[data-message-type="execution-done"]')
 | 
			
		||||
 | 
			
		||||
      await u.clearCommandLogs()
 | 
			
		||||
      await u.removeCurrentCode()
 | 
			
		||||
    const coord =
 | 
			
		||||
      plane === '-XY' || plane === '-YZ' || plane === 'XZ' ? -100 : 100
 | 
			
		||||
    const camCommand: EngineCommand = {
 | 
			
		||||
      type: 'modeling_cmd_req',
 | 
			
		||||
      cmd_id: uuidv4(),
 | 
			
		||||
      cmd: {
 | 
			
		||||
        type: 'default_camera_look_at',
 | 
			
		||||
        center: { x: 0, y: 0, z: 0 },
 | 
			
		||||
        vantage: { x: coord, y: coord, z: coord },
 | 
			
		||||
        up: { x: 0, y: 0, z: 1 },
 | 
			
		||||
      },
 | 
			
		||||
    }
 | 
			
		||||
    const updateCamCommand: EngineCommand = {
 | 
			
		||||
      type: 'modeling_cmd_req',
 | 
			
		||||
      cmd_id: uuidv4(),
 | 
			
		||||
      cmd: {
 | 
			
		||||
        type: 'default_camera_get_settings',
 | 
			
		||||
      },
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const planeConfigs = [
 | 
			
		||||
      {
 | 
			
		||||
        plane: 'XY',
 | 
			
		||||
        coords: { x: 600, y: 388 },
 | 
			
		||||
        description: 'red plane',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        plane: 'YZ',
 | 
			
		||||
        coords: { x: 700, y: 250 },
 | 
			
		||||
        description: 'green plane',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        plane: 'XZ',
 | 
			
		||||
        coords: { x: 684, y: 427 },
 | 
			
		||||
        description: 'blue plane',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        plane: '-XY',
 | 
			
		||||
        coords: { x: 600, y: 118 },
 | 
			
		||||
        description: 'back of red plane',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        plane: '-YZ',
 | 
			
		||||
        coords: { x: 700, y: 219 },
 | 
			
		||||
        description: 'back of green plane',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        plane: '-XZ',
 | 
			
		||||
        coords: { x: 700, y: 80 },
 | 
			
		||||
        description: 'back of blue plane',
 | 
			
		||||
      },
 | 
			
		||||
    ]
 | 
			
		||||
    const code = `@settings(defaultLengthUnit = in)sketch001 = startSketchOn(${plane})profile001 = startProfileAt([0.91, -1.22], sketch001)`
 | 
			
		||||
 | 
			
		||||
    for (const config of planeConfigs) {
 | 
			
		||||
      test(config.plane, async ({ page, homePage, scene, toolbar }) => {
 | 
			
		||||
        await sketchOnPlaneAndBackSideTest(
 | 
			
		||||
          page,
 | 
			
		||||
          homePage,
 | 
			
		||||
          scene,
 | 
			
		||||
          toolbar,
 | 
			
		||||
          config.plane,
 | 
			
		||||
          config.coords
 | 
			
		||||
        )
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    await u.openDebugPanel()
 | 
			
		||||
 | 
			
		||||
    await u.clearCommandLogs()
 | 
			
		||||
    await page.getByRole('button', { name: 'Start Sketch' }).click()
 | 
			
		||||
 | 
			
		||||
    await u.sendCustomCmd(camCommand)
 | 
			
		||||
    await page.waitForTimeout(100)
 | 
			
		||||
    await u.sendCustomCmd(updateCamCommand)
 | 
			
		||||
 | 
			
		||||
    await u.closeDebugPanel()
 | 
			
		||||
 | 
			
		||||
    await page.mouse.click(clickCoords.x, clickCoords.y)
 | 
			
		||||
    await page.waitForTimeout(600) // wait for animation
 | 
			
		||||
 | 
			
		||||
    await toolbar.waitUntilSketchingReady()
 | 
			
		||||
 | 
			
		||||
    await expect(
 | 
			
		||||
      page.getByRole('button', { name: 'line Line', exact: true })
 | 
			
		||||
    ).toBeVisible()
 | 
			
		||||
 | 
			
		||||
    await u.closeDebugPanel()
 | 
			
		||||
    await page.mouse.click(707, 393)
 | 
			
		||||
 | 
			
		||||
    await expect(page.locator('.cm-content')).toHaveText(code)
 | 
			
		||||
 | 
			
		||||
    await page
 | 
			
		||||
      .getByRole('button', { name: 'line Line', exact: true })
 | 
			
		||||
      .first()
 | 
			
		||||
      .click()
 | 
			
		||||
    await u.openAndClearDebugPanel()
 | 
			
		||||
    await page.getByRole('button', { name: 'Exit Sketch' }).click()
 | 
			
		||||
    await u.expectCmdLog('[data-message-type="execution-done"]')
 | 
			
		||||
 | 
			
		||||
    await u.clearCommandLogs()
 | 
			
		||||
    await u.removeCurrentCode()
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
  const planeConfigs = [
 | 
			
		||||
    {
 | 
			
		||||
      plane: 'XY',
 | 
			
		||||
      coords: { x: 600, y: 388 },
 | 
			
		||||
      description: 'red plane',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      plane: 'YZ',
 | 
			
		||||
      coords: { x: 700, y: 250 },
 | 
			
		||||
      description: 'green plane',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      plane: 'XZ',
 | 
			
		||||
      coords: { x: 684, y: 427 },
 | 
			
		||||
      description: 'blue plane',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      plane: '-XY',
 | 
			
		||||
      coords: { x: 600, y: 118 },
 | 
			
		||||
      description: 'back of red plane',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      plane: '-YZ',
 | 
			
		||||
      coords: { x: 700, y: 219 },
 | 
			
		||||
      description: 'back of green plane',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      plane: '-XZ',
 | 
			
		||||
      coords: { x: 700, y: 80 },
 | 
			
		||||
      description: 'back of blue plane',
 | 
			
		||||
    },
 | 
			
		||||
  ]
 | 
			
		||||
 | 
			
		||||
  for (const config of planeConfigs) {
 | 
			
		||||
    test(config.plane, async ({ page, homePage, scene, toolbar }) => {
 | 
			
		||||
      await sketchOnPlaneAndBackSideTest(
 | 
			
		||||
        page,
 | 
			
		||||
        homePage,
 | 
			
		||||
        scene,
 | 
			
		||||
        toolbar,
 | 
			
		||||
        config.plane,
 | 
			
		||||
        config.coords
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ import {
 | 
			
		||||
} from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Code pane and errors', () => {
 | 
			
		||||
  test('Typing KCL errors induces a badge on the code pane button', async ({
 | 
			
		||||
    page,
 | 
			
		||||
    homePage,
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ import {
 | 
			
		||||
} from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Command bar tests', () => {
 | 
			
		||||
  test('Extrude from command bar selects extrude line after', async ({
 | 
			
		||||
    page,
 | 
			
		||||
    homePage,
 | 
			
		||||
@ -179,57 +179,57 @@ test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
    await expect(commandLevelArgButton).toHaveText('level: project')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test(
 | 
			
		||||
    'Command bar keybinding works from code editor and can change a setting',
 | 
			
		||||
    { tag: ['@skipWin'] },
 | 
			
		||||
    async ({ page, homePage }) => {
 | 
			
		||||
      await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
      await homePage.goToModelingScene()
 | 
			
		||||
  test('Command bar keybinding works from code editor and can change a setting', async ({
 | 
			
		||||
    page,
 | 
			
		||||
    homePage,
 | 
			
		||||
  }) => {
 | 
			
		||||
    await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
    await homePage.goToModelingScene()
 | 
			
		||||
 | 
			
		||||
      // FIXME: No KCL code, unable to wait for engine execution
 | 
			
		||||
      await page.waitForTimeout(10000)
 | 
			
		||||
    // FIXME: No KCL code, unable to wait for engine execution
 | 
			
		||||
    await page.waitForTimeout(10000)
 | 
			
		||||
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
      ).not.toBeDisabled()
 | 
			
		||||
    await expect(
 | 
			
		||||
      page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
    ).not.toBeDisabled()
 | 
			
		||||
 | 
			
		||||
      // Put the cursor in the code editor
 | 
			
		||||
      await page.locator('.cm-content').click()
 | 
			
		||||
    // Put the cursor in the code editor
 | 
			
		||||
    await page.locator('.cm-content').click()
 | 
			
		||||
 | 
			
		||||
      // Now try the same, but with the keyboard shortcut, check focus
 | 
			
		||||
      await page.keyboard.press('ControlOrMeta+K')
 | 
			
		||||
    // Now try the same, but with the keyboard shortcut, check focus
 | 
			
		||||
    await page.keyboard.press('ControlOrMeta+K')
 | 
			
		||||
 | 
			
		||||
      let cmdSearchBar = page.getByPlaceholder('Search commands')
 | 
			
		||||
      await expect(cmdSearchBar).toBeVisible()
 | 
			
		||||
      await expect(cmdSearchBar).toBeFocused()
 | 
			
		||||
    let cmdSearchBar = page.getByPlaceholder('Search commands')
 | 
			
		||||
    await expect(cmdSearchBar).toBeVisible()
 | 
			
		||||
    await expect(cmdSearchBar).toBeFocused()
 | 
			
		||||
 | 
			
		||||
      // Try typing in the command bar
 | 
			
		||||
      await cmdSearchBar.fill('theme')
 | 
			
		||||
      const themeOption = page.getByRole('option', {
 | 
			
		||||
        name: 'Settings · app · theme',
 | 
			
		||||
      })
 | 
			
		||||
      await expect(themeOption).toBeVisible()
 | 
			
		||||
      await themeOption.click()
 | 
			
		||||
      const themeInput = page.getByPlaceholder('dark')
 | 
			
		||||
      await expect(themeInput).toBeVisible()
 | 
			
		||||
      await expect(themeInput).toBeFocused()
 | 
			
		||||
      // Select dark theme
 | 
			
		||||
      await page.keyboard.press('ArrowDown')
 | 
			
		||||
      await page.keyboard.press('ArrowDown')
 | 
			
		||||
      await page.keyboard.press('ArrowDown')
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('option', { name: 'system' })
 | 
			
		||||
      ).toHaveAttribute('data-headlessui-state', 'active')
 | 
			
		||||
      await page.keyboard.press('Enter')
 | 
			
		||||
    // Try typing in the command bar
 | 
			
		||||
    await cmdSearchBar.fill('theme')
 | 
			
		||||
    const themeOption = page.getByRole('option', {
 | 
			
		||||
      name: 'Settings · app · theme',
 | 
			
		||||
    })
 | 
			
		||||
    await expect(themeOption).toBeVisible()
 | 
			
		||||
    await themeOption.click()
 | 
			
		||||
    const themeInput = page.getByPlaceholder('dark')
 | 
			
		||||
    await expect(themeInput).toBeVisible()
 | 
			
		||||
    await expect(themeInput).toBeFocused()
 | 
			
		||||
    // Select dark theme
 | 
			
		||||
    await page.keyboard.press('ArrowDown')
 | 
			
		||||
    await page.keyboard.press('ArrowDown')
 | 
			
		||||
    await page.keyboard.press('ArrowDown')
 | 
			
		||||
    await expect(page.getByRole('option', { name: 'system' })).toHaveAttribute(
 | 
			
		||||
      'data-headlessui-state',
 | 
			
		||||
      'active'
 | 
			
		||||
    )
 | 
			
		||||
    await page.keyboard.press('Enter')
 | 
			
		||||
 | 
			
		||||
      // Check the toast appeared
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByText(`Set theme to "system" as a user default`)
 | 
			
		||||
      ).toBeVisible()
 | 
			
		||||
      // Check that the theme changed
 | 
			
		||||
      await expect(page.locator('body')).not.toHaveClass(`body-bg dark`)
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
    // Check the toast appeared
 | 
			
		||||
    await expect(
 | 
			
		||||
      page.getByText(`Set theme to "system" as a user default`)
 | 
			
		||||
    ).toBeVisible()
 | 
			
		||||
    // Check that the theme changed
 | 
			
		||||
    await expect(page.locator('body')).not.toHaveClass(`body-bg dark`)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('Can extrude from the command bar', async ({
 | 
			
		||||
    page,
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test(
 | 
			
		||||
  'export works on the first try',
 | 
			
		||||
  { tag: ['@electron', '@macOS', '@skipLocalEngine'] },
 | 
			
		||||
  { tag: ['@electron', '@macos', '@windows', '@skipLocalEngine'] },
 | 
			
		||||
  async ({ page, context, scene, tronApp, cmdBar }, testInfo) => {
 | 
			
		||||
    if (!tronApp) {
 | 
			
		||||
      fail()
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ import {
 | 
			
		||||
} from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Editor tests', () => {
 | 
			
		||||
  test('can comment out code with ctrl+/', async ({ page, homePage }) => {
 | 
			
		||||
    const u = await getUtils(page)
 | 
			
		||||
    await page.setBodyDimensions({ width: 1000, height: 500 })
 | 
			
		||||
@ -989,162 +989,162 @@ sketch001 = startSketchOn(XZ)
 | 
			
		||||
  |> close()`)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test(
 | 
			
		||||
    'Can undo a sketch modification with ctrl+z',
 | 
			
		||||
    { tag: ['@skipWin'] },
 | 
			
		||||
    async ({ page, homePage, editor }) => {
 | 
			
		||||
      const u = await getUtils(page)
 | 
			
		||||
      await page.addInitScript(async () => {
 | 
			
		||||
        localStorage.setItem(
 | 
			
		||||
          'persistCode',
 | 
			
		||||
          `@settings(defaultLengthUnit=in)
 | 
			
		||||
  test('Can undo a sketch modification with ctrl+z', async ({
 | 
			
		||||
    page,
 | 
			
		||||
    homePage,
 | 
			
		||||
    editor,
 | 
			
		||||
  }) => {
 | 
			
		||||
    const u = await getUtils(page)
 | 
			
		||||
    await page.addInitScript(async () => {
 | 
			
		||||
      localStorage.setItem(
 | 
			
		||||
        'persistCode',
 | 
			
		||||
        `@settings(defaultLengthUnit=in)
 | 
			
		||||
sketch001 = startSketchOn(XZ)
 | 
			
		||||
  |> startProfileAt([4.61, -10.01], %)
 | 
			
		||||
  |> line(end = [12.73, -0.09])
 | 
			
		||||
  |> tangentialArc(endAbsolute = [24.95, -0.38])
 | 
			
		||||
  |> close()
 | 
			
		||||
  |> extrude(length = 5)`
 | 
			
		||||
        )
 | 
			
		||||
      })
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
      await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
    await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
 | 
			
		||||
      await homePage.goToModelingScene()
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
      ).not.toBeDisabled()
 | 
			
		||||
    await homePage.goToModelingScene()
 | 
			
		||||
    await expect(
 | 
			
		||||
      page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
    ).not.toBeDisabled()
 | 
			
		||||
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
      await u.openAndClearDebugPanel()
 | 
			
		||||
      await u.sendCustomCmd({
 | 
			
		||||
        type: 'modeling_cmd_req',
 | 
			
		||||
        cmd_id: uuidv4(),
 | 
			
		||||
        cmd: {
 | 
			
		||||
          type: 'default_camera_look_at',
 | 
			
		||||
          vantage: { x: 0, y: -1250, z: 580 },
 | 
			
		||||
          center: { x: 0, y: 0, z: 0 },
 | 
			
		||||
          up: { x: 0, y: 0, z: 1 },
 | 
			
		||||
        },
 | 
			
		||||
      })
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
      await u.sendCustomCmd({
 | 
			
		||||
        type: 'modeling_cmd_req',
 | 
			
		||||
        cmd_id: uuidv4(),
 | 
			
		||||
        cmd: {
 | 
			
		||||
          type: 'default_camera_get_settings',
 | 
			
		||||
        },
 | 
			
		||||
      })
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
    await page.waitForTimeout(100)
 | 
			
		||||
    await u.openAndClearDebugPanel()
 | 
			
		||||
    await u.sendCustomCmd({
 | 
			
		||||
      type: 'modeling_cmd_req',
 | 
			
		||||
      cmd_id: uuidv4(),
 | 
			
		||||
      cmd: {
 | 
			
		||||
        type: 'default_camera_look_at',
 | 
			
		||||
        vantage: { x: 0, y: -1250, z: 580 },
 | 
			
		||||
        center: { x: 0, y: 0, z: 0 },
 | 
			
		||||
        up: { x: 0, y: 0, z: 1 },
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
    await page.waitForTimeout(100)
 | 
			
		||||
    await u.sendCustomCmd({
 | 
			
		||||
      type: 'modeling_cmd_req',
 | 
			
		||||
      cmd_id: uuidv4(),
 | 
			
		||||
      cmd: {
 | 
			
		||||
        type: 'default_camera_get_settings',
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
    await page.waitForTimeout(100)
 | 
			
		||||
 | 
			
		||||
      const startPX = [1200 / 2, 500 / 2]
 | 
			
		||||
    const startPX = [1200 / 2, 500 / 2]
 | 
			
		||||
 | 
			
		||||
      const dragPX = 40
 | 
			
		||||
    const dragPX = 40
 | 
			
		||||
 | 
			
		||||
      await page.getByText('startProfileAt([4.61, -10.01], %)').click()
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'Edit Sketch' })
 | 
			
		||||
      ).toBeVisible()
 | 
			
		||||
      await page.getByRole('button', { name: 'Edit Sketch' }).click()
 | 
			
		||||
      await page.waitForTimeout(400)
 | 
			
		||||
      let prevContent = await page.locator('.cm-content').innerText()
 | 
			
		||||
    await page.getByText('startProfileAt([4.61, -10.01], %)').click()
 | 
			
		||||
    await expect(
 | 
			
		||||
      page.getByRole('button', { name: 'Edit Sketch' })
 | 
			
		||||
    ).toBeVisible()
 | 
			
		||||
    await page.getByRole('button', { name: 'Edit Sketch' }).click()
 | 
			
		||||
    await page.waitForTimeout(400)
 | 
			
		||||
    let prevContent = await page.locator('.cm-content').innerText()
 | 
			
		||||
 | 
			
		||||
      await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
 | 
			
		||||
    await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
 | 
			
		||||
 | 
			
		||||
      // drag startProfileAt handle
 | 
			
		||||
      await page.dragAndDrop('#stream', '#stream', {
 | 
			
		||||
        sourcePosition: { x: startPX[0] + 68, y: startPX[1] + 147 },
 | 
			
		||||
        targetPosition: { x: startPX[0] + dragPX, y: startPX[1] + dragPX },
 | 
			
		||||
      })
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
      await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
 | 
			
		||||
      prevContent = await page.locator('.cm-content').innerText()
 | 
			
		||||
    // drag startProfileAt handle
 | 
			
		||||
    await page.dragAndDrop('#stream', '#stream', {
 | 
			
		||||
      sourcePosition: { x: startPX[0] + 68, y: startPX[1] + 147 },
 | 
			
		||||
      targetPosition: { x: startPX[0] + dragPX, y: startPX[1] + dragPX },
 | 
			
		||||
    })
 | 
			
		||||
    await page.waitForTimeout(100)
 | 
			
		||||
    await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
 | 
			
		||||
    prevContent = await page.locator('.cm-content').innerText()
 | 
			
		||||
 | 
			
		||||
      // drag line handle
 | 
			
		||||
      // we wait so it saves the code
 | 
			
		||||
      await page.waitForTimeout(800)
 | 
			
		||||
    // drag line handle
 | 
			
		||||
    // we wait so it saves the code
 | 
			
		||||
    await page.waitForTimeout(800)
 | 
			
		||||
 | 
			
		||||
      const lineEnd = await u.getBoundingBox('[data-overlay-index="0"]')
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
      await page.dragAndDrop('#stream', '#stream', {
 | 
			
		||||
        sourcePosition: { x: lineEnd.x - 5, y: lineEnd.y },
 | 
			
		||||
        targetPosition: { x: lineEnd.x + dragPX, y: lineEnd.y + dragPX },
 | 
			
		||||
      })
 | 
			
		||||
      await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
 | 
			
		||||
      prevContent = await page.locator('.cm-content').innerText()
 | 
			
		||||
    const lineEnd = await u.getBoundingBox('[data-overlay-index="0"]')
 | 
			
		||||
    await page.waitForTimeout(100)
 | 
			
		||||
    await page.dragAndDrop('#stream', '#stream', {
 | 
			
		||||
      sourcePosition: { x: lineEnd.x - 5, y: lineEnd.y },
 | 
			
		||||
      targetPosition: { x: lineEnd.x + dragPX, y: lineEnd.y + dragPX },
 | 
			
		||||
    })
 | 
			
		||||
    await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
 | 
			
		||||
    prevContent = await page.locator('.cm-content').innerText()
 | 
			
		||||
 | 
			
		||||
      // we wait so it saves the code
 | 
			
		||||
      await page.waitForTimeout(800)
 | 
			
		||||
    // we wait so it saves the code
 | 
			
		||||
    await page.waitForTimeout(800)
 | 
			
		||||
 | 
			
		||||
      // drag tangentialArc handle
 | 
			
		||||
      const tangentEnd = await u.getBoundingBox('[data-overlay-index="1"]')
 | 
			
		||||
      await page.dragAndDrop('#stream', '#stream', {
 | 
			
		||||
        sourcePosition: { x: tangentEnd.x + 10, y: tangentEnd.y - 5 },
 | 
			
		||||
        targetPosition: {
 | 
			
		||||
          x: tangentEnd.x + dragPX,
 | 
			
		||||
          y: tangentEnd.y + dragPX,
 | 
			
		||||
        },
 | 
			
		||||
      })
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
      await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
 | 
			
		||||
    // drag tangentialArc handle
 | 
			
		||||
    const tangentEnd = await u.getBoundingBox('[data-overlay-index="1"]')
 | 
			
		||||
    await page.dragAndDrop('#stream', '#stream', {
 | 
			
		||||
      sourcePosition: { x: tangentEnd.x + 10, y: tangentEnd.y - 5 },
 | 
			
		||||
      targetPosition: {
 | 
			
		||||
        x: tangentEnd.x + dragPX,
 | 
			
		||||
        y: tangentEnd.y + dragPX,
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
    await page.waitForTimeout(100)
 | 
			
		||||
    await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
 | 
			
		||||
 | 
			
		||||
      // expect the code to have changed
 | 
			
		||||
      await editor.expectEditor.toContain(
 | 
			
		||||
        `sketch001 = startSketchOn(XZ)
 | 
			
		||||
    // expect the code to have changed
 | 
			
		||||
    await editor.expectEditor.toContain(
 | 
			
		||||
      `sketch001 = startSketchOn(XZ)
 | 
			
		||||
    |> startProfileAt([2.71, -2.71], %)
 | 
			
		||||
    |> line(end = [15.4, -2.78])
 | 
			
		||||
    |> tangentialArc(endAbsolute = [27.6, -3.05])
 | 
			
		||||
    |> close()
 | 
			
		||||
    |> extrude(length = 5)`,
 | 
			
		||||
        { shouldNormalise: true }
 | 
			
		||||
      )
 | 
			
		||||
      { shouldNormalise: true }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
      // Hit undo
 | 
			
		||||
      await page.keyboard.down('Control')
 | 
			
		||||
      await page.keyboard.press('KeyZ')
 | 
			
		||||
      await page.keyboard.up('Control')
 | 
			
		||||
    // Hit undo
 | 
			
		||||
    await page.keyboard.down('Control')
 | 
			
		||||
    await page.keyboard.press('KeyZ')
 | 
			
		||||
    await page.keyboard.up('Control')
 | 
			
		||||
 | 
			
		||||
      await editor.expectEditor.toContain(
 | 
			
		||||
        `sketch001 = startSketchOn(XZ)
 | 
			
		||||
    await editor.expectEditor.toContain(
 | 
			
		||||
      `sketch001 = startSketchOn(XZ)
 | 
			
		||||
    |> startProfileAt([2.71, -2.71], %)
 | 
			
		||||
    |> line(end = [15.4, -2.78])
 | 
			
		||||
    |> tangentialArc(endAbsolute = [24.95, -0.38])
 | 
			
		||||
    |> close()
 | 
			
		||||
    |> extrude(length = 5)`,
 | 
			
		||||
        { shouldNormalise: true }
 | 
			
		||||
      )
 | 
			
		||||
      { shouldNormalise: true }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
      // Hit undo again.
 | 
			
		||||
      await page.keyboard.down('Control')
 | 
			
		||||
      await page.keyboard.press('KeyZ')
 | 
			
		||||
      await page.keyboard.up('Control')
 | 
			
		||||
    // Hit undo again.
 | 
			
		||||
    await page.keyboard.down('Control')
 | 
			
		||||
    await page.keyboard.press('KeyZ')
 | 
			
		||||
    await page.keyboard.up('Control')
 | 
			
		||||
 | 
			
		||||
      await editor.expectEditor.toContain(
 | 
			
		||||
        `sketch001 = startSketchOn(XZ)
 | 
			
		||||
    await editor.expectEditor.toContain(
 | 
			
		||||
      `sketch001 = startSketchOn(XZ)
 | 
			
		||||
    |> startProfileAt([2.71, -2.71], %)
 | 
			
		||||
    |> line(end = [12.73, -0.09])
 | 
			
		||||
    |> tangentialArc(endAbsolute = [24.95, -0.38])
 | 
			
		||||
    |> close()
 | 
			
		||||
    |> extrude(length = 5)`,
 | 
			
		||||
        { shouldNormalise: true }
 | 
			
		||||
      )
 | 
			
		||||
      { shouldNormalise: true }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
      // Hit undo again.
 | 
			
		||||
      await page.keyboard.down('Control')
 | 
			
		||||
      await page.keyboard.press('KeyZ')
 | 
			
		||||
      await page.keyboard.up('Control')
 | 
			
		||||
    // Hit undo again.
 | 
			
		||||
    await page.keyboard.down('Control')
 | 
			
		||||
    await page.keyboard.press('KeyZ')
 | 
			
		||||
    await page.keyboard.up('Control')
 | 
			
		||||
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
      await editor.expectEditor.toContain(
 | 
			
		||||
        `sketch001 = startSketchOn(XZ)
 | 
			
		||||
    await page.waitForTimeout(100)
 | 
			
		||||
    await editor.expectEditor.toContain(
 | 
			
		||||
      `sketch001 = startSketchOn(XZ)
 | 
			
		||||
    |> startProfileAt([4.61, -10.01], %)
 | 
			
		||||
    |> line(end = [12.73, -0.09])
 | 
			
		||||
    |> tangentialArc(endAbsolute = [24.95, -0.38])
 | 
			
		||||
    |> close()
 | 
			
		||||
    |> extrude(length = 5)`,
 | 
			
		||||
        { shouldNormalise: true }
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
      { shouldNormalise: true }
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test(
 | 
			
		||||
    `Can import a local OBJ file`,
 | 
			
		||||
 | 
			
		||||
@ -41,7 +41,7 @@ class MyAPIReporter implements Reporter {
 | 
			
		||||
      annotations: test.annotations.map((a) => a.type), // e.g. 'fail' or 'fixme'
 | 
			
		||||
      id: test.id, // computed file/test/project ID used for reruns
 | 
			
		||||
      retry: result.retry,
 | 
			
		||||
      tags: test.tags, // e.g. '@snapshot' or '@skipWin'
 | 
			
		||||
      tags: test.tags, // e.g. '@snapshot' or '@skipLocalEngine'
 | 
			
		||||
      // Extra environment variables
 | 
			
		||||
      CI_COMMIT_SHA: process.env.CI_COMMIT_SHA || null,
 | 
			
		||||
      CI_PR_NUMBER: process.env.CI_PR_NUMBER || null,
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -18,7 +18,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test(
 | 
			
		||||
  'projects reload if a new one is created, deleted, or renamed externally',
 | 
			
		||||
  { tag: ['@electron', '@macOS'] },
 | 
			
		||||
  { tag: ['@electron', '@macos', '@windows'] },
 | 
			
		||||
  async ({ context, page }, testInfo) => {
 | 
			
		||||
    let externalCreatedProjectName = 'external-created-project'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@ sketch003 = startSketchOn(XY)
 | 
			
		||||
extrude003 = extrude(sketch003, length = 20)
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
 | 
			
		||||
test.describe('Prompt-to-edit tests', () => {
 | 
			
		||||
  test.describe('Check the happy path, for basic changing color', () => {
 | 
			
		||||
    const cases = [
 | 
			
		||||
      {
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ import {
 | 
			
		||||
} from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Regression tests', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Regression tests', () => {
 | 
			
		||||
  // bugs we found that don't fit neatly into other categories
 | 
			
		||||
  test('bad model has inline error #3251', async ({
 | 
			
		||||
    context,
 | 
			
		||||
@ -239,17 +239,18 @@ extrude001 = extrude(sketch001, length = 50)
 | 
			
		||||
    await expect(zooLogo).not.toHaveAttribute('href')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test(
 | 
			
		||||
    'Position _ Is Out Of Range... regression test',
 | 
			
		||||
    { tag: ['@skipWin'] },
 | 
			
		||||
    async ({ context, page, homePage }) => {
 | 
			
		||||
      const u = await getUtils(page)
 | 
			
		||||
      // const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
      await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
      await context.addInitScript(async () => {
 | 
			
		||||
        localStorage.setItem(
 | 
			
		||||
          'persistCode',
 | 
			
		||||
          `exampleSketch = startSketchOn("XZ")
 | 
			
		||||
  test('Position _ Is Out Of Range... regression test', async ({
 | 
			
		||||
    context,
 | 
			
		||||
    page,
 | 
			
		||||
    homePage,
 | 
			
		||||
  }) => {
 | 
			
		||||
    const u = await getUtils(page)
 | 
			
		||||
    // const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
    await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
    await context.addInitScript(async () => {
 | 
			
		||||
      localStorage.setItem(
 | 
			
		||||
        'persistCode',
 | 
			
		||||
        `exampleSketch = startSketchOn("XZ")
 | 
			
		||||
      |> startProfileAt([0, 0], %)
 | 
			
		||||
      |> angledLine(angle = 50, length = 45 )
 | 
			
		||||
      |> yLine(endAbsolute = 0)
 | 
			
		||||
@ -258,55 +259,55 @@ extrude001 = extrude(sketch001, length = 50)
 | 
			
		||||
 | 
			
		||||
    example = extrude(exampleSketch, length = 5)
 | 
			
		||||
    shell(exampleSketch, faces = ['end'], thickness = 0.25)`
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    await expect(async () => {
 | 
			
		||||
      await homePage.goToModelingScene()
 | 
			
		||||
      await u.waitForPageLoad()
 | 
			
		||||
 | 
			
		||||
      // error in guter
 | 
			
		||||
      await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
 | 
			
		||||
        timeout: 1_000,
 | 
			
		||||
      })
 | 
			
		||||
      await page.waitForTimeout(200)
 | 
			
		||||
      // expect it still to be there (sometimes it just clears for a bit?)
 | 
			
		||||
      await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
 | 
			
		||||
        timeout: 1_000,
 | 
			
		||||
      })
 | 
			
		||||
    }).toPass({ timeout: 40_000, intervals: [1_000] })
 | 
			
		||||
 | 
			
		||||
      await expect(async () => {
 | 
			
		||||
        await homePage.goToModelingScene()
 | 
			
		||||
        await u.waitForPageLoad()
 | 
			
		||||
    // error text on hover
 | 
			
		||||
    await page.hover('.cm-lint-marker-error')
 | 
			
		||||
    await expect(page.getByText('Unexpected token: |').first()).toBeVisible()
 | 
			
		||||
 | 
			
		||||
        // error in guter
 | 
			
		||||
        await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
 | 
			
		||||
          timeout: 1_000,
 | 
			
		||||
        })
 | 
			
		||||
        await page.waitForTimeout(200)
 | 
			
		||||
        // expect it still to be there (sometimes it just clears for a bit?)
 | 
			
		||||
        await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
 | 
			
		||||
          timeout: 1_000,
 | 
			
		||||
        })
 | 
			
		||||
      }).toPass({ timeout: 40_000, intervals: [1_000] })
 | 
			
		||||
    // Okay execution finished, let's start editing text below the error.
 | 
			
		||||
    await u.codeLocator.click()
 | 
			
		||||
    // Go to the end of the editor
 | 
			
		||||
    // This bug happens when there is a diagnostic in the editor and you try to
 | 
			
		||||
    // edit text below it.
 | 
			
		||||
    // Or delete a huge chunk of text and then try to edit below it.
 | 
			
		||||
    await page.keyboard.press('End')
 | 
			
		||||
    await page.keyboard.down('Shift')
 | 
			
		||||
    await page.keyboard.press('ArrowUp')
 | 
			
		||||
    await page.keyboard.press('ArrowUp')
 | 
			
		||||
    await page.keyboard.press('ArrowUp')
 | 
			
		||||
    await page.keyboard.press('ArrowUp')
 | 
			
		||||
    await page.keyboard.press('ArrowUp')
 | 
			
		||||
    await page.keyboard.press('End')
 | 
			
		||||
    await page.keyboard.up('Shift')
 | 
			
		||||
    await page.keyboard.press('Backspace')
 | 
			
		||||
    await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // error text on hover
 | 
			
		||||
      await page.hover('.cm-lint-marker-error')
 | 
			
		||||
      await expect(page.getByText('Unexpected token: |').first()).toBeVisible()
 | 
			
		||||
    await page.keyboard.press('Enter')
 | 
			
		||||
    await page.keyboard.press('Enter')
 | 
			
		||||
    await page.keyboard.type('thing: "blah"', { delay: 100 })
 | 
			
		||||
    await page.keyboard.press('Enter')
 | 
			
		||||
    await page.keyboard.press('ArrowLeft')
 | 
			
		||||
 | 
			
		||||
      // Okay execution finished, let's start editing text below the error.
 | 
			
		||||
      await u.codeLocator.click()
 | 
			
		||||
      // Go to the end of the editor
 | 
			
		||||
      // This bug happens when there is a diagnostic in the editor and you try to
 | 
			
		||||
      // edit text below it.
 | 
			
		||||
      // Or delete a huge chunk of text and then try to edit below it.
 | 
			
		||||
      await page.keyboard.press('End')
 | 
			
		||||
      await page.keyboard.down('Shift')
 | 
			
		||||
      await page.keyboard.press('ArrowUp')
 | 
			
		||||
      await page.keyboard.press('ArrowUp')
 | 
			
		||||
      await page.keyboard.press('ArrowUp')
 | 
			
		||||
      await page.keyboard.press('ArrowUp')
 | 
			
		||||
      await page.keyboard.press('ArrowUp')
 | 
			
		||||
      await page.keyboard.press('End')
 | 
			
		||||
      await page.keyboard.up('Shift')
 | 
			
		||||
      await page.keyboard.press('Backspace')
 | 
			
		||||
      await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      await page.keyboard.press('Enter')
 | 
			
		||||
      await page.keyboard.press('Enter')
 | 
			
		||||
      await page.keyboard.type('thing: "blah"', { delay: 100 })
 | 
			
		||||
      await page.keyboard.press('Enter')
 | 
			
		||||
      await page.keyboard.press('ArrowLeft')
 | 
			
		||||
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.locator('.cm-content')
 | 
			
		||||
      ).toContainText(`exampleSketch = startSketchOn("XZ")
 | 
			
		||||
    await expect(
 | 
			
		||||
      page.locator('.cm-content')
 | 
			
		||||
    ).toContainText(`exampleSketch = startSketchOn("XZ")
 | 
			
		||||
      |> startProfileAt([0, 0], %)
 | 
			
		||||
      |> angledLine(angle = 50, length = 45 )
 | 
			
		||||
      |> yLine(endAbsolute = 0)
 | 
			
		||||
@ -314,9 +315,8 @@ extrude001 = extrude(sketch001, length = 50)
 | 
			
		||||
 | 
			
		||||
      thing: "blah"`)
 | 
			
		||||
 | 
			
		||||
      await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
    await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test(
 | 
			
		||||
    'window resize updates should reconfigure the stream',
 | 
			
		||||
@ -486,82 +486,81 @@ extrude002 = extrude(profile002, length = 150)
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
  // We updated this test such that you can have multiple exports going at once.
 | 
			
		||||
  test(
 | 
			
		||||
    'ensure you CAN export while an export is already going',
 | 
			
		||||
    { tag: ['@skipLinux', '@skipWin'] },
 | 
			
		||||
    async ({ page, homePage }) => {
 | 
			
		||||
      const u = await getUtils(page)
 | 
			
		||||
      await test.step('Set up the code and durations', async () => {
 | 
			
		||||
        await page.addInitScript(
 | 
			
		||||
          async ({ code }) => {
 | 
			
		||||
            localStorage.setItem('persistCode', code)
 | 
			
		||||
            ;(window as any).playwrightSkipFilePicker = true
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            code: bracket,
 | 
			
		||||
          }
 | 
			
		||||
        )
 | 
			
		||||
  test('ensure you CAN export while an export is already going', async ({
 | 
			
		||||
    page,
 | 
			
		||||
    homePage,
 | 
			
		||||
  }) => {
 | 
			
		||||
    const u = await getUtils(page)
 | 
			
		||||
    await test.step('Set up the code and durations', async () => {
 | 
			
		||||
      await page.addInitScript(
 | 
			
		||||
        async ({ code }) => {
 | 
			
		||||
          localStorage.setItem('persistCode', code)
 | 
			
		||||
          ;(window as any).playwrightSkipFilePicker = true
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          code: bracket,
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
        await page.setBodyDimensions({ width: 1000, height: 500 })
 | 
			
		||||
      await page.setBodyDimensions({ width: 1000, height: 500 })
 | 
			
		||||
 | 
			
		||||
        await homePage.goToModelingScene()
 | 
			
		||||
        await u.waitForPageLoad()
 | 
			
		||||
      await homePage.goToModelingScene()
 | 
			
		||||
      await u.waitForPageLoad()
 | 
			
		||||
 | 
			
		||||
        // wait for execution done
 | 
			
		||||
        await u.openDebugPanel()
 | 
			
		||||
        await u.expectCmdLog('[data-message-type="execution-done"]')
 | 
			
		||||
        await u.closeDebugPanel()
 | 
			
		||||
      // wait for execution done
 | 
			
		||||
      await u.openDebugPanel()
 | 
			
		||||
      await u.expectCmdLog('[data-message-type="execution-done"]')
 | 
			
		||||
      await u.closeDebugPanel()
 | 
			
		||||
 | 
			
		||||
        // expect zero errors in guter
 | 
			
		||||
        await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
 | 
			
		||||
      })
 | 
			
		||||
      // expect zero errors in guter
 | 
			
		||||
      await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
      const errorToastMessage = page.getByText(`Error while exporting`)
 | 
			
		||||
      const exportingToastMessage = page.getByText(`Exporting...`)
 | 
			
		||||
      const engineErrorToastMessage = page.getByText(`Nothing to export`)
 | 
			
		||||
      const alreadyExportingToastMessage = page.getByText(`Already exporting`)
 | 
			
		||||
      const successToastMessage = page.getByText(`Exported successfully`)
 | 
			
		||||
    const errorToastMessage = page.getByText(`Error while exporting`)
 | 
			
		||||
    const exportingToastMessage = page.getByText(`Exporting...`)
 | 
			
		||||
    const engineErrorToastMessage = page.getByText(`Nothing to export`)
 | 
			
		||||
    const alreadyExportingToastMessage = page.getByText(`Already exporting`)
 | 
			
		||||
    const successToastMessage = page.getByText(`Exported successfully`)
 | 
			
		||||
 | 
			
		||||
      await test.step('second export', async () => {
 | 
			
		||||
        await clickExportButton(page)
 | 
			
		||||
    await test.step('second export', async () => {
 | 
			
		||||
      await clickExportButton(page)
 | 
			
		||||
 | 
			
		||||
        await expect(exportingToastMessage).toBeVisible()
 | 
			
		||||
      await expect(exportingToastMessage).toBeVisible()
 | 
			
		||||
 | 
			
		||||
        await clickExportButton(page)
 | 
			
		||||
      await clickExportButton(page)
 | 
			
		||||
 | 
			
		||||
        await test.step('The first export still succeeds', async () => {
 | 
			
		||||
          await Promise.all([
 | 
			
		||||
            expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 }),
 | 
			
		||||
            expect(errorToastMessage).not.toBeVisible(),
 | 
			
		||||
            expect(engineErrorToastMessage).not.toBeVisible(),
 | 
			
		||||
            expect(successToastMessage).toBeVisible({ timeout: 15_000 }),
 | 
			
		||||
            expect(alreadyExportingToastMessage).not.toBeVisible({
 | 
			
		||||
              timeout: 15_000,
 | 
			
		||||
            }),
 | 
			
		||||
          ])
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      await test.step('Successful, unblocked export', async () => {
 | 
			
		||||
        // Try exporting again.
 | 
			
		||||
        await clickExportButton(page)
 | 
			
		||||
 | 
			
		||||
        // Find the toast.
 | 
			
		||||
        // Look out for the toast message
 | 
			
		||||
        await expect(exportingToastMessage).toBeVisible()
 | 
			
		||||
 | 
			
		||||
        // Expect it to succeed.
 | 
			
		||||
      await test.step('The first export still succeeds', async () => {
 | 
			
		||||
        await Promise.all([
 | 
			
		||||
          expect(exportingToastMessage).not.toBeVisible(),
 | 
			
		||||
          expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 }),
 | 
			
		||||
          expect(errorToastMessage).not.toBeVisible(),
 | 
			
		||||
          expect(engineErrorToastMessage).not.toBeVisible(),
 | 
			
		||||
          expect(alreadyExportingToastMessage).not.toBeVisible(),
 | 
			
		||||
          expect(successToastMessage).toBeVisible({ timeout: 15_000 }),
 | 
			
		||||
          expect(alreadyExportingToastMessage).not.toBeVisible({
 | 
			
		||||
            timeout: 15_000,
 | 
			
		||||
          }),
 | 
			
		||||
        ])
 | 
			
		||||
 | 
			
		||||
        await expect(successToastMessage).toHaveCount(2)
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    await test.step('Successful, unblocked export', async () => {
 | 
			
		||||
      // Try exporting again.
 | 
			
		||||
      await clickExportButton(page)
 | 
			
		||||
 | 
			
		||||
      // Find the toast.
 | 
			
		||||
      // Look out for the toast message
 | 
			
		||||
      await expect(exportingToastMessage).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // Expect it to succeed.
 | 
			
		||||
      await Promise.all([
 | 
			
		||||
        expect(exportingToastMessage).not.toBeVisible(),
 | 
			
		||||
        expect(errorToastMessage).not.toBeVisible(),
 | 
			
		||||
        expect(engineErrorToastMessage).not.toBeVisible(),
 | 
			
		||||
        expect(alreadyExportingToastMessage).not.toBeVisible(),
 | 
			
		||||
      ])
 | 
			
		||||
 | 
			
		||||
      await expect(successToastMessage).toHaveCount(2)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test(
 | 
			
		||||
    `Network health indicator only appears in modeling view`,
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -47,7 +47,7 @@ test.setTimeout(60_000)
 | 
			
		||||
// up with another PR if we want this back.
 | 
			
		||||
test(
 | 
			
		||||
  'exports of each format should work',
 | 
			
		||||
  { tag: ['@snapshot', '@skipWin', '@skipMacos'] },
 | 
			
		||||
  { tag: ['@snapshot'] },
 | 
			
		||||
  async ({ page, context, scene, cmdBar, tronApp }) => {
 | 
			
		||||
    if (!tronApp) {
 | 
			
		||||
      fail()
 | 
			
		||||
 | 
			
		||||
@ -8,230 +8,235 @@ import {
 | 
			
		||||
} from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Test network and connection issues', {
 | 
			
		||||
  tag: ['@macOS'],
 | 
			
		||||
}, () => {
 | 
			
		||||
  test(
 | 
			
		||||
    'simulate network down and network little widget',
 | 
			
		||||
    { tag: '@skipLocalEngine' },
 | 
			
		||||
    async ({ page, homePage }) => {
 | 
			
		||||
      test.fixme(orRunWhenFullSuiteEnabled())
 | 
			
		||||
      const u = await getUtils(page)
 | 
			
		||||
      await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
test.describe(
 | 
			
		||||
  'Test network and connection issues',
 | 
			
		||||
  {
 | 
			
		||||
    tag: ['@macos', '@windows'],
 | 
			
		||||
  },
 | 
			
		||||
  () => {
 | 
			
		||||
    test(
 | 
			
		||||
      'simulate network down and network little widget',
 | 
			
		||||
      { tag: '@skipLocalEngine' },
 | 
			
		||||
      async ({ page, homePage }) => {
 | 
			
		||||
        test.fixme(orRunWhenFullSuiteEnabled())
 | 
			
		||||
        const u = await getUtils(page)
 | 
			
		||||
        await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
 | 
			
		||||
      await homePage.goToModelingScene()
 | 
			
		||||
        await homePage.goToModelingScene()
 | 
			
		||||
 | 
			
		||||
      const networkToggle = page.getByTestId('network-toggle')
 | 
			
		||||
        const networkToggle = page.getByTestId('network-toggle')
 | 
			
		||||
 | 
			
		||||
      // This is how we wait until the stream is online
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
      ).not.toBeDisabled({ timeout: 15000 })
 | 
			
		||||
        // This is how we wait until the stream is online
 | 
			
		||||
        await expect(
 | 
			
		||||
          page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
        ).not.toBeDisabled({ timeout: 15000 })
 | 
			
		||||
 | 
			
		||||
      const networkWidget = page.locator('[data-testid="network-toggle"]')
 | 
			
		||||
      await expect(networkWidget).toBeVisible()
 | 
			
		||||
      await networkWidget.hover()
 | 
			
		||||
        const networkWidget = page.locator('[data-testid="network-toggle"]')
 | 
			
		||||
        await expect(networkWidget).toBeVisible()
 | 
			
		||||
        await networkWidget.hover()
 | 
			
		||||
 | 
			
		||||
      const networkPopover = page.locator('[data-testid="network-popover"]')
 | 
			
		||||
      await expect(networkPopover).not.toBeVisible()
 | 
			
		||||
        const networkPopover = page.locator('[data-testid="network-popover"]')
 | 
			
		||||
        await expect(networkPopover).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // (First check) Expect the network to be up
 | 
			
		||||
      await expect(networkToggle).toContainText('Connected')
 | 
			
		||||
        // (First check) Expect the network to be up
 | 
			
		||||
        await expect(networkToggle).toContainText('Connected')
 | 
			
		||||
 | 
			
		||||
      // Click the network widget
 | 
			
		||||
      await networkWidget.click()
 | 
			
		||||
        // Click the network widget
 | 
			
		||||
        await networkWidget.click()
 | 
			
		||||
 | 
			
		||||
      // Check the modal opened.
 | 
			
		||||
      await expect(networkPopover).toBeVisible()
 | 
			
		||||
        // Check the modal opened.
 | 
			
		||||
        await expect(networkPopover).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // Click off the modal.
 | 
			
		||||
      await page.mouse.click(100, 100)
 | 
			
		||||
      await expect(networkPopover).not.toBeVisible()
 | 
			
		||||
        // Click off the modal.
 | 
			
		||||
        await page.mouse.click(100, 100)
 | 
			
		||||
        await expect(networkPopover).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // Turn off the network
 | 
			
		||||
      await u.emulateNetworkConditions({
 | 
			
		||||
        offline: true,
 | 
			
		||||
        // values of 0 remove any active throttling. crbug.com/456324#c9
 | 
			
		||||
        latency: 0,
 | 
			
		||||
        downloadThroughput: -1,
 | 
			
		||||
        uploadThroughput: -1,
 | 
			
		||||
      })
 | 
			
		||||
        // Turn off the network
 | 
			
		||||
        await u.emulateNetworkConditions({
 | 
			
		||||
          offline: true,
 | 
			
		||||
          // values of 0 remove any active throttling. crbug.com/456324#c9
 | 
			
		||||
          latency: 0,
 | 
			
		||||
          downloadThroughput: -1,
 | 
			
		||||
          uploadThroughput: -1,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      // Expect the network to be down
 | 
			
		||||
      await expect(networkToggle).toContainText('Problem')
 | 
			
		||||
        // Expect the network to be down
 | 
			
		||||
        await expect(networkToggle).toContainText('Problem')
 | 
			
		||||
 | 
			
		||||
      // Click the network widget
 | 
			
		||||
      await networkWidget.click()
 | 
			
		||||
        // Click the network widget
 | 
			
		||||
        await networkWidget.click()
 | 
			
		||||
 | 
			
		||||
      // Check the modal opened.
 | 
			
		||||
      await expect(networkPopover).toBeVisible()
 | 
			
		||||
        // Check the modal opened.
 | 
			
		||||
        await expect(networkPopover).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // Click off the modal.
 | 
			
		||||
      await page.mouse.click(0, 0)
 | 
			
		||||
      await expect(networkPopover).not.toBeVisible()
 | 
			
		||||
        // Click off the modal.
 | 
			
		||||
        await page.mouse.click(0, 0)
 | 
			
		||||
        await expect(networkPopover).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // Turn back on the network
 | 
			
		||||
      await u.emulateNetworkConditions({
 | 
			
		||||
        offline: false,
 | 
			
		||||
        // values of 0 remove any active throttling. crbug.com/456324#c9
 | 
			
		||||
        latency: 0,
 | 
			
		||||
        downloadThroughput: -1,
 | 
			
		||||
        uploadThroughput: -1,
 | 
			
		||||
      })
 | 
			
		||||
        // Turn back on the network
 | 
			
		||||
        await u.emulateNetworkConditions({
 | 
			
		||||
          offline: false,
 | 
			
		||||
          // values of 0 remove any active throttling. crbug.com/456324#c9
 | 
			
		||||
          latency: 0,
 | 
			
		||||
          downloadThroughput: -1,
 | 
			
		||||
          uploadThroughput: -1,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
      ).not.toBeDisabled({ timeout: 15000 })
 | 
			
		||||
        await expect(
 | 
			
		||||
          page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
        ).not.toBeDisabled({ timeout: 15000 })
 | 
			
		||||
 | 
			
		||||
      // (Second check) expect the network to be up
 | 
			
		||||
      await expect(networkToggle).toContainText('Connected')
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
        // (Second check) expect the network to be up
 | 
			
		||||
        await expect(networkToggle).toContainText('Connected')
 | 
			
		||||
      }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
  test(
 | 
			
		||||
    'Engine disconnect & reconnect in sketch mode',
 | 
			
		||||
    { tag: '@skipLocalEngine' },
 | 
			
		||||
    async ({ page, homePage, toolbar, scene, cmdBar }) => {
 | 
			
		||||
      test.fixme(orRunWhenFullSuiteEnabled())
 | 
			
		||||
      const networkToggle = page.getByTestId('network-toggle')
 | 
			
		||||
    test(
 | 
			
		||||
      'Engine disconnect & reconnect in sketch mode',
 | 
			
		||||
      { tag: '@skipLocalEngine' },
 | 
			
		||||
      async ({ page, homePage, toolbar, scene, cmdBar }) => {
 | 
			
		||||
        test.fixme(orRunWhenFullSuiteEnabled())
 | 
			
		||||
        const networkToggle = page.getByTestId('network-toggle')
 | 
			
		||||
 | 
			
		||||
      const u = await getUtils(page)
 | 
			
		||||
      await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
      const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
        const u = await getUtils(page)
 | 
			
		||||
        await page.setBodyDimensions({ width: 1200, height: 500 })
 | 
			
		||||
        const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
 | 
			
		||||
      await homePage.goToModelingScene()
 | 
			
		||||
      await u.waitForPageLoad()
 | 
			
		||||
        await homePage.goToModelingScene()
 | 
			
		||||
        await u.waitForPageLoad()
 | 
			
		||||
 | 
			
		||||
      await u.openDebugPanel()
 | 
			
		||||
      // click on "Start Sketch" button
 | 
			
		||||
      await u.clearCommandLogs()
 | 
			
		||||
      await page.getByRole('button', { name: 'Start Sketch' }).click()
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
        await u.openDebugPanel()
 | 
			
		||||
        // click on "Start Sketch" button
 | 
			
		||||
        await u.clearCommandLogs()
 | 
			
		||||
        await page.getByRole('button', { name: 'Start Sketch' }).click()
 | 
			
		||||
        await page.waitForTimeout(100)
 | 
			
		||||
 | 
			
		||||
      // select a plane
 | 
			
		||||
      await page.mouse.click(700, 200)
 | 
			
		||||
        // select a plane
 | 
			
		||||
        await page.mouse.click(700, 200)
 | 
			
		||||
 | 
			
		||||
      await expect(page.locator('.cm-content')).toHaveText(
 | 
			
		||||
        `sketch001 = startSketchOn(XZ)`
 | 
			
		||||
      )
 | 
			
		||||
      await u.closeDebugPanel()
 | 
			
		||||
        await expect(page.locator('.cm-content')).toHaveText(
 | 
			
		||||
          `sketch001 = startSketchOn(XZ)`
 | 
			
		||||
        )
 | 
			
		||||
        await u.closeDebugPanel()
 | 
			
		||||
 | 
			
		||||
      await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
 | 
			
		||||
        await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
 | 
			
		||||
 | 
			
		||||
      const startXPx = 600
 | 
			
		||||
      await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
 | 
			
		||||
      await expect(page.locator('.cm-content')).toHaveText(
 | 
			
		||||
        `sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)`
 | 
			
		||||
      )
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
        const startXPx = 600
 | 
			
		||||
        await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
 | 
			
		||||
        await expect(page.locator('.cm-content')).toHaveText(
 | 
			
		||||
          `sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)`
 | 
			
		||||
        )
 | 
			
		||||
        await page.waitForTimeout(100)
 | 
			
		||||
 | 
			
		||||
      await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
        await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
 | 
			
		||||
        await page.waitForTimeout(100)
 | 
			
		||||
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.locator('.cm-content')
 | 
			
		||||
      ).toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)
 | 
			
		||||
        await expect(
 | 
			
		||||
          page.locator('.cm-content')
 | 
			
		||||
        ).toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)
 | 
			
		||||
      |> xLine(length = ${commonPoints.num1})`)
 | 
			
		||||
 | 
			
		||||
      // Expect the network to be up
 | 
			
		||||
      await expect(networkToggle).toContainText('Connected')
 | 
			
		||||
        // Expect the network to be up
 | 
			
		||||
        await expect(networkToggle).toContainText('Connected')
 | 
			
		||||
 | 
			
		||||
      // simulate network down
 | 
			
		||||
      await u.emulateNetworkConditions({
 | 
			
		||||
        offline: true,
 | 
			
		||||
        // values of 0 remove any active throttling. crbug.com/456324#c9
 | 
			
		||||
        latency: 0,
 | 
			
		||||
        downloadThroughput: -1,
 | 
			
		||||
        uploadThroughput: -1,
 | 
			
		||||
      })
 | 
			
		||||
        // simulate network down
 | 
			
		||||
        await u.emulateNetworkConditions({
 | 
			
		||||
          offline: true,
 | 
			
		||||
          // values of 0 remove any active throttling. crbug.com/456324#c9
 | 
			
		||||
          latency: 0,
 | 
			
		||||
          downloadThroughput: -1,
 | 
			
		||||
          uploadThroughput: -1,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      // Expect the network to be down
 | 
			
		||||
      await expect(networkToggle).toContainText('Problem')
 | 
			
		||||
        // Expect the network to be down
 | 
			
		||||
        await expect(networkToggle).toContainText('Problem')
 | 
			
		||||
 | 
			
		||||
      // Ensure we are not in sketch mode
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'Exit Sketch' })
 | 
			
		||||
      ).not.toBeVisible()
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
      ).toBeVisible()
 | 
			
		||||
        // Ensure we are not in sketch mode
 | 
			
		||||
        await expect(
 | 
			
		||||
          page.getByRole('button', { name: 'Exit Sketch' })
 | 
			
		||||
        ).not.toBeVisible()
 | 
			
		||||
        await expect(
 | 
			
		||||
          page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
        ).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // simulate network up
 | 
			
		||||
      await u.emulateNetworkConditions({
 | 
			
		||||
        offline: false,
 | 
			
		||||
        // values of 0 remove any active throttling. crbug.com/456324#c9
 | 
			
		||||
        latency: 0,
 | 
			
		||||
        downloadThroughput: -1,
 | 
			
		||||
        uploadThroughput: -1,
 | 
			
		||||
      })
 | 
			
		||||
        // simulate network up
 | 
			
		||||
        await u.emulateNetworkConditions({
 | 
			
		||||
          offline: false,
 | 
			
		||||
          // values of 0 remove any active throttling. crbug.com/456324#c9
 | 
			
		||||
          latency: 0,
 | 
			
		||||
          downloadThroughput: -1,
 | 
			
		||||
          uploadThroughput: -1,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
      // Wait for the app to be ready for use
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
      ).not.toBeDisabled({ timeout: 15000 })
 | 
			
		||||
        // Wait for the app to be ready for use
 | 
			
		||||
        await expect(
 | 
			
		||||
          page.getByRole('button', { name: 'Start Sketch' })
 | 
			
		||||
        ).not.toBeDisabled({ timeout: 15000 })
 | 
			
		||||
 | 
			
		||||
      // Expect the network to be up
 | 
			
		||||
      await expect(networkToggle).toContainText('Connected')
 | 
			
		||||
      await scene.settled(cmdBar)
 | 
			
		||||
        // Expect the network to be up
 | 
			
		||||
        await expect(networkToggle).toContainText('Connected')
 | 
			
		||||
        await scene.settled(cmdBar)
 | 
			
		||||
 | 
			
		||||
      // Click off the code pane.
 | 
			
		||||
      await page.mouse.click(100, 100)
 | 
			
		||||
        // Click off the code pane.
 | 
			
		||||
        await page.mouse.click(100, 100)
 | 
			
		||||
 | 
			
		||||
      // select a line
 | 
			
		||||
      await page
 | 
			
		||||
        .getByText(`startProfileAt(${commonPoints.startAt}, sketch001)`)
 | 
			
		||||
        .click()
 | 
			
		||||
        // select a line
 | 
			
		||||
        await page
 | 
			
		||||
          .getByText(`startProfileAt(${commonPoints.startAt}, sketch001)`)
 | 
			
		||||
          .click()
 | 
			
		||||
 | 
			
		||||
      // enter sketch again
 | 
			
		||||
      await toolbar.editSketch()
 | 
			
		||||
        // enter sketch again
 | 
			
		||||
        await toolbar.editSketch()
 | 
			
		||||
 | 
			
		||||
      // Click the line tool
 | 
			
		||||
      await page.getByRole('button', { name: 'line Line', exact: true }).click()
 | 
			
		||||
        // Click the line tool
 | 
			
		||||
        await page
 | 
			
		||||
          .getByRole('button', { name: 'line Line', exact: true })
 | 
			
		||||
          .click()
 | 
			
		||||
 | 
			
		||||
      await page.waitForTimeout(150)
 | 
			
		||||
        await page.waitForTimeout(150)
 | 
			
		||||
 | 
			
		||||
      const camCommand: EngineCommand = {
 | 
			
		||||
        type: 'modeling_cmd_req',
 | 
			
		||||
        cmd_id: uuidv4(),
 | 
			
		||||
        cmd: {
 | 
			
		||||
          type: 'default_camera_look_at',
 | 
			
		||||
          center: { x: 109, y: 0, z: -152 },
 | 
			
		||||
          vantage: { x: 115, y: -505, z: -152 },
 | 
			
		||||
          up: { x: 0, y: 0, z: 1 },
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
      const updateCamCommand: EngineCommand = {
 | 
			
		||||
        type: 'modeling_cmd_req',
 | 
			
		||||
        cmd_id: uuidv4(),
 | 
			
		||||
        cmd: {
 | 
			
		||||
          type: 'default_camera_get_settings',
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
      await toolbar.openPane('debug')
 | 
			
		||||
      await u.sendCustomCmd(camCommand)
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
      await u.sendCustomCmd(updateCamCommand)
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
        const camCommand: EngineCommand = {
 | 
			
		||||
          type: 'modeling_cmd_req',
 | 
			
		||||
          cmd_id: uuidv4(),
 | 
			
		||||
          cmd: {
 | 
			
		||||
            type: 'default_camera_look_at',
 | 
			
		||||
            center: { x: 109, y: 0, z: -152 },
 | 
			
		||||
            vantage: { x: 115, y: -505, z: -152 },
 | 
			
		||||
            up: { x: 0, y: 0, z: 1 },
 | 
			
		||||
          },
 | 
			
		||||
        }
 | 
			
		||||
        const updateCamCommand: EngineCommand = {
 | 
			
		||||
          type: 'modeling_cmd_req',
 | 
			
		||||
          cmd_id: uuidv4(),
 | 
			
		||||
          cmd: {
 | 
			
		||||
            type: 'default_camera_get_settings',
 | 
			
		||||
          },
 | 
			
		||||
        }
 | 
			
		||||
        await toolbar.openPane('debug')
 | 
			
		||||
        await u.sendCustomCmd(camCommand)
 | 
			
		||||
        await page.waitForTimeout(100)
 | 
			
		||||
        await u.sendCustomCmd(updateCamCommand)
 | 
			
		||||
        await page.waitForTimeout(100)
 | 
			
		||||
 | 
			
		||||
      // click to continue profile
 | 
			
		||||
      await page.mouse.click(1007, 400)
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
      // Ensure we can continue sketching
 | 
			
		||||
      await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
 | 
			
		||||
      await expect
 | 
			
		||||
        .poll(u.normalisedEditorCode)
 | 
			
		||||
        .toBe(`sketch001 = startSketchOn(XZ)
 | 
			
		||||
        // click to continue profile
 | 
			
		||||
        await page.mouse.click(1007, 400)
 | 
			
		||||
        await page.waitForTimeout(100)
 | 
			
		||||
        // Ensure we can continue sketching
 | 
			
		||||
        await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
 | 
			
		||||
        await expect
 | 
			
		||||
          .poll(u.normalisedEditorCode)
 | 
			
		||||
          .toBe(`sketch001 = startSketchOn(XZ)
 | 
			
		||||
profile001 = startProfileAt([12.34, -12.34], sketch001)
 | 
			
		||||
  |> xLine(length = 12.34)
 | 
			
		||||
  |> line(end = [-12.34, 12.34])
 | 
			
		||||
 | 
			
		||||
`)
 | 
			
		||||
      await page.waitForTimeout(100)
 | 
			
		||||
      await page.mouse.click(startXPx, 500 - PUR * 20)
 | 
			
		||||
        await page.waitForTimeout(100)
 | 
			
		||||
        await page.mouse.click(startXPx, 500 - PUR * 20)
 | 
			
		||||
 | 
			
		||||
      await expect
 | 
			
		||||
        .poll(u.normalisedEditorCode)
 | 
			
		||||
        .toBe(`sketch001 = startSketchOn(XZ)
 | 
			
		||||
        await expect
 | 
			
		||||
          .poll(u.normalisedEditorCode)
 | 
			
		||||
          .toBe(`sketch001 = startSketchOn(XZ)
 | 
			
		||||
profile001 = startProfileAt([12.34, -12.34], sketch001)
 | 
			
		||||
  |> xLine(length = 12.34)
 | 
			
		||||
  |> line(end = [-12.34, 12.34])
 | 
			
		||||
@ -239,21 +244,22 @@ profile001 = startProfileAt([12.34, -12.34], sketch001)
 | 
			
		||||
 | 
			
		||||
`)
 | 
			
		||||
 | 
			
		||||
      // Unequip line tool
 | 
			
		||||
      await page.keyboard.press('Escape')
 | 
			
		||||
      // Make sure we didn't pop out of sketch mode.
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'Exit Sketch' })
 | 
			
		||||
      ).toBeVisible()
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'line Line', exact: true })
 | 
			
		||||
      ).not.toHaveAttribute('aria-pressed', 'true')
 | 
			
		||||
        // Unequip line tool
 | 
			
		||||
        await page.keyboard.press('Escape')
 | 
			
		||||
        // Make sure we didn't pop out of sketch mode.
 | 
			
		||||
        await expect(
 | 
			
		||||
          page.getByRole('button', { name: 'Exit Sketch' })
 | 
			
		||||
        ).toBeVisible()
 | 
			
		||||
        await expect(
 | 
			
		||||
          page.getByRole('button', { name: 'line Line', exact: true })
 | 
			
		||||
        ).not.toHaveAttribute('aria-pressed', 'true')
 | 
			
		||||
 | 
			
		||||
      // Exit sketch
 | 
			
		||||
      await page.keyboard.press('Escape')
 | 
			
		||||
      await expect(
 | 
			
		||||
        page.getByRole('button', { name: 'Exit Sketch' })
 | 
			
		||||
      ).not.toBeVisible()
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
        // Exit sketch
 | 
			
		||||
        await page.keyboard.press('Escape')
 | 
			
		||||
        await expect(
 | 
			
		||||
          page.getByRole('button', { name: 'Exit Sketch' })
 | 
			
		||||
        ).not.toBeVisible()
 | 
			
		||||
      }
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ import { uuidv4 } from '@src/lib/utils'
 | 
			
		||||
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Testing Camera Movement', () => {
 | 
			
		||||
  test('Can move camera reliably', async ({
 | 
			
		||||
    page,
 | 
			
		||||
    context,
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ import {
 | 
			
		||||
} from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Testing constraints', () => {
 | 
			
		||||
  test('Can constrain line length', async ({ page, homePage }) => {
 | 
			
		||||
    await page.addInitScript(async () => {
 | 
			
		||||
      localStorage.setItem(
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ import { TEST_CODE_GIZMO } from '@e2e/playwright/storageStates'
 | 
			
		||||
import { getUtils } from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Testing Gizmo', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Testing Gizmo', () => {
 | 
			
		||||
  const cases = [
 | 
			
		||||
    {
 | 
			
		||||
      testDescription: 'top view',
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ import {
 | 
			
		||||
} from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Testing segment overlays', () => {
 | 
			
		||||
  test('Hover over a segment should show its overlay, hovering over the input overlays should show its popover, clicking the input overlay should constrain/unconstrain it:\nfor the following segments', () => {
 | 
			
		||||
    // TODO: fix this test on mac after the electron migration
 | 
			
		||||
    test.fixme(orRunWhenFullSuiteEnabled())
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ import {
 | 
			
		||||
} from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Testing selections', () => {
 | 
			
		||||
  test.setTimeout(90_000)
 | 
			
		||||
  test('Selections work on fresh and edited sketch', async ({
 | 
			
		||||
    page,
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
test.describe(
 | 
			
		||||
  'Testing settings',
 | 
			
		||||
  {
 | 
			
		||||
    tag: ['@macOS'],
 | 
			
		||||
    tag: ['@macos', '@windows'],
 | 
			
		||||
  },
 | 
			
		||||
  () => {
 | 
			
		||||
    test('Stored settings are validated and fall back to defaults', async ({
 | 
			
		||||
@ -281,7 +281,7 @@ test.describe(
 | 
			
		||||
 | 
			
		||||
    test(
 | 
			
		||||
      `Project settings override user settings on desktop`,
 | 
			
		||||
      { tag: ['@electron', '@skipWin'] },
 | 
			
		||||
      { tag: ['@electron'] },
 | 
			
		||||
      async ({ context, page }, testInfo) => {
 | 
			
		||||
        test.fixme(orRunWhenFullSuiteEnabled())
 | 
			
		||||
        const projectName = 'bracket'
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ import {
 | 
			
		||||
} from '@e2e/playwright/test-utils'
 | 
			
		||||
import { expect, test } from '@e2e/playwright/zoo-test'
 | 
			
		||||
 | 
			
		||||
test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
test.describe('Text-to-CAD tests', () => {
 | 
			
		||||
  test('basic lego happy case', async ({ page, homePage }) => {
 | 
			
		||||
    const u = await getUtils(page)
 | 
			
		||||
 | 
			
		||||
@ -436,93 +436,92 @@ test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => {
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  // This will be fine once greg makes prompt at top of file deterministic
 | 
			
		||||
  test(
 | 
			
		||||
    'can do many at once and get many prompts back, and interact with many',
 | 
			
		||||
    { tag: ['@skipWin'] },
 | 
			
		||||
    async ({ page, homePage }) => {
 | 
			
		||||
      test.fixme(orRunWhenFullSuiteEnabled())
 | 
			
		||||
      // Let this test run longer since we've seen it timeout.
 | 
			
		||||
      test.setTimeout(180_000)
 | 
			
		||||
  test('can do many at once and get many prompts back, and interact with many', async ({
 | 
			
		||||
    page,
 | 
			
		||||
    homePage,
 | 
			
		||||
  }) => {
 | 
			
		||||
    test.fixme(orRunWhenFullSuiteEnabled())
 | 
			
		||||
    // Let this test run longer since we've seen it timeout.
 | 
			
		||||
    test.setTimeout(180_000)
 | 
			
		||||
 | 
			
		||||
      const u = await getUtils(page)
 | 
			
		||||
    const u = await getUtils(page)
 | 
			
		||||
 | 
			
		||||
      await page.setBodyDimensions({ width: 1000, height: 500 })
 | 
			
		||||
    await page.setBodyDimensions({ width: 1000, height: 500 })
 | 
			
		||||
 | 
			
		||||
      await homePage.goToModelingScene()
 | 
			
		||||
      await u.waitForPageLoad()
 | 
			
		||||
    await homePage.goToModelingScene()
 | 
			
		||||
    await u.waitForPageLoad()
 | 
			
		||||
 | 
			
		||||
      await sendPromptFromCommandBar(page, 'a 2x4 lego')
 | 
			
		||||
    await sendPromptFromCommandBar(page, 'a 2x4 lego')
 | 
			
		||||
 | 
			
		||||
      await sendPromptFromCommandBar(page, 'a 2x8 lego')
 | 
			
		||||
    await sendPromptFromCommandBar(page, 'a 2x8 lego')
 | 
			
		||||
 | 
			
		||||
      await sendPromptFromCommandBar(page, 'a 2x10 lego')
 | 
			
		||||
    await sendPromptFromCommandBar(page, 'a 2x10 lego')
 | 
			
		||||
 | 
			
		||||
      // Find the toast.
 | 
			
		||||
      // Look out for the toast message
 | 
			
		||||
      const submittingToastMessage = page.getByText(
 | 
			
		||||
        `Submitting to Text-to-CAD API...`
 | 
			
		||||
      )
 | 
			
		||||
      await expect(submittingToastMessage.first()).toBeVisible()
 | 
			
		||||
    // Find the toast.
 | 
			
		||||
    // Look out for the toast message
 | 
			
		||||
    const submittingToastMessage = page.getByText(
 | 
			
		||||
      `Submitting to Text-to-CAD API...`
 | 
			
		||||
    )
 | 
			
		||||
    await expect(submittingToastMessage.first()).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      const generatingToastMessage = page.getByText(
 | 
			
		||||
        `Generating parametric model...`
 | 
			
		||||
      )
 | 
			
		||||
      await expect(generatingToastMessage.first()).toBeVisible({
 | 
			
		||||
        timeout: 10_000,
 | 
			
		||||
      })
 | 
			
		||||
    const generatingToastMessage = page.getByText(
 | 
			
		||||
      `Generating parametric model...`
 | 
			
		||||
    )
 | 
			
		||||
    await expect(generatingToastMessage.first()).toBeVisible({
 | 
			
		||||
      timeout: 10_000,
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
      const successToastMessage = page.getByText(`Text-to-CAD successful`)
 | 
			
		||||
      // We should have three success toasts.
 | 
			
		||||
      await expect(successToastMessage).toHaveCount(3, { timeout: 25_000 })
 | 
			
		||||
    const successToastMessage = page.getByText(`Text-to-CAD successful`)
 | 
			
		||||
    // We should have three success toasts.
 | 
			
		||||
    await expect(successToastMessage).toHaveCount(3, { timeout: 25_000 })
 | 
			
		||||
 | 
			
		||||
      await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
 | 
			
		||||
      await expect(page.getByText(`a 2x8 lego`)).toBeVisible()
 | 
			
		||||
      await expect(page.getByText(`a 2x10 lego`)).toBeVisible()
 | 
			
		||||
    await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
 | 
			
		||||
    await expect(page.getByText(`a 2x8 lego`)).toBeVisible()
 | 
			
		||||
    await expect(page.getByText(`a 2x10 lego`)).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // Ensure if you reject one, the others stay.
 | 
			
		||||
      const rejectButton = page.getByRole('button', { name: 'Reject' })
 | 
			
		||||
      await expect(rejectButton.first()).toBeVisible()
 | 
			
		||||
      // Click the reject button on the first toast.
 | 
			
		||||
      await rejectButton.first().click()
 | 
			
		||||
    // Ensure if you reject one, the others stay.
 | 
			
		||||
    const rejectButton = page.getByRole('button', { name: 'Reject' })
 | 
			
		||||
    await expect(rejectButton.first()).toBeVisible()
 | 
			
		||||
    // Click the reject button on the first toast.
 | 
			
		||||
    await rejectButton.first().click()
 | 
			
		||||
 | 
			
		||||
      // The first toast should disappear, but not the others.
 | 
			
		||||
      await expect(page.getByText(`a 2x10 lego`)).not.toBeVisible()
 | 
			
		||||
      await expect(page.getByText(`a 2x8 lego`)).toBeVisible()
 | 
			
		||||
      await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
 | 
			
		||||
    // The first toast should disappear, but not the others.
 | 
			
		||||
    await expect(page.getByText(`a 2x10 lego`)).not.toBeVisible()
 | 
			
		||||
    await expect(page.getByText(`a 2x8 lego`)).toBeVisible()
 | 
			
		||||
    await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // Ensure you can copy the code for one of the models remaining.
 | 
			
		||||
      const copyToClipboardButton = page.getByRole('button', {
 | 
			
		||||
        name: 'Accept',
 | 
			
		||||
      })
 | 
			
		||||
      await expect(copyToClipboardButton.first()).toBeVisible()
 | 
			
		||||
      // Click the button.
 | 
			
		||||
      await copyToClipboardButton.first().click()
 | 
			
		||||
    // Ensure you can copy the code for one of the models remaining.
 | 
			
		||||
    const copyToClipboardButton = page.getByRole('button', {
 | 
			
		||||
      name: 'Accept',
 | 
			
		||||
    })
 | 
			
		||||
    await expect(copyToClipboardButton.first()).toBeVisible()
 | 
			
		||||
    // Click the button.
 | 
			
		||||
    await copyToClipboardButton.first().click()
 | 
			
		||||
 | 
			
		||||
      // Do NOT do AI tests like this: "Expect the code to be pasted."
 | 
			
		||||
      // Reason: AI tests are NONDETERMINISTIC. Thus we need to be as most
 | 
			
		||||
      // general as we can for the assertion.
 | 
			
		||||
      // We can use Kolmogorov complexity as a measurement of the
 | 
			
		||||
      // "probably most minimal version of this program" to have a lower
 | 
			
		||||
      // bound to work with. It is completely by feel because there are
 | 
			
		||||
      // no proofs that any program is its smallest self.
 | 
			
		||||
      const code2x8 = await page.locator('.cm-content').innerText()
 | 
			
		||||
      await expect(code2x8.length).toBeGreaterThan(249)
 | 
			
		||||
    // Do NOT do AI tests like this: "Expect the code to be pasted."
 | 
			
		||||
    // Reason: AI tests are NONDETERMINISTIC. Thus we need to be as most
 | 
			
		||||
    // general as we can for the assertion.
 | 
			
		||||
    // We can use Kolmogorov complexity as a measurement of the
 | 
			
		||||
    // "probably most minimal version of this program" to have a lower
 | 
			
		||||
    // bound to work with. It is completely by feel because there are
 | 
			
		||||
    // no proofs that any program is its smallest self.
 | 
			
		||||
    const code2x8 = await page.locator('.cm-content').innerText()
 | 
			
		||||
    await expect(code2x8.length).toBeGreaterThan(249)
 | 
			
		||||
 | 
			
		||||
      // Ensure the final toast remains.
 | 
			
		||||
      await expect(page.getByText(`a 2x10 lego`)).not.toBeVisible()
 | 
			
		||||
      await expect(page.getByText(`Prompt: "a 2x8 lego`)).not.toBeVisible()
 | 
			
		||||
      await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
 | 
			
		||||
    // Ensure the final toast remains.
 | 
			
		||||
    await expect(page.getByText(`a 2x10 lego`)).not.toBeVisible()
 | 
			
		||||
    await expect(page.getByText(`Prompt: "a 2x8 lego`)).not.toBeVisible()
 | 
			
		||||
    await expect(page.getByText(`a 2x4 lego`)).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // Ensure you can copy the code for the final model.
 | 
			
		||||
      await expect(copyToClipboardButton).toBeVisible()
 | 
			
		||||
      // Click the button.
 | 
			
		||||
      await copyToClipboardButton.click()
 | 
			
		||||
    // Ensure you can copy the code for the final model.
 | 
			
		||||
    await expect(copyToClipboardButton).toBeVisible()
 | 
			
		||||
    // Click the button.
 | 
			
		||||
    await copyToClipboardButton.click()
 | 
			
		||||
 | 
			
		||||
      // Expect the code to be pasted.
 | 
			
		||||
      const code2x4 = await page.locator('.cm-content').innerText()
 | 
			
		||||
      await expect(code2x4.length).toBeGreaterThan(249)
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
    // Expect the code to be pasted.
 | 
			
		||||
    const code2x4 = await page.locator('.cm-content').innerText()
 | 
			
		||||
    await expect(code2x4.length).toBeGreaterThan(249)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('can do many at once with errors, clicking dismiss error does not dismiss all', async ({
 | 
			
		||||
    page,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								package.json
									
									
									
									
									
								
							@ -126,7 +126,7 @@
 | 
			
		||||
    "generate:machine-api": "npx openapi-typescript ./openapi/machine-api.json -o src/lib/machine-api.d.ts",
 | 
			
		||||
    "generate:samples-manifest": "cd public/kcl-samples && node generate-manifest.js",
 | 
			
		||||
    "tron:start": "electron-forge start",
 | 
			
		||||
    "chrome:test": "PLATFORM=web NODE_ENV=development playwright test --config=playwright.config.ts --project='Google Chrome' --grep-invert='@snapshot'",
 | 
			
		||||
    "chrome:test": "PLATFORM=web NODE_ENV=development playwright test --config=playwright.config.ts --project='Google Chrome' --grep-invert=@snapshot",
 | 
			
		||||
    "tronb:vite:dev": "vite build -c vite.main.config.ts -m development && vite build -c vite.preload.config.ts -m development && vite build -c vite.renderer.config.ts -m development",
 | 
			
		||||
    "tronb:vite:prod": "vite build -c vite.main.config.ts && vite build -c vite.preload.config.ts && vite build -c vite.renderer.config.ts",
 | 
			
		||||
    "tronb:package:dev": "npm run tronb:vite:dev && electron-builder --config electron-builder.yml",
 | 
			
		||||
@ -136,15 +136,15 @@
 | 
			
		||||
    "test:snapshots": "PLATFORM=web NODE_ENV=development playwright test --config=playwright.config.ts --grep=@snapshot --trace=on --shard=1/1",
 | 
			
		||||
    "test:unit": "vitest run --mode development --exclude **/kclSamples.test.ts",
 | 
			
		||||
    "test:unit:kcl-samples": "vitest run --mode development ./src/lang/kclSamples.test.ts",
 | 
			
		||||
    "test:playwright:electron": "playwright test --config=playwright.electron.config.ts --grep-invert='@snapshot'",
 | 
			
		||||
    "test:playwright:electron:windows": "playwright test --config=playwright.electron.config.ts --grep-invert=\"@skipWin|@snapshot\" --quiet",
 | 
			
		||||
    "test:playwright:electron:macos": "playwright test --config=playwright.electron.config.ts --grep='@macOS' --quiet",
 | 
			
		||||
    "test:playwright:electron:ubuntu": "playwright test --config=playwright.electron.config.ts --grep-invert='@skipLinux|@snapshot' --quiet",
 | 
			
		||||
    "test:playwright:electron:local": "npm run tronb:vite:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@snapshot'",
 | 
			
		||||
    "test:playwright:electron:windows:local": "npm run tronb:vite:dev && set NODE_ENV='development' && playwright test --config=playwright.electron.config.ts --grep-invert=\"@skipWin|@snapshot\"",
 | 
			
		||||
    "test:playwright:electron:macos:local": "npm run tronb:vite:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@skipMacos|@snapshot'",
 | 
			
		||||
    "test:playwright:electron:ubuntu:local": "npm run tronb:vite:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@skipLinux|@snapshot'",
 | 
			
		||||
    "test:playwright:electron:ubuntu:engine:local": "npm run tronb:vite:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert='@skipLinux|@snapshot|@skipLocalEngine'",
 | 
			
		||||
    "test:playwright:electron": "playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot",
 | 
			
		||||
    "test:playwright:electron:windows": "playwright test --config=playwright.electron.config.ts --grep=@windows --quiet",
 | 
			
		||||
    "test:playwright:electron:macos": "playwright test --config=playwright.electron.config.ts --grep=@macos --quiet",
 | 
			
		||||
    "test:playwright:electron:ubuntu": "playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot --quiet",
 | 
			
		||||
    "test:playwright:electron:local": "npm run tronb:vite:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot",
 | 
			
		||||
    "test:playwright:electron:windows:local": "npm run tronb:vite:dev && set NODE_ENV='development' && playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot",
 | 
			
		||||
    "test:playwright:electron:macos:local": "npm run tronb:vite:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot",
 | 
			
		||||
    "test:playwright:electron:ubuntu:local": "npm run tronb:vite:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot",
 | 
			
		||||
    "test:playwright:electron:ubuntu:engine:local": "npm run tronb:vite:dev && NODE_ENV=development playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot|@skipLocalEngine",
 | 
			
		||||
    "test:unit:local": "npm run simpleserver:bg && npm run test:unit; kill-port 3000",
 | 
			
		||||
    "test:unit:kcl-samples:local": "npm run simpleserver:bg && npm run test:unit:kcl-samples; kill-port 3000"
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user