diff --git a/.eslintrc.js b/.eslintrc.js index e623a6fb21..331543c931 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -204,6 +204,7 @@ const config = { 'scripts/**/*', '**/benchmark/**/*', '**/__debug__/**/*', + '**/e2e/**/*', ], rules: { '@typescript-eslint/no-non-null-assertion': 0, diff --git a/apps/electron/tests/basic.spec.ts b/apps/electron/e2e/basic.spec.ts similarity index 100% rename from apps/electron/tests/basic.spec.ts rename to apps/electron/e2e/basic.spec.ts diff --git a/apps/electron/tests/fixture.ts b/apps/electron/e2e/fixture.ts similarity index 100% rename from apps/electron/tests/fixture.ts rename to apps/electron/e2e/fixture.ts diff --git a/apps/electron/tests/setup.ts b/apps/electron/e2e/setup.ts similarity index 100% rename from apps/electron/tests/setup.ts rename to apps/electron/e2e/setup.ts diff --git a/apps/electron/tests/tsconfig.json b/apps/electron/e2e/tsconfig.json similarity index 100% rename from apps/electron/tests/tsconfig.json rename to apps/electron/e2e/tsconfig.json diff --git a/apps/electron/tests/workspace.spec.ts b/apps/electron/e2e/workspace.spec.ts similarity index 100% rename from apps/electron/tests/workspace.spec.ts rename to apps/electron/e2e/workspace.spec.ts diff --git a/apps/electron/playwright.config.ts b/apps/electron/playwright.config.ts index d3f67bbca7..94b4c898c2 100644 --- a/apps/electron/playwright.config.ts +++ b/apps/electron/playwright.config.ts @@ -11,7 +11,7 @@ import type { PlaywrightTestConfig } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ const config: PlaywrightTestConfig = { - testDir: './tests', + testDir: './e2e', testIgnore: '**/lib/**', fullyParallel: true, timeout: process.env.CI ? 50_000 : 30_000, diff --git a/apps/electron/src/helper/db/__tests__/ensure-db.spec.ts b/apps/electron/src/helper/db/__tests__/ensure-db.spec.ts index aa56434030..84a5935370 100644 --- a/apps/electron/src/helper/db/__tests__/ensure-db.spec.ts +++ b/apps/electron/src/helper/db/__tests__/ensure-db.spec.ts @@ -1,10 +1,11 @@ import path from 'node:path'; import { setTimeout } from 'node:timers/promises'; -import fs from 'fs-extra'; import { v4 } from 'uuid'; import { afterEach, beforeEach, expect, test, vi } from 'vitest'; +import { removeWithRetry } from '../../../../tests/utils'; + const tmpDir = path.join(__dirname, 'tmp'); const appDataPath = path.join(tmpDir, 'app-data'); @@ -44,11 +45,7 @@ beforeEach(() => { afterEach(async () => { existProcess(); - // wait for the db to be closed on Windows - if (process.platform === 'win32') { - await setTimeout(200); - } - await fs.remove(tmpDir); + await removeWithRetry(tmpDir); vi.useRealTimers(); }); diff --git a/apps/electron/src/helper/db/__tests__/workspace-db-adapter.spec.ts b/apps/electron/src/helper/db/__tests__/workspace-db-adapter.spec.ts index 329d509d09..f261446f61 100644 --- a/apps/electron/src/helper/db/__tests__/workspace-db-adapter.spec.ts +++ b/apps/electron/src/helper/db/__tests__/workspace-db-adapter.spec.ts @@ -5,6 +5,7 @@ import { v4 } from 'uuid'; import { afterEach, expect, test, vi } from 'vitest'; import * as Y from 'yjs'; +import { removeWithRetry } from '../../../../tests/utils'; import { dbSubjects } from '../subjects'; const tmpDir = path.join(__dirname, 'tmp'); @@ -17,7 +18,7 @@ vi.doMock('../../main-rpc', () => ({ })); afterEach(async () => { - await fs.remove(tmpDir); + await removeWithRetry(tmpDir); }); let testYDoc: Y.Doc; diff --git a/apps/electron/src/helper/workspace/__tests__/handlers.spec.ts b/apps/electron/src/helper/workspace/__tests__/handlers.spec.ts index 7faa160eb0..c1ad11525a 100644 --- a/apps/electron/src/helper/workspace/__tests__/handlers.spec.ts +++ b/apps/electron/src/helper/workspace/__tests__/handlers.spec.ts @@ -4,6 +4,8 @@ import fs from 'fs-extra'; import { v4 } from 'uuid'; import { afterEach, describe, expect, test, vi } from 'vitest'; +import { removeWithRetry } from '../../../../tests/utils'; + const tmpDir = path.join(__dirname, 'tmp'); const appDataPath = path.join(tmpDir, 'app-data'); @@ -20,7 +22,7 @@ vi.doMock('../../main-rpc', () => ({ })); afterEach(async () => { - await fs.remove(tmpDir); + await removeWithRetry(tmpDir); }); describe('list workspaces', () => { diff --git a/apps/electron/src/main/__tests__/integration.spec.ts b/apps/electron/src/main/__tests__/integration.spec.ts index 4559fb146f..04a138eacc 100644 --- a/apps/electron/src/main/__tests__/integration.spec.ts +++ b/apps/electron/src/main/__tests__/integration.spec.ts @@ -1,10 +1,10 @@ import assert from 'node:assert'; import path from 'node:path'; -import { setTimeout } from 'node:timers/promises'; import fs from 'fs-extra'; import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; +import { removeWithRetry } from '../../../tests/utils'; import type { MainIPCHandlerMap } from '../exposed'; const registeredHandlers = new Map< @@ -121,11 +121,7 @@ beforeEach(async () => { afterEach(async () => { // reset registered handlers registeredHandlers.get('before-quit')?.forEach(fn => fn()); - // wait for the db to be closed on Windows - if (process.platform === 'win32') { - await setTimeout(200); - } - await fs.remove(SESSION_DATA_PATH); + await removeWithRetry(SESSION_DATA_PATH); }); describe('UI handlers', () => { diff --git a/apps/electron/tests/utils.ts b/apps/electron/tests/utils.ts new file mode 100644 index 0000000000..e92a6c2f7e --- /dev/null +++ b/apps/electron/tests/utils.ts @@ -0,0 +1,26 @@ +import { setTimeout } from 'node:timers/promises'; + +import fs from 'fs-extra'; + +export async function removeWithRetry( + filePath: string, + maxRetries = 5, + delay = 500 +) { + for (let i = 0; i < maxRetries; i++) { + try { + await fs.remove(filePath); + console.log(`File ${filePath} successfully deleted.`); + return true; + } catch (err: any) { + if (err.code === 'EBUSY' || err.code === 'EPERM') { + console.log(`File ${filePath} is busy or locked, retrying...`); + await setTimeout(delay); + } else { + console.error(`Failed to delete file ${filePath}:`, err); + } + } + } + // Add a return statement here to ensure that a value is always returned + return false; +} diff --git a/apps/electron/tsconfig.json b/apps/electron/tsconfig.json index 139f7d3649..fe899d5c2a 100644 --- a/apps/electron/tsconfig.json +++ b/apps/electron/tsconfig.json @@ -14,7 +14,7 @@ "noImplicitOverride": true }, "include": ["./src"], - "exclude": ["node_modules", "out", "dist"], + "exclude": ["node_modules", "out", "dist", "**/__tests__/**/*"], "references": [ { "path": "../../packages/plugin-infra" @@ -31,7 +31,7 @@ "path": "./tsconfig.node.json" }, { - "path": "./tests/tsconfig.json" + "path": "./e2e/tsconfig.json" }, { "path": "../../tests/kit" } ], diff --git a/apps/electron/tsconfig.tests.json b/apps/electron/tsconfig.tests.json new file mode 100644 index 0000000000..4af2e315d8 --- /dev/null +++ b/apps/electron/tsconfig.tests.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true + }, + "include": ["**/__tests__/**/*", "./tests"], + "references": [ + { + "path": "./tsconfig.json" + } + ] +}