export on project/file pane load playwright test (#3489)
* export on project/file pane load Signed-off-by: Jess Frazelle <github@jessfraz.com> add desktop exxport Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * Look at this (photo)Graph *in the voice of Nickelback* * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix lint Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixeds Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										184
									
								
								e2e/playwright/desktop-export.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								e2e/playwright/desktop-export.spec.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,184 @@
 | 
			
		||||
import { test, expect } from '@playwright/test'
 | 
			
		||||
import { getUtils, setupElectron, tearDown } from './test-utils'
 | 
			
		||||
import fsp from 'fs/promises'
 | 
			
		||||
 | 
			
		||||
test.afterEach(async ({ page }, testInfo) => {
 | 
			
		||||
  await tearDown(page, testInfo)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test(
 | 
			
		||||
  'export works on the first try',
 | 
			
		||||
  { tag: '@electron' },
 | 
			
		||||
  async ({ browserName }, testInfo) => {
 | 
			
		||||
    const { electronApp, page } = await setupElectron({
 | 
			
		||||
      testInfo,
 | 
			
		||||
      folderSetupFn: async (dir) => {
 | 
			
		||||
        await Promise.all([fsp.mkdir(`${dir}/bracket`, { recursive: true })])
 | 
			
		||||
        await Promise.all([
 | 
			
		||||
          fsp.copyFile(
 | 
			
		||||
            'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl',
 | 
			
		||||
            `${dir}/bracket/other.kcl`
 | 
			
		||||
          ),
 | 
			
		||||
          fsp.copyFile(
 | 
			
		||||
            'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl',
 | 
			
		||||
            `${dir}/bracket/main.kcl`
 | 
			
		||||
          ),
 | 
			
		||||
        ])
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
    await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
 | 
			
		||||
    page.on('console', console.log)
 | 
			
		||||
 | 
			
		||||
    await test.step('on open of project', async () => {
 | 
			
		||||
      await expect(page.getByText(`bracket`)).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // open the project
 | 
			
		||||
      await page.getByText(`bracket`).click()
 | 
			
		||||
 | 
			
		||||
      // wait for the project to load
 | 
			
		||||
      await expect(page.getByTestId('loading')).toBeAttached()
 | 
			
		||||
      await expect(page.getByTestId('loading')).not.toBeAttached({
 | 
			
		||||
        timeout: 20_000,
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      // expect zero errors in guter
 | 
			
		||||
      await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // export the model
 | 
			
		||||
      const exportButton = page.getByTestId('export-pane-button')
 | 
			
		||||
      await expect(exportButton).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      const gltfOption = page.getByText('glTF')
 | 
			
		||||
      const submitButton = page.getByText('Confirm Export')
 | 
			
		||||
      const exportingToastMessage = page.getByText(`Exporting...`)
 | 
			
		||||
      const errorToastMessage = page.getByText(`Error while exporting`)
 | 
			
		||||
      const engineErrorToastMessage = page.getByText(`Nothing to export`)
 | 
			
		||||
      const alreadyExportingToastMessage = page.getByText(`Already exporting`)
 | 
			
		||||
 | 
			
		||||
      // Click the export button
 | 
			
		||||
      await exportButton.click()
 | 
			
		||||
 | 
			
		||||
      await expect(gltfOption).toBeVisible()
 | 
			
		||||
      await expect(page.getByText('STL')).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      await page.keyboard.press('Enter')
 | 
			
		||||
 | 
			
		||||
      // Click the checkbox
 | 
			
		||||
      await expect(submitButton).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      await page.waitForTimeout(500)
 | 
			
		||||
 | 
			
		||||
      await page.keyboard.press('Enter')
 | 
			
		||||
 | 
			
		||||
      // Find the toast.
 | 
			
		||||
      // Look out for the toast message
 | 
			
		||||
      await expect(exportingToastMessage).toBeVisible()
 | 
			
		||||
      await expect(alreadyExportingToastMessage).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // Expect it to succeed.
 | 
			
		||||
      await expect(errorToastMessage).not.toBeVisible()
 | 
			
		||||
      await expect(engineErrorToastMessage).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      const successToastMessage = page.getByText(`Exported successfully`)
 | 
			
		||||
      await expect(successToastMessage).toBeVisible()
 | 
			
		||||
      await expect(exportingToastMessage).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      await test.step('Check the export size', async () => {
 | 
			
		||||
        await expect
 | 
			
		||||
          .poll(
 | 
			
		||||
            async () => {
 | 
			
		||||
              try {
 | 
			
		||||
                const outputGltf = await fsp.readFile('output.gltf')
 | 
			
		||||
                return outputGltf.byteLength
 | 
			
		||||
              } catch (e) {
 | 
			
		||||
                return 0
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
            { timeout: 15_000 }
 | 
			
		||||
          )
 | 
			
		||||
          .toBe(477327)
 | 
			
		||||
 | 
			
		||||
        // clean up output.gltf
 | 
			
		||||
        await fsp.rm('output.gltf')
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    await test.step('on open of file in file pane', async () => {
 | 
			
		||||
      const u = await getUtils(page)
 | 
			
		||||
      u.openFilePanel()
 | 
			
		||||
 | 
			
		||||
      const otherKclButton = page.getByRole('button', { name: 'other.kcl' })
 | 
			
		||||
 | 
			
		||||
      // Click the file
 | 
			
		||||
      await otherKclButton.click()
 | 
			
		||||
 | 
			
		||||
      // Close the file pane
 | 
			
		||||
      u.closeFilePanel()
 | 
			
		||||
 | 
			
		||||
      // wait for it to finish executing (todo: make this more robust)
 | 
			
		||||
      await page.waitForTimeout(1000)
 | 
			
		||||
      // expect zero errors in guter
 | 
			
		||||
      await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // export the model
 | 
			
		||||
      const exportButton = page.getByTestId('export-pane-button')
 | 
			
		||||
      await expect(exportButton).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      const gltfOption = page.getByText('glTF')
 | 
			
		||||
      const submitButton = page.getByText('Confirm Export')
 | 
			
		||||
      const exportingToastMessage = page.getByText(`Exporting...`)
 | 
			
		||||
      const errorToastMessage = page.getByText(`Error while exporting`)
 | 
			
		||||
      const engineErrorToastMessage = page.getByText(`Nothing to export`)
 | 
			
		||||
      const alreadyExportingToastMessage = page.getByText(`Already exporting`)
 | 
			
		||||
 | 
			
		||||
      // Click the export button
 | 
			
		||||
      await exportButton.click()
 | 
			
		||||
 | 
			
		||||
      await expect(gltfOption).toBeVisible()
 | 
			
		||||
      await expect(page.getByText('STL')).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      await page.keyboard.press('Enter')
 | 
			
		||||
 | 
			
		||||
      // Click the checkbox
 | 
			
		||||
      await expect(submitButton).toBeVisible()
 | 
			
		||||
 | 
			
		||||
      await page.keyboard.press('Enter')
 | 
			
		||||
 | 
			
		||||
      // Find the toast.
 | 
			
		||||
      // Look out for the toast message
 | 
			
		||||
      await expect(exportingToastMessage).toBeVisible()
 | 
			
		||||
      await expect(alreadyExportingToastMessage).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      // Expect it to succeed.
 | 
			
		||||
      await expect(errorToastMessage).not.toBeVisible()
 | 
			
		||||
      await expect(engineErrorToastMessage).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      const successToastMessage = page.getByText(`Exported successfully`)
 | 
			
		||||
      await expect(successToastMessage).toBeVisible()
 | 
			
		||||
      await expect(exportingToastMessage).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
      await test.step('Check the export size', async () => {
 | 
			
		||||
        await expect
 | 
			
		||||
          .poll(
 | 
			
		||||
            async () => {
 | 
			
		||||
              try {
 | 
			
		||||
                const outputGltf = await fsp.readFile('output.gltf')
 | 
			
		||||
                return outputGltf.byteLength
 | 
			
		||||
              } catch (e) {
 | 
			
		||||
                return 0
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
            { timeout: 15_000 }
 | 
			
		||||
          )
 | 
			
		||||
          .toBe(108944)
 | 
			
		||||
 | 
			
		||||
        // clean up output.gltf
 | 
			
		||||
        await fsp.rm('output.gltf')
 | 
			
		||||
      })
 | 
			
		||||
      await electronApp.close()
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    await electronApp.close()
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
@ -473,7 +473,7 @@ async function clickExportButton(page: Page) {
 | 
			
		||||
    // Click the export button
 | 
			
		||||
    await exportButton.click()
 | 
			
		||||
 | 
			
		||||
    // Click the stl.
 | 
			
		||||
    // Click the gltf.
 | 
			
		||||
    const gltfOption = page.getByRole('option', { name: 'glTF' })
 | 
			
		||||
    await expect(gltfOption).toBeVisible()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -148,6 +148,27 @@ async function closeDebugPanel(page: Page) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function openFilePanel(page: Page) {
 | 
			
		||||
  const fileLocator = page.getByTestId('files-pane-button')
 | 
			
		||||
  await expect(fileLocator).toBeVisible()
 | 
			
		||||
  const isOpen = (await fileLocator?.getAttribute('aria-pressed')) === 'true'
 | 
			
		||||
 | 
			
		||||
  if (!isOpen) {
 | 
			
		||||
    await fileLocator.click()
 | 
			
		||||
    await expect(fileLocator).toHaveAttribute('aria-pressed', 'true')
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function closeFilePanel(page: Page) {
 | 
			
		||||
  const fileLocator = page.getByTestId('files-pane-button')
 | 
			
		||||
  await expect(fileLocator).toBeVisible()
 | 
			
		||||
  const isOpen = (await fileLocator?.getAttribute('aria-pressed')) === 'true'
 | 
			
		||||
  if (isOpen) {
 | 
			
		||||
    await fileLocator.click()
 | 
			
		||||
    await expect(fileLocator).not.toHaveAttribute('aria-pressed', 'true')
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function waitForCmdReceive(page: Page, commandType: string) {
 | 
			
		||||
  return page
 | 
			
		||||
    .locator(`[data-receive-command-type="${commandType}"]`)
 | 
			
		||||
@ -321,6 +342,8 @@ export async function getUtils(page: Page) {
 | 
			
		||||
    closeKclCodePanel: () => closeKclCodePanel(page),
 | 
			
		||||
    openDebugPanel: () => openDebugPanel(page),
 | 
			
		||||
    closeDebugPanel: () => closeDebugPanel(page),
 | 
			
		||||
    openFilePanel: () => openFilePanel(page),
 | 
			
		||||
    closeFilePanel: () => closeFilePanel(page),
 | 
			
		||||
    openAndClearDebugPanel: async () => {
 | 
			
		||||
      await openDebugPanel(page)
 | 
			
		||||
      return clearCommandLogs(page)
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user