mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-18 10:36:22 +08:00
test(electron): add cloud test (#4184)
Co-authored-by: Peng Xiao <pengxiao@outlook.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import { test } from '@affine-test/kit/electron';
|
||||
import {
|
||||
createRandomUser,
|
||||
enableCloudWorkspace,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import { waitForEditorLoad } from '@affine-test/kit/utils/page-logic';
|
||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||
|
||||
let user: {
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
test.beforeEach(async () => {
|
||||
user = await createRandomUser();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await loginUser(page, user.email);
|
||||
});
|
||||
|
||||
test('new page', async ({ page }) => {
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
await createLocalWorkspace(
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
page
|
||||
);
|
||||
await enableCloudWorkspace(page);
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "@affine-test/affine-desktop-cloud",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"e2e": "DEBUG=pw:browser yarn playwright test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@affine-test/fixtures": "workspace:*",
|
||||
"@affine-test/kit": "workspace:*",
|
||||
"@playwright/test": "^1.37.1",
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"fs-extra": "^11.1.1"
|
||||
},
|
||||
"version": "0.9.0-canary.8"
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
||||
// import { devices } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
// require('dotenv').config();
|
||||
|
||||
/**
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: './e2e',
|
||||
fullyParallel: true,
|
||||
timeout: process.env.CI ? 50_000 : 30_000,
|
||||
use: {
|
||||
viewport: { width: 1440, height: 800 },
|
||||
},
|
||||
reporter: process.env.CI ? 'github' : 'list',
|
||||
webServer: [
|
||||
// Intentionally not building the web, reminds you to run it by yourself.
|
||||
{
|
||||
command: 'yarn -T run start:web-static',
|
||||
port: 8080,
|
||||
timeout: 120 * 1000,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
env: {
|
||||
COVERAGE: process.env.COVERAGE || 'false',
|
||||
},
|
||||
},
|
||||
{
|
||||
command: 'yarn workspace @affine/server start',
|
||||
port: 3010,
|
||||
timeout: 120 * 1000,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
env: {
|
||||
DATABASE_URL:
|
||||
process.env.DATABASE_URL ??
|
||||
'postgresql://affine:affine@localhost:5432/affine',
|
||||
NODE_ENV: 'development',
|
||||
AFFINE_ENV: process.env.AFFINE_ENV ?? 'dev',
|
||||
DEBUG: 'affine:*',
|
||||
FORCE_COLOR: 'true',
|
||||
DEBUG_COLORS: 'true',
|
||||
ENABLE_LOCAL_EMAIL: process.env.ENABLE_LOCAL_EMAIL ?? 'true',
|
||||
NEXTAUTH_URL: 'http://localhost:8080',
|
||||
OAUTH_EMAIL_SENDER: 'noreply@toeverything.info',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (process.env.CI) {
|
||||
config.retries = 3;
|
||||
config.workers = '50%';
|
||||
}
|
||||
|
||||
export default config;
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["e2e"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../kit"
|
||||
},
|
||||
{
|
||||
"path": "../fixtures"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
import { platform } from 'node:os';
|
||||
|
||||
import { test } from '@affine-test/kit/electron';
|
||||
import { clickSideBarSettingButton } from '@affine-test/kit/utils/sidebar';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
test('new page', async ({ page, workspace }) => {
|
||||
await page.getByTestId('new-page-button').click({
|
||||
delay: 100,
|
||||
});
|
||||
await page.waitForSelector('v-line');
|
||||
const flavour = (await workspace.current()).flavour;
|
||||
expect(flavour).toBe('local');
|
||||
});
|
||||
|
||||
// macOS only
|
||||
if (platform() === 'darwin') {
|
||||
test('app sidebar router forward/back', async ({ page }) => {
|
||||
await page.getByTestId('help-island').click();
|
||||
await page.getByTestId('easy-guide').click();
|
||||
await page.getByTestId('onboarding-modal-next-button').click();
|
||||
await page.getByTestId('onboarding-modal-close-button').click();
|
||||
{
|
||||
// create pages
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByTestId('new-page-button').click({
|
||||
delay: 100,
|
||||
});
|
||||
await page.waitForSelector('v-line');
|
||||
await page.focus('.affine-doc-page-block-title');
|
||||
await page.type('.affine-doc-page-block-title', 'test1', {
|
||||
delay: 100,
|
||||
});
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByTestId('new-page-button').click({
|
||||
delay: 100,
|
||||
});
|
||||
await page.waitForSelector('v-line');
|
||||
await page.focus('.affine-doc-page-block-title');
|
||||
await page.type('.affine-doc-page-block-title', 'test2', {
|
||||
delay: 100,
|
||||
});
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByTestId('new-page-button').click({
|
||||
delay: 100,
|
||||
});
|
||||
await page.waitForSelector('v-line');
|
||||
await page.focus('.affine-doc-page-block-title');
|
||||
await page.type('.affine-doc-page-block-title', 'test3', {
|
||||
delay: 100,
|
||||
});
|
||||
}
|
||||
{
|
||||
const title = (await page
|
||||
.locator('.affine-doc-page-block-title')
|
||||
.textContent()) as string;
|
||||
expect(title.trim()).toBe('test3');
|
||||
}
|
||||
|
||||
await page.click('[data-testid="app-sidebar-arrow-button-back"]');
|
||||
await page.waitForTimeout(1000);
|
||||
await page.click('[data-testid="app-sidebar-arrow-button-back"]');
|
||||
await page.waitForTimeout(1000);
|
||||
{
|
||||
const title = (await page
|
||||
.locator('.affine-doc-page-block-title')
|
||||
.textContent()) as string;
|
||||
expect(title.trim()).toBe('test1');
|
||||
}
|
||||
await page.click('[data-testid="app-sidebar-arrow-button-forward"]');
|
||||
await page.waitForTimeout(1000);
|
||||
await page.click('[data-testid="app-sidebar-arrow-button-forward"]');
|
||||
await page.waitForTimeout(1000);
|
||||
{
|
||||
const title = (await page
|
||||
.locator('.affine-doc-page-block-title')
|
||||
.textContent()) as string;
|
||||
expect(title.trim()).toBe('test3');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
test('clientBorder value should disable by default on window', async ({
|
||||
page,
|
||||
}) => {
|
||||
await clickSideBarSettingButton(page);
|
||||
await page.waitForTimeout(1000);
|
||||
const settingItem = page.locator(
|
||||
'[data-testid="client-border-style-trigger"]'
|
||||
);
|
||||
expect(await settingItem.locator('input').inputValue()).toEqual(
|
||||
process.platform === 'win32' ? 'off' : 'on'
|
||||
);
|
||||
});
|
||||
|
||||
test('app theme', async ({ page, electronApp }) => {
|
||||
const root = page.locator('html');
|
||||
{
|
||||
const themeMode = await root.evaluate(element =>
|
||||
element.getAttribute('data-theme')
|
||||
);
|
||||
expect(themeMode).toBe('light');
|
||||
|
||||
const theme = await electronApp.evaluate(({ nativeTheme }) => {
|
||||
return nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
|
||||
});
|
||||
|
||||
expect(theme).toBe('light');
|
||||
}
|
||||
|
||||
{
|
||||
await page.getByTestId('settings-modal-trigger').click();
|
||||
await page.getByTestId('appearance-panel-trigger').click();
|
||||
await page.waitForTimeout(50);
|
||||
await page.getByTestId('dark-theme-trigger').click();
|
||||
const themeMode = await root.evaluate(element =>
|
||||
element.getAttribute('data-theme')
|
||||
);
|
||||
expect(themeMode).toBe('dark');
|
||||
const theme = await electronApp.evaluate(({ nativeTheme }) => {
|
||||
return nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
|
||||
});
|
||||
expect(theme).toBe('dark');
|
||||
}
|
||||
});
|
||||
|
||||
test('affine onboarding button', async ({ page }) => {
|
||||
await page.getByTestId('help-island').click();
|
||||
await page.getByTestId('easy-guide').click();
|
||||
const onboardingModal = page.locator('[data-testid=onboarding-modal]');
|
||||
expect(await onboardingModal.isVisible()).toEqual(true);
|
||||
const switchVideo = page.locator(
|
||||
'[data-testid=onboarding-modal-switch-video]'
|
||||
);
|
||||
expect(await switchVideo.isVisible()).toEqual(true);
|
||||
await page.getByTestId('onboarding-modal-next-button').click();
|
||||
const editingVideo = page.locator(
|
||||
'[data-testid=onboarding-modal-editing-video]'
|
||||
);
|
||||
expect(await editingVideo.isVisible()).toEqual(true);
|
||||
await page.getByTestId('onboarding-modal-close-button').click();
|
||||
|
||||
expect(await onboardingModal.isVisible()).toEqual(false);
|
||||
});
|
||||
|
||||
test('windows only check', async ({ page }) => {
|
||||
const windowOnlyUI = page.locator('[data-platform-target=win32]');
|
||||
if (process.platform === 'win32') {
|
||||
await expect(windowOnlyUI).toBeVisible();
|
||||
} else {
|
||||
await expect(windowOnlyUI).not.toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
test('delete workspace', async ({ page }) => {
|
||||
await page.getByTestId('current-workspace').click();
|
||||
await page.getByTestId('new-workspace').click();
|
||||
await page.getByTestId('create-workspace-input').type('Delete Me', {
|
||||
delay: 100,
|
||||
});
|
||||
await page.getByTestId('create-workspace-create-button').click({
|
||||
delay: 100,
|
||||
});
|
||||
await page.getByTestId('create-workspace-continue-button').click({
|
||||
delay: 100,
|
||||
});
|
||||
await page.waitForTimeout(1000);
|
||||
await clickSideBarSettingButton(page);
|
||||
await page.getByTestId('current-workspace-label').click();
|
||||
expect(await page.getByTestId('workspace-name-input').inputValue()).toBe(
|
||||
'Delete Me'
|
||||
);
|
||||
const contentElement = await page.getByTestId('setting-modal-content');
|
||||
const boundingBox = await contentElement.boundingBox();
|
||||
if (!boundingBox) {
|
||||
throw new Error('boundingBox is null');
|
||||
}
|
||||
await page.mouse.move(
|
||||
boundingBox.x + boundingBox.width / 2,
|
||||
boundingBox.y + boundingBox.height / 2
|
||||
);
|
||||
await page.mouse.wheel(0, 500);
|
||||
await page.getByTestId('delete-workspace-button').click();
|
||||
await page.getByTestId('delete-workspace-input').type('Delete Me');
|
||||
await page.getByTestId('delete-workspace-confirm-button').click();
|
||||
await page.waitForTimeout(1000);
|
||||
expect(await page.getByTestId('workspace-name').textContent()).toBe(
|
||||
'Demo Workspace'
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,117 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import { test } from '@affine-test/kit/electron';
|
||||
import { expect } from '@playwright/test';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
test('check workspace has a DB file', async ({ appInfo, workspace }) => {
|
||||
const w = await workspace.current();
|
||||
const dbPath = path.join(
|
||||
appInfo.sessionData,
|
||||
'workspaces',
|
||||
w.id,
|
||||
'storage.db'
|
||||
);
|
||||
// check if db file exists
|
||||
expect(await fs.exists(dbPath)).toBe(true);
|
||||
});
|
||||
|
||||
test.skip('move workspace db file', async ({ page, appInfo, workspace }) => {
|
||||
const w = await workspace.current();
|
||||
await page.getByTestId('slider-bar-workspace-setting-button').click();
|
||||
await expect(page.getByTestId('setting-modal')).toBeVisible();
|
||||
|
||||
// goto workspace setting
|
||||
await page.getByTestId('workspace-list-item').click();
|
||||
|
||||
const tmpPath = path.join(appInfo.sessionData, w.id + '-tmp-dir');
|
||||
|
||||
// move db file to tmp folder
|
||||
await page.evaluate(tmpPath => {
|
||||
window.apis?.dialog.setFakeDialogResult({
|
||||
filePath: tmpPath,
|
||||
});
|
||||
}, tmpPath);
|
||||
|
||||
await page.getByTestId('move-folder').click();
|
||||
// check if db file exists
|
||||
await page.waitForSelector('text="Move folder success"');
|
||||
expect(await fs.exists(tmpPath)).toBe(true);
|
||||
// check if db file exists under tmpPath (a file ends with .affine)
|
||||
const files = await fs.readdir(tmpPath);
|
||||
expect(files.some(f => f.endsWith('.affine'))).toBe(true);
|
||||
});
|
||||
|
||||
//TODO:fix test
|
||||
test.fixme('export then add', async ({ page, appInfo, workspace }) => {
|
||||
const w = await workspace.current();
|
||||
|
||||
await page.focus('.affine-doc-page-block-title');
|
||||
await page.fill('.affine-doc-page-block-title', 'test1');
|
||||
|
||||
await page.getByTestId('slider-bar-workspace-setting-button').click();
|
||||
await expect(page.getByTestId('setting-modal')).toBeVisible();
|
||||
|
||||
const originalId = w.id;
|
||||
|
||||
const newWorkspaceName = 'new-test-name';
|
||||
|
||||
// goto workspace setting
|
||||
await page.getByTestId('workspace-list-item').click();
|
||||
const input = page.getByTestId('workspace-name-input');
|
||||
await expect(input).toBeVisible();
|
||||
|
||||
// change workspace name
|
||||
await input.fill(newWorkspaceName);
|
||||
await page.getByTestId('save-workspace-name').click();
|
||||
await page.waitForSelector('text="Update workspace name success"');
|
||||
|
||||
const tmpPath = path.join(appInfo.sessionData, w.id + '-tmp.db');
|
||||
|
||||
// export db file to tmp folder
|
||||
await page.evaluate(tmpPath => {
|
||||
window.apis?.dialog.setFakeDialogResult({
|
||||
filePath: tmpPath,
|
||||
});
|
||||
}, tmpPath);
|
||||
|
||||
await page.getByTestId('export-affine-backup').click();
|
||||
await page.waitForSelector('text="Export success"');
|
||||
await page.waitForTimeout(1000);
|
||||
expect(await fs.exists(tmpPath)).toBe(true);
|
||||
|
||||
await page.getByTestId('modal-close-button').click();
|
||||
|
||||
// add workspace
|
||||
// we are reusing the same db file so that we don't need to maintain one
|
||||
// in the codebase
|
||||
await page.getByTestId('current-workspace').click();
|
||||
await page.getByTestId('add-or-new-workspace').click();
|
||||
|
||||
await page.evaluate(tmpPath => {
|
||||
window.apis?.dialog.setFakeDialogResult({
|
||||
filePath: tmpPath,
|
||||
});
|
||||
}, tmpPath);
|
||||
|
||||
// load the db file
|
||||
await page.getByTestId('add-workspace').click();
|
||||
|
||||
// should show "Added Successfully" dialog
|
||||
await page.waitForSelector('text="Added Successfully"');
|
||||
await page.getByTestId('create-workspace-continue-button').click();
|
||||
|
||||
// sleep for a while to wait for the workspace to be added :D
|
||||
await page.waitForTimeout(2000);
|
||||
const newWorkspace = await workspace.current();
|
||||
expect(newWorkspace.id).not.toBe(originalId);
|
||||
// check its name is correct
|
||||
await expect(page.getByTestId('workspace-name')).toHaveText(newWorkspaceName);
|
||||
|
||||
// find button which has the title "test1"
|
||||
const test1PageButton = await page.waitForSelector(`text="test1"`);
|
||||
await test1PageButton.click();
|
||||
|
||||
const title = page.locator('[data-block-is-title] >> text="test1"');
|
||||
await expect(title).toBeVisible();
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "@affine-test/affine-desktop",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"e2e": "DEBUG=pw:browser yarn playwright test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@affine-test/fixtures": "workspace:*",
|
||||
"@affine-test/kit": "workspace:*",
|
||||
"@playwright/test": "^1.37.1",
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"fs-extra": "^11.1.1"
|
||||
},
|
||||
"version": "0.9.0-canary.8"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
||||
// import { devices } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
// require('dotenv').config();
|
||||
|
||||
/**
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: './e2e',
|
||||
fullyParallel: true,
|
||||
timeout: process.env.CI ? 50_000 : 30_000,
|
||||
use: {
|
||||
viewport: { width: 1440, height: 800 },
|
||||
},
|
||||
};
|
||||
|
||||
if (process.env.CI) {
|
||||
config.retries = 3;
|
||||
config.workers = '50%';
|
||||
}
|
||||
|
||||
export default config;
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["e2e"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../kit"
|
||||
},
|
||||
{
|
||||
"path": "../fixtures"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
import crypto from 'node:crypto';
|
||||
import { join, resolve } from 'node:path';
|
||||
|
||||
import type { Page } from '@playwright/test';
|
||||
import fs from 'fs-extra';
|
||||
import type { ElectronApplication } from 'playwright';
|
||||
import { _electron as electron } from 'playwright';
|
||||
|
||||
import {
|
||||
enableCoverage,
|
||||
istanbulTempDir,
|
||||
test as base,
|
||||
testResultDir,
|
||||
} from './playwright';
|
||||
import { removeWithRetry } from './utils/utils';
|
||||
|
||||
const projectRoot = resolve(__dirname, '..', '..');
|
||||
const electronRoot = resolve(projectRoot, 'apps', 'electron');
|
||||
|
||||
function generateUUID() {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
|
||||
type RoutePath = 'setting';
|
||||
|
||||
export const test = base.extend<{
|
||||
electronApp: ElectronApplication;
|
||||
appInfo: {
|
||||
appPath: string;
|
||||
appData: string;
|
||||
sessionData: string;
|
||||
};
|
||||
router: {
|
||||
goto: (path: RoutePath) => Promise<void>;
|
||||
};
|
||||
}>({
|
||||
page: async ({ electronApp }, use) => {
|
||||
const page = await electronApp.firstWindow();
|
||||
await page.getByTestId('onboarding-modal-close-button').click({
|
||||
delay: 100,
|
||||
});
|
||||
// wait for blocksuite to be loaded
|
||||
await page.waitForSelector('v-line');
|
||||
if (enableCoverage) {
|
||||
await fs.promises.mkdir(istanbulTempDir, { recursive: true });
|
||||
await page.exposeFunction(
|
||||
'collectIstanbulCoverage',
|
||||
(coverageJSON?: string) => {
|
||||
if (coverageJSON)
|
||||
fs.writeFileSync(
|
||||
join(
|
||||
istanbulTempDir,
|
||||
`playwright_coverage_${generateUUID()}.json`
|
||||
),
|
||||
coverageJSON
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
await use(page as Page);
|
||||
if (enableCoverage) {
|
||||
await page.evaluate(() =>
|
||||
// @ts-expect-error
|
||||
window.collectIstanbulCoverage(JSON.stringify(window.__coverage__))
|
||||
);
|
||||
}
|
||||
await page.close();
|
||||
},
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
electronApp: async ({}, use) => {
|
||||
// a random id to avoid conflicts between tests
|
||||
const id = generateUUID();
|
||||
const ext = process.platform === 'win32' ? '.cmd' : '';
|
||||
const dist = resolve(electronRoot, 'dist');
|
||||
const clonedDist = resolve(electronRoot, 'e2e-dist-' + id);
|
||||
await fs.copy(dist, clonedDist);
|
||||
const packageJson = await fs.readJSON(
|
||||
resolve(electronRoot, 'package.json')
|
||||
);
|
||||
// overwrite the app name
|
||||
packageJson.name = 'affine-test-' + id;
|
||||
// overwrite the path to the main script
|
||||
packageJson.main = './main.js';
|
||||
// write to the cloned dist
|
||||
await fs.writeJSON(resolve(clonedDist, 'package.json'), packageJson);
|
||||
|
||||
const env: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(process.env)) {
|
||||
if (value) {
|
||||
env[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.DEV_SERVER_URL) {
|
||||
env.DEV_SERVER_URL = process.env.DEV_SERVER_URL;
|
||||
}
|
||||
|
||||
const electronApp = await electron.launch({
|
||||
args: [clonedDist],
|
||||
env,
|
||||
executablePath: resolve(
|
||||
electronRoot,
|
||||
'node_modules',
|
||||
'.bin',
|
||||
`electron${ext}`
|
||||
),
|
||||
cwd: clonedDist,
|
||||
recordVideo: {
|
||||
dir: testResultDir,
|
||||
},
|
||||
colorScheme: 'light',
|
||||
});
|
||||
await use(electronApp);
|
||||
try {
|
||||
await removeWithRetry(clonedDist);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
appInfo: async ({ electronApp }, use) => {
|
||||
const appInfo = await electronApp.evaluate(async ({ app }) => {
|
||||
return {
|
||||
appPath: app.getAppPath(),
|
||||
appData: app.getPath('appData'),
|
||||
sessionData: app.getPath('sessionData'),
|
||||
};
|
||||
});
|
||||
await use(appInfo);
|
||||
},
|
||||
});
|
||||
@@ -4,6 +4,7 @@
|
||||
"type": "module",
|
||||
"version": "0.9.0-canary.12",
|
||||
"exports": {
|
||||
"./electron": "./electron.ts",
|
||||
"./playwright": "./playwright.ts",
|
||||
"./utils/*": "./utils/*.ts"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
|
||||
import type { Page } from '@playwright/test';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
export async function waitForLogMessage(
|
||||
page: Page,
|
||||
@@ -12,3 +15,26 @@ export async function waitForLogMessage(
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,12 +19,20 @@ export async function createLocalWorkspace(
|
||||
// open create workspace modal
|
||||
await page.getByTestId('new-workspace').click();
|
||||
|
||||
const isDesktop: boolean = await page.evaluate(() => {
|
||||
return !!window.appInfo?.electron;
|
||||
}, []);
|
||||
|
||||
// input workspace name
|
||||
await page.getByPlaceholder('Set a Workspace name').click();
|
||||
await page.getByPlaceholder('Set a Workspace name').fill(params.name);
|
||||
|
||||
// click create button
|
||||
return page.getByRole('button', { name: 'Create' }).click({
|
||||
await page.getByRole('button', { name: 'Create' }).click({
|
||||
delay: 500,
|
||||
});
|
||||
|
||||
if (isDesktop) {
|
||||
await page.getByTestId('create-workspace-continue-button').click();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user