diff --git a/e2e/playwright/projects.spec.ts b/e2e/playwright/projects.spec.ts index fece88f91..1f8a7a603 100644 --- a/e2e/playwright/projects.spec.ts +++ b/e2e/playwright/projects.spec.ts @@ -1,49 +1,41 @@ -import { test, expect } from '@playwright/test' +import { test, expect } from './zoo-test' import { doExport, executorInputPath, getUtils, isOutOfViewInScrollContainer, Paths, - setupElectron, - tearDown, createProject, + getPlaywrightDownloadDir, } from './test-utils' import fsp from 'fs/promises' import fs from 'fs' -import { join } from 'path' +import path from 'path' import { DEFAULT_PROJECT_KCL_FILE } from 'lib/constants' -test.afterEach(async ({ page }, testInfo) => { - await tearDown(page, testInfo) -}) - test( 'projects reload if a new one is created, deleted, or renamed externally', { tag: '@electron' }, - async ({ browserName }, testInfo) => { + async ({ context, page }, testInfo) => { let externalCreatedProjectName = 'external-created-project' let targetDir = '' - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - targetDir = dir - setTimeout(() => { - const myDir = join(dir, externalCreatedProjectName) - ;(async () => { - await fsp.mkdir(myDir) - await fsp.writeFile( - join(myDir, DEFAULT_PROJECT_KCL_FILE), - 'sca ba be bop de day wawa skee' - ) - })().catch(console.error) - }, 5000) - }, + await context.folderSetupFn(async (dir) => { + targetDir = dir + setTimeout(() => { + const myDir = path.join(dir, externalCreatedProjectName) + ;(async () => { + await fsp.mkdir(myDir) + await fsp.writeFile( + path.join(myDir, DEFAULT_PROJECT_KCL_FILE), + 'sca ba be bop de day wawa skee' + ) + })().catch(console.error) + }, 5000) }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) const projectLinks = page.getByTestId('project-link') @@ -51,34 +43,29 @@ test( await expect(projectLinks).toContainText(externalCreatedProjectName) await fsp.rename( - join(targetDir, externalCreatedProjectName), - join(targetDir, externalCreatedProjectName + '1') + path.join(targetDir, externalCreatedProjectName), + path.join(targetDir, externalCreatedProjectName + '1') ) externalCreatedProjectName += '1' await expect(projectLinks).toContainText(externalCreatedProjectName) - await fsp.rm(join(targetDir, externalCreatedProjectName), { + await fsp.rm(path.join(targetDir, externalCreatedProjectName), { recursive: true, force: true, }) await expect(projectLinks).toHaveCount(0) - await electronApp.close() } ) test( 'click help/keybindings from home page', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async () => {}, - }) + async ({ page }, testInfo) => { - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -90,27 +77,23 @@ test( // Make sure the keyboard shortcuts modal is visible. await expect(page.getByText('Enter Sketch Mode')).toBeVisible() - await electronApp.close() } ) test( 'click help/keybindings from project page', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - const bracketDir = join(dir, 'bracket') - await fsp.mkdir(bracketDir, { recursive: true }) - await fsp.copyFile( - executorInputPath('focusrite_scarlett_mounting_braket.kcl'), - join(bracketDir, 'main.kcl') - ) - }, + async ({ context, page }, testInfo) => { + await context.folderSetupFn(async (dir) => { + const bracketDir = path.join(dir, 'bracket') + await fsp.mkdir(bracketDir, { recursive: true }) + await fsp.copyFile( + executorInputPath('focusrite_scarlett_mounting_braket.kcl'), + path.join(bracketDir, 'main.kcl') + ) }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -132,7 +115,6 @@ test( // Make sure the keyboard shortcuts modal is visible. await expect(page.getByText('Enter Sketch Mode')).toBeVisible() - await electronApp.close() } ) @@ -468,19 +450,16 @@ test( test( 'when code with error first loads you get errors in console', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await fsp.mkdir(join(dir, 'broken-code'), { recursive: true }) - await fsp.copyFile( - executorInputPath('broken-code-test.kcl'), - join(dir, 'broken-code', 'main.kcl') - ) - }, + async ({ context, page }, testInfo) => { + await context.folderSetupFn(async (dir) => { + await fsp.mkdir(path.join(dir, 'broken-code'), { recursive: true }) + await fsp.copyFile( + executorInputPath('broken-code-test.kcl'), + path.join(dir, 'broken-code', 'main.kcl') + ) }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) await expect(page.getByText('broken-code')).toBeVisible() @@ -499,7 +478,6 @@ test( const crypticErrorText = `Expected a tag declarator` await expect(page.getByText(crypticErrorText).first()).toBeVisible() - await electronApp.close() } ) @@ -510,20 +488,17 @@ test.describe('Can export from electron app', () => { test( `Can export using ${method}`, { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - const bracketDir = join(dir, 'bracket') - await fsp.mkdir(bracketDir, { recursive: true }) - await fsp.copyFile( - executorInputPath('focusrite_scarlett_mounting_braket.kcl'), - join(bracketDir, 'main.kcl') - ) - }, + async ({ context, page }, testInfo) => { + await context.folderSetupFn(async (dir) => { + const bracketDir = path.join(dir, 'bracket') + await fsp.mkdir(bracketDir, { recursive: true }) + await fsp.copyFile( + executorInputPath('focusrite_scarlett_mounting_braket.kcl'), + path.join(bracketDir, 'main.kcl') + ) }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) const u = await getUtils(page) page.on('console', console.log) @@ -571,12 +546,17 @@ test.describe('Can export from electron app', () => { ) }) + const filepath = path.resolve( + getPlaywrightDownloadDir(page), + 'main.gltf' + ) + await test.step('Check the export size', async () => { await expect .poll( async () => { try { - const outputGltf = await fsp.readFile('main.gltf') + const outputGltf = await fsp.readFile(filepath) return outputGltf.byteLength } catch (e) { return 0 @@ -587,10 +567,9 @@ test.describe('Can export from electron app', () => { .toBeGreaterThan(300_000) // clean up exported file - await fsp.rm('main.gltf') + await fsp.rm(filepath) }) - await electronApp.close() } ) } @@ -598,38 +577,35 @@ test.describe('Can export from electron app', () => { test( 'Rename and delete projects, also spam arrow keys when renaming', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }) - await fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', - `${dir}/router-template-slate/main.kcl` - ) - const _1975 = new Date('1975-01-01T00:01:11') - fs.utimesSync(`${dir}/router-template-slate/main.kcl`, _1975, _1975) + async ({ context, page}, testInfo) => { + await context.folderSetupFn(async (dir) => { + await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }) + await fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', + `${dir}/router-template-slate/main.kcl` + ) + const _1975 = new Date('1975-01-01T00:01:11') + fs.utimesSync(`${dir}/router-template-slate/main.kcl`, _1975, _1975) - await fsp.mkdir(`${dir}/bracket`, { recursive: true }) - await fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl', - `${dir}/bracket/main.kcl` - ) - const _1985 = new Date('1985-01-01T00:02:22') - fs.utimesSync(`${dir}/bracket/main.kcl`, _1985, _1985) + await fsp.mkdir(`${dir}/bracket`, { recursive: true }) + await fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl', + `${dir}/bracket/main.kcl` + ) + const _1985 = new Date('1985-01-01T00:02:22') + fs.utimesSync(`${dir}/bracket/main.kcl`, _1985, _1985) - await new Promise((r) => setTimeout(r, 1_000)) - await fsp.mkdir(`${dir}/lego`, { recursive: true }) - await fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/lego.kcl', - `${dir}/lego/main.kcl` - ) - const _1995 = new Date('1995-01-01T00:03:33') - fs.utimesSync(`${dir}/lego/main.kcl`, _1995, _1995) - }, + await new Promise((r) => setTimeout(r, 1_000)) + await fsp.mkdir(`${dir}/lego`, { recursive: true }) + await fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/lego.kcl', + `${dir}/lego/main.kcl` + ) + const _1995 = new Date('1995-01-01T00:03:33') + fs.utimesSync(`${dir}/lego/main.kcl`, _1995, _1995) }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -795,25 +771,21 @@ test( await expect(page.getByText('bracket')).toBeVisible() }) - await electronApp.close() } ) test( 'pressing "delete" on home screen should do nothing', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }) - await fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', - `${dir}/router-template-slate/main.kcl` - ) - }, + async ({ context, page }, testInfo) => { + await context.folderSetupFn(async (dir) => { + await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }) + await fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', + `${dir}/router-template-slate/main.kcl` + ) }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -828,7 +800,6 @@ test( await expect(page.getByText('router-template-slate')).toBeVisible() await expect(page.getByText('Your Projects')).toBeVisible() - await electronApp.close() } ) @@ -836,17 +807,14 @@ test.describe(`Project management commands`, () => { test( `Rename from project page`, { tag: '@electron' }, - async ({ browserName }, testInfo) => { + async ({ context, page }, testInfo) => { const projectName = `my_project_to_rename` - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) - await fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', - `${dir}/${projectName}/main.kcl` - ) - }, + await context.folderSetupFn(async (dir) => { + await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) + await fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', + `${dir}/${projectName}/main.kcl` + ) }) const u = await getUtils(page) @@ -866,7 +834,7 @@ test.describe(`Project management commands`, () => { const toastMessage = page.getByText(`Successfully renamed`) await test.step(`Setup`, async () => { - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) await projectHomeLink.click() @@ -895,24 +863,20 @@ test.describe(`Project management commands`, () => { await expect(projectHomeLink.first()).toContainText(projectRenamedName) }) - await electronApp.close() } ) test( `Delete from project page`, { tag: '@electron' }, - async ({ browserName: _ }, testInfo) => { + async ({ context, page }, testInfo) => { const projectName = `my_project_to_delete` - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) - await fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', - `${dir}/${projectName}/main.kcl` - ) - }, + await context.folderSetupFn(async (dir) => { + await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) + await fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', + `${dir}/${projectName}/main.kcl` + ) }) const u = await getUtils(page) @@ -929,7 +893,7 @@ test.describe(`Project management commands`, () => { const noProjectsMessage = page.getByText('No Projects found') await test.step(`Setup`, async () => { - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) await projectHomeLink.click() @@ -952,23 +916,19 @@ test.describe(`Project management commands`, () => { await expect(noProjectsMessage).toBeVisible() }) - await electronApp.close() } ) test( `Rename from home page`, { tag: '@electron' }, - async ({ browserName: _ }, testInfo) => { + async ({ context, page }, testInfo) => { const projectName = `my_project_to_rename` - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) - await fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', - `${dir}/${projectName}/main.kcl` - ) - }, + await context.folderSetupFn(async (dir) => { + await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) + await fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', + `${dir}/${projectName}/main.kcl` + ) }) // Constants and locators @@ -986,7 +946,7 @@ test.describe(`Project management commands`, () => { const toastMessage = page.getByText(`Successfully renamed`) await test.step(`Setup`, async () => { - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) await expect(projectHomeLink).toBeVisible() }) @@ -1012,23 +972,19 @@ test.describe(`Project management commands`, () => { await expect(projectHomeLink).not.toHaveText(projectName) }) - await electronApp.close() } ) test( `Delete from home page`, { tag: '@electron' }, - async ({ browserName: _ }, testInfo) => { + async ({ context, page }, testInfo) => { const projectName = `my_project_to_delete` - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) - await fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', - `${dir}/${projectName}/main.kcl` - ) - }, + await context.folderSetupFn(async (dir) => { + await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) + await fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', + `${dir}/${projectName}/main.kcl` + ) }) // Constants and locators @@ -1044,7 +1000,7 @@ test.describe(`Project management commands`, () => { const noProjectsMessage = page.getByText('No Projects found') await test.step(`Setup`, async () => { - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) await expect(projectHomeLink).toBeVisible() }) @@ -1066,7 +1022,6 @@ test.describe(`Project management commands`, () => { await expect(noProjectsMessage).toBeVisible() }) - await electronApp.close() } ) }) @@ -1074,24 +1029,21 @@ test.describe(`Project management commands`, () => { test( 'File in the file pane should open with a single click', { tag: '@electron' }, - async ({ browserName }, testInfo) => { + async ({ context, page }, testInfo) => { const projectName = 'router-template-slate' - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) - await fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', - `${dir}/${projectName}/main.kcl` - ) - await fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl', - `${dir}/${projectName}/otherThingToClickOn.kcl` - ) - }, + await context.folderSetupFn(async (dir) => { + await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) + await fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', + `${dir}/${projectName}/main.kcl` + ) + await fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl', + `${dir}/${projectName}/otherThingToClickOn.kcl` + ) }) const u = await getUtils(page) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -1116,34 +1068,30 @@ test( 'A mounting bracket for the Focusrite Scarlett Solo audio interface' ) - await electronApp.close() } ) test( 'Nested directories in project without main.kcl do not create main.kcl', { tag: '@electron' }, - async ({ browserName }, testInfo) => { + async ({ context, page }, testInfo) => { let testDir: string | undefined - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await fsp.mkdir(join(dir, 'router-template-slate', 'nested'), { - recursive: true, - }) - await fsp.copyFile( - executorInputPath('router-template-slate.kcl'), - join(dir, 'router-template-slate', 'nested', 'slate.kcl') - ) - await fsp.copyFile( - executorInputPath('focusrite_scarlett_mounting_braket.kcl'), - join(dir, 'router-template-slate', 'nested', 'bracket.kcl') - ) - testDir = dir - }, + await context.folderSetupFn(async (dir) => { + await fsp.mkdir(path.join(dir, 'router-template-slate', 'nested'), { + recursive: true, + }) + await fsp.copyFile( + executorInputPath('router-template-slate.kcl'), + path.join(dir, 'router-template-slate', 'nested', 'slate.kcl') + ) + await fsp.copyFile( + executorInputPath('focusrite_scarlett_mounting_braket.kcl'), + path.join(dir, 'router-template-slate', 'nested', 'bracket.kcl') + ) + testDir = dir }) const u = await getUtils(page) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -1171,44 +1119,40 @@ test( if (testDir !== undefined) { // eslint-disable-next-line jest/no-conditional-expect await expect( - fsp.access(join(testDir, 'router-template-slate', 'main.kcl')) + fsp.access(path.join(testDir, 'router-template-slate', 'main.kcl')) ).rejects.toThrow() // eslint-disable-next-line jest/no-conditional-expect await expect( - fsp.access(join(testDir, 'router-template-slate', 'nested', 'main.kcl')) + fsp.access(path.join(testDir, 'router-template-slate', 'nested', 'main.kcl')) ).rejects.toThrow() } - await electronApp.close() } ) test.fixme( 'Deleting projects, can delete individual project, can still create projects after deleting all', { tag: '@electron' }, - async ({ browserName }, testInfo) => { + async ({ context, page }, testInfo) => { const projectData = [ ['router-template-slate', 'cylinder.kcl'], ['bracket', 'focusrite_scarlett_mounting_braket.kcl'], ['lego', 'lego.kcl'], ] - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - // Do these serially to ensure the order is correct - for (const [name, file] of projectData) { - await fsp.mkdir(join(dir, name), { recursive: true }) - await fsp.copyFile( - executorInputPath(file), - join(dir, name, `main.kcl`) - ) - // Wait 1s between each project to ensure the order is correct - await new Promise((r) => setTimeout(r, 1_000)) - } - }, + await context.folderSetupFn(async (dir) => { + // Do these serially to ensure the order is correct + for (const [name, file] of projectData) { + await fsp.mkdir(path.join(dir, name), { recursive: true }) + await fsp.copyFile( + executorInputPath(file), + path.join(dir, name, `main.kcl`) + ) + // Wait 1s between each project to ensure the order is correct + await new Promise((r) => setTimeout(r, 1_000)) + } }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) await test.step('delete the middle project, i.e. the bracket project', async () => { @@ -1262,35 +1206,31 @@ test.fixme( ).toBeVisible() }) - await electronApp.close() } ) test( 'Can load a file with CRLF line endings', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - const routerTemplateDir = join(dir, 'router-template-slate') - await fsp.mkdir(routerTemplateDir, { recursive: true }) + async ({ context, page }, testInfo) => { + await context.folderSetupFn(async (dir) => { + const routerTemplateDir = path.join(dir, 'router-template-slate') + await fsp.mkdir(routerTemplateDir, { recursive: true }) - const file = await fsp.readFile( - executorInputPath('router-template-slate.kcl'), - 'utf-8' - ) - // Replace both \r optionally so we don't end up with \r\r\n - const fileWithCRLF = file.replace(/\r?\n/g, '\r\n') - await fsp.writeFile( - join(routerTemplateDir, 'main.kcl'), - fileWithCRLF, - 'utf-8' - ) - }, + const file = await fsp.readFile( + executorInputPath('router-template-slate.kcl'), + 'utf-8' + ) + // Replace both \r optionally so we don't end up with \r\r\n + const fileWithCRLF = file.replace(/\r?\n/g, '\r\n') + await fsp.writeFile( + path.join(routerTemplateDir, 'main.kcl'), + fileWithCRLF, + 'utf-8' + ) }) const u = await getUtils(page) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -1304,36 +1244,32 @@ test( await expect(u.codeLocator).toContainText('templateGap') await expect(u.codeLocator).toContainText('minClampingDistance') - await electronApp.close() } ) test( 'Can sort projects on home page', { tag: '@electron' }, - async ({ browserName }, testInfo) => { + async ({ context, page }, testInfo) => { const projectData = [ ['router-template-slate', 'cylinder.kcl'], ['bracket', 'focusrite_scarlett_mounting_braket.kcl'], ['lego', 'lego.kcl'], ] - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - // Do these serially to ensure the order is correct - for (const [name, file] of projectData) { - await fsp.mkdir(join(dir, name), { recursive: true }) - await fsp.copyFile( - executorInputPath(file), - join(dir, name, `main.kcl`) - ) - // Wait 1s between each project to ensure the order is correct - await new Promise((r) => setTimeout(r, 1_000)) - } - }, + await context.folderSetupFn(async (dir) => { + // Do these serially to ensure the order is correct + for (const [name, file] of projectData) { + await fsp.mkdir(path.join(dir, name), { recursive: true }) + await fsp.copyFile( + executorInputPath(file), + path.join(dir, name, `main.kcl`) + ) + // Wait 1s between each project to ensure the order is correct + await new Promise((r) => setTimeout(r, 1_000)) + } }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) const getAllProjects = () => page.getByTestId('project-link').all() @@ -1416,17 +1352,15 @@ test( } }) - await electronApp.close() } ) test.fixme( 'When the project folder is empty, user can create new project and open it.', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ testInfo }) + async ({ page }, testInfo) => { const u = await getUtils(page) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -1509,49 +1443,45 @@ extrude001 = extrude(200, sketch001)`) await createProject({ name, page, returnHome: true }) await expect(projectLinks.getByText(name)).toBeVisible() } - await electronApp.close() } ) test( 'Opening a project should successfully load the stream, (regression test that this also works when switching between projects)', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await Promise.all([ - fsp.mkdir(join(dir, 'router-template-slate'), { recursive: true }), - fsp.mkdir(join(dir, 'bracket'), { recursive: true }), - ]) - await Promise.all([ - fsp.copyFile( - join( - 'src', - 'wasm-lib', - 'tests', - 'executor', - 'inputs', - 'router-template-slate.kcl' - ), - join(dir, 'router-template-slate', 'main.kcl') + async ({ context, page }, testInfo) => { + await context.folderSetupFn(async (dir) => { + await Promise.all([ + fsp.mkdir(path.join(dir, 'router-template-slate'), { recursive: true }), + fsp.mkdir(path.join(dir, 'bracket'), { recursive: true }), + ]) + await Promise.all([ + fsp.copyFile( + path.join( + 'src', + 'wasm-lib', + 'tests', + 'executor', + 'inputs', + 'router-template-slate.kcl' ), - fsp.copyFile( - join( - 'src', - 'wasm-lib', - 'tests', - 'executor', - 'inputs', - 'focusrite_scarlett_mounting_braket.kcl' - ), - join(dir, 'bracket', 'main.kcl') + path.join(dir, 'router-template-slate', 'main.kcl') + ), + fsp.copyFile( + path.join( + 'src', + 'wasm-lib', + 'tests', + 'executor', + 'inputs', + 'focusrite_scarlett_mounting_braket.kcl' ), - ]) - }, + path.join(dir, 'bracket', 'main.kcl') + ), + ]) }) const u = await getUtils(page) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -1611,34 +1541,30 @@ test( await expect(page.getByText('New Project')).toBeVisible() }) - await electronApp.close() } ) test( 'You can change the root projects directory and nothing is lost', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - await Promise.all([ - fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }), - fsp.mkdir(`${dir}/bracket`, { recursive: true }), - ]) - await Promise.all([ - fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', - `${dir}/router-template-slate/main.kcl` - ), - fsp.copyFile( - 'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl', - `${dir}/bracket/main.kcl` - ), - ]) - }, + async ({ context, page, electronApp }, testInfo) => { + await context.folderSetupFn(async (dir) => { + await Promise.all([ + fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }), + fsp.mkdir(`${dir}/bracket`, { recursive: true }), + ]) + await Promise.all([ + fsp.copyFile( + 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', + `${dir}/router-template-slate/main.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 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -1664,7 +1590,6 @@ test( .locator('section#projectDirectory input') .inputValue() - // Can't use Playwright filechooser since this is happening in electron. const handleFile = electronApp.evaluate( async ({ dialog }, filePaths) => { dialog.showOpenDialog = () => @@ -1675,7 +1600,7 @@ test( await page.getByTestId('project-directory-button').click() await handleFile - await expect(page.locator('section#projectDirectory input')).toHaveValue( + await expect.poll(() => page.locator('section#projectDirectory input').inputValue()).toContain( newProjectDirName ) @@ -1695,6 +1620,7 @@ test( await page.getByTestId('project-directory-settings-link').click() + const handleFile = electronApp.evaluate( async ({ dialog }, filePaths) => { dialog.showOpenDialog = () => @@ -1716,15 +1642,13 @@ test( await expect(page.getByText('bracket')).toBeVisible() await expect(page.getByText('router-template-slate')).toBeVisible() }) - - await electronApp.close() } ) test( 'Search projects on desktop home', { tag: '@electron' }, - async ({ browserName: _ }, testInfo) => { + async ({ context, page }, testInfo) => { const projectData = [ ['basic bracket', 'focusrite_scarlett_mounting_braket.kcl'], ['basic-cube', 'basic_fillet_cube_end.kcl'], @@ -1732,20 +1656,17 @@ test( ['router-template-slate', 'router-template-slate.kcl'], ['Ancient Temple Block', 'lego.kcl'], ] - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - // Do these serially to ensure the order is correct - for (const [name, file] of projectData) { - await fsp.mkdir(join(dir, name), { recursive: true }) - await fsp.copyFile( - executorInputPath(file), - join(dir, name, `main.kcl`) - ) - } - }, + await context.folderSetupFn(async (dir) => { + // Do these serially to ensure the order is correct + for (const [name, file] of projectData) { + await fsp.mkdir(path.join(dir, name), { recursive: true }) + await fsp.copyFile( + executorInputPath(file), + path.join(dir, name, `main.kcl`) + ) + } }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -1778,90 +1699,86 @@ test( } }) - await electronApp.close() } ) test( 'file pane is scrollable when there are many files', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - const testDir = join(dir, 'testProject') - await fsp.mkdir(testDir, { recursive: true }) - const fileNames = [ - 'angled_line.kcl', - 'basic_fillet_cube_close_opposite.kcl', - 'basic_fillet_cube_end.kcl', - 'basic_fillet_cube_next_adjacent.kcl', - 'basic_fillet_cube_previous_adjacent.kcl', - 'basic_fillet_cube_start.kcl', - 'big_number_angle_to_match_length_x.kcl', - 'big_number_angle_to_match_length_y.kcl', - 'close_arc.kcl', - 'computed_var.kcl', - 'cube-embedded.gltf', - 'cube.bin', - 'cube.glb', - 'cube.gltf', - 'cube.kcl', - 'cube.mtl', - 'cube.obj', - 'cylinder.kcl', - 'dimensions_match.kcl', - 'extrude-custom-plane.kcl', - 'extrude-inside-fn-with-tags.kcl', - 'fillet-and-shell.kcl', - 'fillet_duplicate_tags.kcl', - 'focusrite_scarlett_mounting_braket.kcl', - 'function_sketch.kcl', - 'function_sketch_with_position.kcl', - 'global-tags.kcl', - 'helix_defaults.kcl', - 'helix_defaults_negative_extrude.kcl', - 'helix_with_length.kcl', - 'i_shape.kcl', - 'kittycad_svg.kcl', - 'lego.kcl', - 'lsystem.kcl', - 'math.kcl', - 'member_expression_sketch.kcl', - 'mike_stress_test.kcl', - 'negative_args.kcl', - 'order-sketch-extrude-in-order.kcl', - 'order-sketch-extrude-out-of-order.kcl', - 'parametric.kcl', - 'parametric_with_tan_arc.kcl', - 'pattern_vase.kcl', - 'pentagon_fillet_sugar.kcl', - 'pipe_as_arg.kcl', - 'pipes_on_pipes.kcl', - 'riddle.kcl', - 'riddle_small.kcl', - 'router-template-slate.kcl', - 'scoped-tags.kcl', - 'server-rack-heavy.kcl', - 'server-rack-lite.kcl', - 'sketch_on_face.kcl', - 'sketch_on_face_circle_tagged.kcl', - 'sketch_on_face_end.kcl', - 'sketch_on_face_end_negative_extrude.kcl', - 'sketch_on_face_start.kcl', - 'tan_arc_x_line.kcl', - 'tangential_arc.kcl', - ] - for (const fileName of fileNames) { - await fsp.copyFile( - executorInputPath(fileName), - join(testDir, fileName) - ) - } - }, + async ({ context, page }, testInfo) => { + await context.folderSetupFn(async (dir) => { + const testDir = path.join(dir, 'testProject') + await fsp.mkdir(testDir, { recursive: true }) + const fileNames = [ + 'angled_line.kcl', + 'basic_fillet_cube_close_opposite.kcl', + 'basic_fillet_cube_end.kcl', + 'basic_fillet_cube_next_adjacent.kcl', + 'basic_fillet_cube_previous_adjacent.kcl', + 'basic_fillet_cube_start.kcl', + 'big_number_angle_to_match_length_x.kcl', + 'big_number_angle_to_match_length_y.kcl', + 'close_arc.kcl', + 'computed_var.kcl', + 'cube-embedded.gltf', + 'cube.bin', + 'cube.glb', + 'cube.gltf', + 'cube.kcl', + 'cube.mtl', + 'cube.obj', + 'cylinder.kcl', + 'dimensions_match.kcl', + 'extrude-custom-plane.kcl', + 'extrude-inside-fn-with-tags.kcl', + 'fillet-and-shell.kcl', + 'fillet_duplicate_tags.kcl', + 'focusrite_scarlett_mounting_braket.kcl', + 'function_sketch.kcl', + 'function_sketch_with_position.kcl', + 'global-tags.kcl', + 'helix_defaults.kcl', + 'helix_defaults_negative_extrude.kcl', + 'helix_with_length.kcl', + 'i_shape.kcl', + 'kittycad_svg.kcl', + 'lego.kcl', + 'lsystem.kcl', + 'math.kcl', + 'member_expression_sketch.kcl', + 'mike_stress_test.kcl', + 'negative_args.kcl', + 'order-sketch-extrude-in-order.kcl', + 'order-sketch-extrude-out-of-order.kcl', + 'parametric.kcl', + 'parametric_with_tan_arc.kcl', + 'pattern_vase.kcl', + 'pentagon_fillet_sugar.kcl', + 'pipe_as_arg.kcl', + 'pipes_on_pipes.kcl', + 'riddle.kcl', + 'riddle_small.kcl', + 'router-template-slate.kcl', + 'scoped-tags.kcl', + 'server-rack-heavy.kcl', + 'server-rack-lite.kcl', + 'sketch_on_face.kcl', + 'sketch_on_face_circle_tagged.kcl', + 'sketch_on_face_end.kcl', + 'sketch_on_face_end_negative_extrude.kcl', + 'sketch_on_face_start.kcl', + 'tan_arc_x_line.kcl', + 'tangential_arc.kcl', + ] + for (const fileName of fileNames) { + await fsp.copyFile( + executorInputPath(fileName), + path.join(testDir, fileName) + ) + } }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -1888,29 +1805,25 @@ test( ) }) - await electronApp.close() } ) test( 'select all in code editor does not actually select all, just what is visible (regression)', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - folderSetupFn: async (dir) => { - // src/wasm-lib/tests/executor/inputs/mike_stress_test.kcl - const name = 'mike_stress_test' - const testDir = join(dir, name) - await fsp.mkdir(testDir, { recursive: true }) - await fsp.copyFile( - executorInputPath(`${name}.kcl`), - join(testDir, 'main.kcl') - ) - }, + async ({ context, page }, testInfo) => { + await context.folderSetupFn(async (dir) => { + // src/wasm-lib/tests/executor/inputs/mike_stress_test.kcl + const name = 'mike_stress_test' + const testDir = path.join(dir, name) + await fsp.mkdir(testDir, { recursive: true }) + await fsp.copyFile( + executorInputPath(`${name}.kcl`), + path.join(testDir, 'main.kcl') + ) }) const u = await getUtils(page) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -1951,19 +1864,15 @@ test( await expect(u.codeLocator).toHaveText('') }) - await electronApp.close() } ) test( 'Settings persist across restarts', - { tag: '@electron' }, - async ({ browserName }, testInfo) => { + { tag: '@electron', cleanProjectDir: true }, + async ({ page }, testInfo) => { await test.step('We can change a user setting like theme', async () => { - const { electronApp, page } = await setupElectron({ - testInfo, - }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) @@ -1975,25 +1884,15 @@ test( await page.getByTestId('app-theme').selectOption('light') - await electronApp.close() }) await test.step('Starting the app again and we can see the same theme', async () => { - let { electronApp, page } = await setupElectron({ - testInfo, - cleanProjectDir: false, - }) - await page.setViewportSize({ width: 1200, height: 500 }) + await page.reload() + await page.setBodyDimensions({ width: 1200, height: 500 }) page.on('console', console.log) - - await page.getByTestId('user-sidebar-toggle').click() - - await page.getByTestId('user-settings').click() - await expect(page.getByTestId('app-theme')).toHaveValue('light') - await electronApp.close() }) } ) @@ -2002,11 +1901,8 @@ test( test.fixme( 'Original project name persist after onboarding', { tag: '@electron' }, - async ({ browserName }, testInfo) => { - const { electronApp, page } = await setupElectron({ - testInfo, - }) - await page.setViewportSize({ width: 1200, height: 500 }) + async ({ page }, testInfo) => { + await page.setBodyDimensions({ width: 1200, height: 500 }) const getAllProjects = () => page.getByTestId('project-link').all() page.on('console', console.log) @@ -2039,6 +1935,5 @@ test.fixme( } }) - await electronApp.close() } ) diff --git a/e2e/playwright/zoo-test.ts b/e2e/playwright/zoo-test.ts index 55750e9b4..1a026b937 100644 --- a/e2e/playwright/zoo-test.ts +++ b/e2e/playwright/zoo-test.ts @@ -73,6 +73,7 @@ export function test(desc, objOrFn, fnMaybe) { { context: tronApp.context, page: tronApp.page, + electronApp: tronApp.electronApp, ...fixtures, }, testInfo