diff --git a/e2e/playwright/fixtures/fixtureSetup.ts b/e2e/playwright/fixtures/fixtureSetup.ts index 8ccbd1a44..67066c61c 100644 --- a/e2e/playwright/fixtures/fixtureSetup.ts +++ b/e2e/playwright/fixtures/fixtureSetup.ts @@ -20,11 +20,11 @@ export class AuthenticatedApp { public readonly page: Page public readonly context: BrowserContext public readonly testInfo: TestInfo - public readonly viewPortSize = { width: 1000, height: 500 } + public readonly viewPortSize = { width: 1200, height: 500 } constructor(context: BrowserContext, page: Page, testInfo: TestInfo) { - this.page = page this.context = context + this.page = page this.testInfo = testInfo } @@ -49,7 +49,7 @@ export class AuthenticatedApp { } } -interface Fixtures { +export interface Fixtures { app: AuthenticatedApp tronApp: AuthenticatedTronApp cmdBar: CmdBarFixture @@ -61,9 +61,10 @@ interface Fixtures { export class AuthenticatedTronApp { public readonly _page: Page public page: Page - public readonly context: BrowserContext + public context: BrowserContext public readonly testInfo: TestInfo public electronApp?: ElectronApplication + public readonly viewPortSize = { width: 1200, height: 500 } constructor(context: BrowserContext, page: Page, testInfo: TestInfo) { this._page = page @@ -79,15 +80,20 @@ export class AuthenticatedTronApp { appSettings?: Partial } = { fixtures: {} } ) { - const { electronApp, page } = await setupElectron({ + const { electronApp, page, context } = await setupElectron({ testInfo: this.testInfo, folderSetupFn: arg.folderSetupFn, cleanProjectDir: arg.cleanProjectDir, appSettings: arg.appSettings, }) this.page = page + this.context = context this.electronApp = electronApp - await page.setViewportSize({ width: 1200, height: 500 }) + + // Setup localStorage, addCookies, reload + await setup(this.context, this.page, this.testInfo) + + await page.setViewportSize(this.viewPortSize) for (const key of unsafeTypedKeys(arg.fixtures)) { const fixture = arg.fixtures[key] @@ -110,13 +116,7 @@ export class AuthenticatedTronApp { }) } -export const test = base.extend({ - app: async ({ page, context }, use, testInfo) => { - await use(new AuthenticatedApp(context, page, testInfo)) - }, - tronApp: async ({ page, context }, use, testInfo) => { - await use(new AuthenticatedTronApp(context, page, testInfo)) - }, +export const fixtures = { cmdBar: async ({ page }, use) => { await use(new CmdBarFixture(page)) }, @@ -129,13 +129,7 @@ export const test = base.extend({ scene: async ({ page }, use) => { await use(new SceneFixture(page)) }, - homePage: async ({ page }, use) => { + homePage: async ({ page }, use, testInfo) => { await use(new HomePageFixture(page)) }, -}) - -test.afterEach(async ({ page }, testInfo) => { - await tearDown(page, testInfo) -}) - -export { expect } from '@playwright/test' +} diff --git a/e2e/playwright/fixtures/homePageFixture.ts b/e2e/playwright/fixtures/homePageFixture.ts index 4987ad1f2..9f2312b5b 100644 --- a/e2e/playwright/fixtures/homePageFixture.ts +++ b/e2e/playwright/fixtures/homePageFixture.ts @@ -15,10 +15,14 @@ interface HomePageState { export class HomePageFixture { public page: Page + projectSection!: Locator projectCard!: Locator projectCardTitle!: Locator projectCardFile!: Locator projectCardFolder!: Locator + projectButtonNew!: Locator + projectButtonContinue!: Locator + projectTextName!: Locator sortByDateBtn!: Locator sortByNameBtn!: Locator @@ -29,11 +33,17 @@ export class HomePageFixture { reConstruct = (page: Page) => { this.page = page + this.projectSection = this.page.getByTestId('home-section') + this.projectCard = this.page.getByTestId('project-link') this.projectCardTitle = this.page.getByTestId('project-title') this.projectCardFile = this.page.getByTestId('project-file-count') this.projectCardFolder = this.page.getByTestId('project-folder-count') + this.projectButtonNew = this.page.getByTestId('home-new-file') + this.projectTextName = this.page.getByTestId('cmd-bar-arg-value') + this.projectButtonContinue = this.page.getByRole('button', { name: 'Continue' }) + this.sortByDateBtn = this.page.getByTestId('home-sort-by-modified') this.sortByNameBtn = this.page.getByTestId('home-sort-by-name') } @@ -94,10 +104,22 @@ export class HomePageFixture { .toEqual(expectedState) } + createAndGoToProject = async (projectTitle: string) => { + await expect(this.projectSection).not.toHaveText('Loading your Projects...') + await this.projectButtonNew.click() + await this.projectTextName.click() + await this.projectTextName.fill(projectTitle) + await this.projectButtonContinue.click() + } + openProject = async (projectTitle: string) => { const projectCard = this.projectCard.locator( this.page.getByText(projectTitle) ) await projectCard.click() } + + goToModelingScene = async (name?: string = "testDefault") => { + await this.createAndGoToProject(name) + } } diff --git a/e2e/playwright/null.spec.ts b/e2e/playwright/null.spec.ts new file mode 100644 index 000000000..14a5f3878 --- /dev/null +++ b/e2e/playwright/null.spec.ts @@ -0,0 +1,12 @@ +// These tests are meant to simply test starting and stopping the electron +// application, check it can make it to the project pane, and nothing more. +// It also tests our test wrappers are working. +// Additionally this serves as a nice minimal example. + +import { test as testZoo, expect } from './fixtures/fixtureSetup' + +testZoo.describe('Open the application', () => { + testZoo('see the project view', async ({ tronApp: { page, context } }) => { + await expect(page.getByTestId('home-section')).toBeVisible() + }) +}) diff --git a/e2e/playwright/sketch-tests.spec.ts b/e2e/playwright/sketch-tests.spec.ts index 1a315b000..48d1989d2 100644 --- a/e2e/playwright/sketch-tests.spec.ts +++ b/e2e/playwright/sketch-tests.spec.ts @@ -1,5 +1,7 @@ -import { test, expect, Page } from '@playwright/test' -import { test as test2, expect as expect2 } from './fixtures/fixtureSetup' +import { test, expect, Page } from './zoo-test' +import fs from 'node:fs/promises' +import path from 'node:path' +import { HomePageFixture } from './fixtures/homePageFixture' import { getMovementUtils, @@ -10,10 +12,6 @@ import { } from './test-utils' import { uuidv4, roundOff } from 'lib/utils' -test.beforeEach(async ({ context, page }, testInfo) => { - await setup(context, page, testInfo) -}) - test.afterEach(async ({ page }, testInfo) => { await tearDown(page, testInfo) }) @@ -22,6 +20,7 @@ test.describe('Sketch tests', () => { test('multi-sketch file shows multiple Edit Sketch buttons', async ({ page, context, + homePage, }) => { const u = await getUtils(page) const selectionsSnippets = { @@ -81,7 +80,7 @@ test.describe('Sketch tests', () => { ) await page.setViewportSize({ width: 1200, height: 500 }) - await u.waitForAuthSkipAppStart() + await homePage.goToModelingScene() // wait for execution done await u.openDebugPanel() @@ -108,6 +107,8 @@ test.describe('Sketch tests', () => { }) test('Can delete most of a sketch and the line tool will still work', async ({ page, + center, + homePage, }) => { const u = await getUtils(page) await page.addInitScript(async () => { @@ -120,12 +121,9 @@ test.describe('Sketch tests', () => { ) }) - await page.setViewportSize({ width: 1200, height: 500 }) - - await u.waitForAuthSkipAppStart() + await homePage.goToModelingScene() await expect(async () => { - await page.mouse.click(700, 200) await page.getByText('tangentialArcTo([24.95, -5.38], %)').click() await expect( page.getByRole('button', { name: 'Edit Sketch' }) @@ -151,6 +149,7 @@ test.describe('Sketch tests', () => { await page.waitForTimeout(100) await expect(async () => { + await page.mouse.move(700, 200, { step: 25 }) await page.mouse.click(700, 200) await expect.poll(u.normalisedEditorCode, { timeout: 1000 }) @@ -161,7 +160,7 @@ test.describe('Sketch tests', () => { `) }).toPass({ timeout: 40_000, intervals: [1_000] }) }) - test('Can exit selection of face', async ({ page }) => { + test('Can exit selection of face', async ({ page, homePage }) => { // Load the app with the code panes await page.addInitScript(async () => { localStorage.setItem('persistCode', ``) @@ -170,7 +169,7 @@ test.describe('Sketch tests', () => { const u = await getUtils(page) await page.setViewportSize({ width: 1200, height: 500 }) - await u.waitForAuthSkipAppStart() + await homePage.goToModelingScene() await page.getByRole('button', { name: 'Start Sketch' }).click() await expect( @@ -187,6 +186,7 @@ test.describe('Sketch tests', () => { test.describe('Can edit segments by dragging their handles', () => { const doEditSegmentsByDraggingHandle = async ( page: Page, + homePage: HomePageFixture, openPanes: string[] ) => { // Load the app with the code panes @@ -202,10 +202,9 @@ test.describe('Sketch tests', () => { }) const u = await getUtils(page) - await page.setViewportSize({ width: 1200, height: 500 }) + await homePage.goToModelingScene() - await u.waitForAuthSkipAppStart() - await expect( + await expect( page.getByRole('button', { name: 'Start Sketch' }) ).not.toBeDisabled() @@ -318,7 +317,7 @@ test.describe('Sketch tests', () => { |> line([1.97, 2.06], %) |> close(%)`) } - test('code pane open at start-handles', async ({ page }) => { + test('code pane open at start-handles', async ({ page, homePage }) => { // Load the app with the code panes await page.addInitScript(async () => { localStorage.setItem( @@ -331,10 +330,10 @@ test.describe('Sketch tests', () => { }) ) }) - await doEditSegmentsByDraggingHandle(page, ['code']) + await doEditSegmentsByDraggingHandle(page, homePage, ['code']) }) - test('code pane closed at start-handles', async ({ page }) => { + test('code pane closed at start-handles', async ({ page, homePage }) => { // Load the app with the code panes await page.addInitScript(async (persistModelingContext) => { localStorage.setItem( @@ -342,12 +341,13 @@ test.describe('Sketch tests', () => { JSON.stringify({ openPanes: [] }) ) }, PERSIST_MODELING_CONTEXT) - await doEditSegmentsByDraggingHandle(page, []) + await doEditSegmentsByDraggingHandle(page, homePage, []) }) }) test('Can edit a circle center and radius by dragging its handles', async ({ page, + homePage, }) => { const u = await getUtils(page) await page.addInitScript(async () => { @@ -358,9 +358,8 @@ test.describe('Sketch tests', () => { ) }) - await page.setViewportSize({ width: 1200, height: 500 }) + await homePage.goToModelingScene() - await u.waitForAuthSkipAppStart() await expect( page.getByRole('button', { name: 'Start Sketch' }) ).not.toBeDisabled() @@ -434,6 +433,7 @@ test.describe('Sketch tests', () => { }) test('Can edit a sketch that has been extruded in the same pipe', async ({ page, + homePage }) => { const u = await getUtils(page) await page.addInitScript(async () => { @@ -448,9 +448,8 @@ test.describe('Sketch tests', () => { ) }) - await page.setViewportSize({ width: 1200, height: 500 }) + await homePage.goToModelingScene() - await u.waitForAuthSkipAppStart() await expect( page.getByRole('button', { name: 'Start Sketch' }) ).not.toBeDisabled() @@ -504,11 +503,11 @@ test.describe('Sketch tests', () => { await page.waitForTimeout(100) 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 }, + sourcePosition: { x: lineEnd.x - 15, y: lineEnd.y }, + targetPosition: { x: lineEnd.x, y: lineEnd.y + 15 }, }) + await page.waitForTimeout(100) await expect(page.locator('.cm-content')).not.toHaveText(prevContent) prevContent = await page.locator('.cm-content').innerText() @@ -517,8 +516,8 @@ test.describe('Sketch tests', () => { await page.dragAndDrop('#stream', '#stream', { sourcePosition: { x: tangentEnd.x + 10, y: tangentEnd.y - 5 }, targetPosition: { - x: tangentEnd.x + dragPX, - y: tangentEnd.y + dragPX, + x: tangentEnd.x, + y: tangentEnd.y - 15, }, }) await page.waitForTimeout(100) @@ -528,8 +527,8 @@ test.describe('Sketch tests', () => { await expect(page.locator('.cm-content')) .toHaveText(`sketch001 = startSketchOn('XZ') |> startProfileAt([7.12, -12.68], %) - |> line([15.39, -2.78], %) - |> tangentialArcTo([27.6, -3.05], %) + |> line([12.68, -1.09], %) + |> tangentialArcTo([24.89, 0.68], %) |> close(%) |> extrude(5, %) `) @@ -537,6 +536,7 @@ test.describe('Sketch tests', () => { test('Can edit a sketch that has been revolved in the same pipe', async ({ page, + homePage, }) => { const u = await getUtils(page) await page.addInitScript(async () => { @@ -551,9 +551,8 @@ test.describe('Sketch tests', () => { ) }) - await page.setViewportSize({ width: 1200, height: 500 }) + await homePage.goToModelingScene() - await u.waitForAuthSkipAppStart() await expect( page.getByRole('button', { name: 'Start Sketch' }) ).not.toBeDisabled() @@ -636,12 +635,13 @@ test.describe('Sketch tests', () => { |> close(%) |> revolve({ axis: "X" }, %)`) }) - test('Can add multiple sketches', async ({ page }) => { + test('Can add multiple sketches', async ({ page, homePage }) => { const u = await getUtils(page) + const viewportSize = { width: 1200, height: 500 } await page.setViewportSize(viewportSize) - await u.waitForAuthSkipAppStart() + await homePage.goToModelingScene() await u.openDebugPanel() const center = { x: viewportSize.width / 2, y: viewportSize.height / 2 } @@ -738,8 +738,7 @@ test.describe('Sketch tests', () => { const u = await getUtils(page) await page.setViewportSize({ width: 1200, height: 500 }) - await u.waitForAuthSkipAppStart() - await u.openDebugPanel() + await u.openDebugPanel() const code = `sketch001 = startSketchOn('-XZ') |> startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(scale * 34.8)}], %) @@ -820,16 +819,19 @@ test.describe('Sketch tests', () => { await u.expectCmdLog('[data-message-type="execution-done"]') await u.removeCurrentCode() } - test('[0, 100, 100]', async ({ page }) => { + test('[0, 100, 100]', async ({ page, homePage }) => { + await homePage.goToModelingScene() await doSnapAtDifferentScales(page, [0, 100, 100], 0.01) }) - test('[0, 10000, 10000]', async ({ page }) => { + test('[0, 10000, 10000]', async ({ page, homePage }) => { + await homePage.goToModelingScene() await doSnapAtDifferentScales(page, [0, 10000, 10000]) }) }) test('exiting a close extrude, has the extrude button enabled ready to go', async ({ page, + homePage, }) => { // this was a regression https://github.com/KittyCAD/modeling-app/issues/2832 await page.addInitScript(async () => { @@ -849,7 +851,7 @@ test.describe('Sketch tests', () => { const u = await getUtils(page) await page.setViewportSize({ width: 1200, height: 500 }) - await u.waitForAuthSkipAppStart() + await homePage.goToModelingScene() // wait for execution done await u.openDebugPanel() @@ -885,7 +887,7 @@ test.describe('Sketch tests', () => { timeout: 10_000, }) }) - test("Existing sketch with bad code delete user's code", async ({ page }) => { + test("Existing sketch with bad code delete user's code", async ({ page, homePage }) => { // this was a regression https://github.com/KittyCAD/modeling-app/issues/2832 await page.addInitScript(async () => { localStorage.setItem( @@ -905,7 +907,7 @@ extrude001 = extrude(5, sketch001) const u = await getUtils(page) await page.setViewportSize({ width: 1200, height: 500 }) - await u.waitForAuthSkipAppStart() + await homePage.goToModelingScene() await u.openDebugPanel() await u.expectCmdLog('[data-message-type="execution-done"]') @@ -945,12 +947,8 @@ sketch002 = startSketchOn(extrude001, 'END') }) test('empty-scene default-planes act as expected', async ({ page, - browserName, + homePage, }) => { - test.skip( - browserName === 'webkit', - 'Skip on Safari until `window.tearDown` is working there' - ) /** * Tests the following things * 1) The the planes are there on load because the scene is empty @@ -963,9 +961,7 @@ sketch002 = startSketchOn(extrude001, 'END') */ const u = await getUtils(page) - await page.setViewportSize({ width: 1200, height: 500 }) - - await u.waitForAuthSkipAppStart() + await homePage.goToModelingScene() await u.openDebugPanel() await u.expectCmdLog('[data-message-type="execution-done"]') @@ -1013,7 +1009,7 @@ sketch002 = startSketchOn(extrude001, 'END') // click start Sketch await page.getByRole('button', { name: 'Start Sketch' }).click() - await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y, { steps: 5 }) + await page.mouse.move(XYPlanePoint.x, XYPlanePoint.y, { steps: 50 }) const hoveredColor: [number, number, number] = [93, 93, 127] // now that we're expecting the user to select a plan, it does respond to hover await expect @@ -1040,8 +1036,6 @@ sketch002 = startSketchOn(extrude001, 'END') ` ) }) - await page.reload() - await u.waitForAuthSkipAppStart() await u.openDebugPanel() await u.expectCmdLog('[data-message-type="execution-done"]') @@ -1055,12 +1049,8 @@ sketch002 = startSketchOn(extrude001, 'END') test('Can attempt to sketch on revolved face', async ({ page, - browserName, + homePage, }) => { - test.skip( - browserName === 'webkit', - 'Skip on Safari until `window.tearDown` is working there' - ) const u = await getUtils(page) await page.setViewportSize({ width: 1200, height: 500 }) @@ -1087,7 +1077,7 @@ sketch002 = startSketchOn(extrude001, 'END') ) }) - await u.waitForAuthSkipAppStart() + await homePage.goToModelingScene() await u.openDebugPanel() await u.expectCmdLog('[data-message-type="execution-done"]') @@ -1119,6 +1109,7 @@ sketch002 = startSketchOn(extrude001, 'END') test('Can sketch on face when user defined function was used in the sketch', async ({ page, + homePage, }) => { const u = await getUtils(page) await page.setViewportSize({ width: 1200, height: 500 }) @@ -1175,7 +1166,7 @@ const rail = startSketchOn('XZ') const center = { x: 600, y: 250 } const rectangleSize = 20 - await u.waitForAuthSkipAppStart() + await homePage.goToModelingScene() // Start a sketch await page.getByRole('button', { name: 'Start Sketch' }).click() @@ -1214,27 +1205,26 @@ const rail = startSketchOn('XZ') }) }) -test2.describe('Sketch mode should be toleratant to syntax errors', () => { - test2( +test.describe('Sketch mode should be toleratant to syntax errors', () => { + test( 'adding a syntax error, recovers after fixing', { tag: ['@skipWin'] }, - async ({ app, scene, editor, toolbar }) => { - test.skip( - process.platform === 'win32', - 'a codemirror error appears in this test only on windows, that causes the test to fail only because of our "no new error" logic, but it can not be replicated locally' - ) - const file = await app.getInputFile('e2e-can-sketch-on-chamfer.kcl') - await app.initialise(file) + async ({ page, homePage, context, scene, editor, toolbar }) => { + const file = await fs.readFile(path.resolve(__dirname, '../../', './src/wasm-lib/tests/executor/inputs/e2e-can-sketch-on-chamfer.kcl'), 'utf-8') + await context.addInitScript((file) => { + localStorage.setItem('persistCode', file) + }, file) + await homePage.goToModelingScene() const [objClick] = scene.makeMouseHelpers(600, 250) - const arrowHeadLocation = { x: 604, y: 129 } as const + const arrowHeadLocation = { x: 706, y: 129 } as const const arrowHeadWhite: [number, number, number] = [255, 255, 255] const backgroundGray: [number, number, number] = [28, 28, 28] const verifyArrowHeadColor = async (c: [number, number, number]) => scene.expectPixelColor(c, arrowHeadLocation, 15) await test.step('check chamfer selection changes cursor positon', async () => { - await expect2(async () => { + await expect(async () => { // sometimes initial click doesn't register await objClick() await editor.expectActiveLinesToBe([ @@ -1270,7 +1260,7 @@ test2.describe('Sketch mode should be toleratant to syntax errors', () => { // this checks sketch segments have been drawn await verifyArrowHeadColor(arrowHeadWhite) }) - await app.page.waitForTimeout(100) + await page.waitForTimeout(100) } ) }) diff --git a/e2e/playwright/test-utils.ts b/e2e/playwright/test-utils.ts index c75cc5467..a070a0fd9 100644 --- a/e2e/playwright/test-utils.ts +++ b/e2e/playwright/test-utils.ts @@ -798,6 +798,8 @@ export async function tearDown(page: Page, testInfo: TestInfo) { // It seems it's best to give the browser about 3s to close things // It's not super reliable but we have no real other choice for now await page.waitForTimeout(3000) + + await testInfo.tronApp.close() } // settingsOverrides may need to be augmented to take more generic items, @@ -887,8 +889,10 @@ export async function setupElectron({ ? { executablePath: process.env.ELECTRON_OVERRIDE_DIST_PATH + 'electron' } : {}), }) + const context = electronApp.context() const page = await electronApp.firstWindow() + context.on('console', console.log) page.on('console', console.log) @@ -924,7 +928,7 @@ export async function setupElectron({ await setup(context, page) - return { electronApp, page, dir: projectDirName } + return { electronApp, page, context, dir: projectDirName } } function failOnConsoleErrors(page: Page, testInfo?: TestInfo) { diff --git a/e2e/playwright/zoo-test.ts b/e2e/playwright/zoo-test.ts new file mode 100644 index 000000000..7d4726a51 --- /dev/null +++ b/e2e/playwright/zoo-test.ts @@ -0,0 +1,54 @@ +import { test as playwrightTestFn } from '@playwright/test' +import { fixtures, Fixtures, AuthenticatedTronApp } from './fixtures/fixtureSetup' +export { expect, Page, BrowserContext, TestInfo } from '@playwright/test' + +// Our custom decorated Zoo test object. Makes it easier to add fixtures, and +// switch between web and electron if needed. +const pwTestFnWithFixtures = playwrightTestFn.extend(fixtures) + +export function test(desc, objOrFn, fnMaybe) { + const hasTestConf = typeof objOrFn === 'object' + const fn = hasTestConf ? fnMaybe : objOrFn + + return pwTestFnWithFixtures(desc, hasTestConf ? objOrFn : {}, async ({ page, context, cmdBar, editor, toolbar, scene, homePage }, testInfo) => { + // To switch to web, change this to AuthenticatedApp from fixtureSetup.ts + const tronApp = new AuthenticatedTronApp( + context, + page, + testInfo + ) + + const fixtures: Fixtures = { cmdBar, editor, toolbar, scene, homePage } + await tronApp.initialise({ fixtures }) + + // We need to patch this because addInitScript will bind too late in our + // electron tests, never running. We need to call reload() after each call + // to guarantee it runs. + const oldContextAddInitScript = tronApp.context.addInitScript + tronApp.context.addInitScript = async function(a, b) { + await oldContextAddInitScript.apply(this, [a, b]) + await tronApp.page.reload() + } + + // No idea why we mix and match page and context's addInitScript but we do + const oldPageAddInitScript = tronApp.page.addInitScript + tronApp.page.addInitScript = async function(a, b) { + await oldPageAddInitScript.apply(this, [a, b]) + await tronApp.page.reload() + } + + await fn({ + context: tronApp.context, + page: tronApp.page, + ...fixtures + }, testInfo) + + testInfo.tronApp = tronApp + }) +} + +test.describe = pwTestFnWithFixtures.describe +test.beforeEach = pwTestFnWithFixtures.beforeEach +test.afterEach = pwTestFnWithFixtures.afterEach +test.step = pwTestFnWithFixtures.step +test.skip = pwTestFnWithFixtures.skip diff --git a/package.json b/package.json index 52d0504a8..e06982814 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "tron:package": "electron-forge package", "tron:make": "electron-forge make", "tron:publish": "electron-forge publish", - "tron:test": "NODE_ENV=development yarn playwright test --config=playwright.electron.config.ts --grep=@electron", + "tron:test": "NODE_ENV=development yarn playwright test --config=playwright.electron.config.ts --grep-invert='@snapshot'", "tronb:vite": "vite build -c vite.main.config.ts && vite build -c vite.preload.config.ts && vite build -c vite.renderer.config.ts", "tronb:package": "electron-builder --config electron-builder.yml", "test-setup": "yarn install && yarn build:wasm", diff --git a/src/lang/codeManager.ts b/src/lang/codeManager.ts index bb295bd24..623f6a30a 100644 --- a/src/lang/codeManager.ts +++ b/src/lang/codeManager.ts @@ -57,6 +57,10 @@ export default class CodeManager { return this._code } + localStoragePersistCode(): string { + return safeLSGetItem(PERSIST_CODE_KEY) + } + registerCallBacks({ setCode }: { setCode: (arg: string) => void }) { this.#updateState = setCode } diff --git a/src/lib/routeLoaders.ts b/src/lib/routeLoaders.ts index 8089d28f0..e3e211cbc 100644 --- a/src/lib/routeLoaders.ts +++ b/src/lib/routeLoaders.ts @@ -85,12 +85,13 @@ export const fileLoader: LoaderFunction = async ( ) const isBrowserProject = params.id === decodeURIComponent(BROWSER_PATH) + let code = '' + if (!isBrowserProject && projectPathData) { const { projectName, projectPath, currentFileName, currentFilePath } = projectPathData const urlObj = new URL(routerData.request.url) - let code = '' if (!urlObj.pathname.endsWith('/settings')) { const fallbackFile = isDesktop() @@ -120,6 +121,10 @@ export const fileLoader: LoaderFunction = async ( }) code = normalizeLineEndings(code) + // If persistCode in localStorage is present, it'll persist that code + // through *anything*. INTENDED FOR TESTS. + code = codeManager.localStoragePersistCode() || code + // Update both the state and the editor's code. // We explicitly do not write to the file here since we are loading from // the file system and not the editor. @@ -147,12 +152,6 @@ export const fileLoader: LoaderFunction = async ( ? await getProjectInfo(projectPath) : null - console.log('maybeProjectInfo', { - maybeProjectInfo, - defaultProjectData, - projectPathData, - }) - const projectData: IndexLoaderData = { code, project: maybeProjectInfo ?? defaultProjectData, @@ -169,7 +168,7 @@ export const fileLoader: LoaderFunction = async ( } return { - code: '', + code, project: { name: BROWSER_PROJECT_NAME, path: '/' + BROWSER_PROJECT_NAME,