feat: create workspace from loading existing exported file (#2122)

Co-authored-by: Himself65 <himself65@outlook.com>
This commit is contained in:
Peng Xiao
2023-05-09 15:30:01 +08:00
committed by GitHub
parent 5432aae85c
commit 7c2574b1ca
93 changed files with 2999 additions and 1406 deletions

View File

@@ -1,48 +1,17 @@
import { resolve } from 'node:path';
import { test, testResultDir } from '@affine-test/kit/playwright';
import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';
import type { ElectronApplication } from 'playwright';
import { _electron as electron } from 'playwright';
let electronApp: ElectronApplication;
let page: Page;
import { test } from './fixture';
test.beforeEach(async () => {
electronApp = await electron.launch({
args: [resolve(__dirname, '..')],
executablePath: resolve(__dirname, '../node_modules/.bin/electron'),
colorScheme: 'light',
});
page = await electronApp.firstWindow();
await page.getByTestId('onboarding-modal-close-button').click({
delay: 100,
});
// cleanup page data
await page.evaluate(() => localStorage.clear());
});
test.afterEach(async () => {
// cleanup page data
await page.evaluate(() => localStorage.clear());
await page.close();
await electronApp.close();
});
test('new page', async () => {
test('new page', async ({ page, workspace }) => {
await page.getByTestId('new-page-button').click({
delay: 100,
});
await page.waitForSelector('v-line');
const flavour = await page.evaluate(
// @ts-expect-error
() => globalThis.currentWorkspace.flavour
);
const flavour = (await workspace.current()).flavour;
expect(flavour).toBe('local');
});
test('app theme', async () => {
test('app theme', async ({ page, electronApp }) => {
await page.waitForSelector('v-line');
const root = page.locator('html');
{
@@ -50,25 +19,35 @@ test('app theme', async () => {
element.getAttribute('data-theme')
);
expect(themeMode).toBe('light');
// check if electron theme source is set to light
const themeSource = await electronApp.evaluate(({ nativeTheme }) => {
return nativeTheme.themeSource;
});
expect(themeSource).toBe('light');
}
await page.screenshot({
path: resolve(testResultDir, 'affine-light-theme-electron.png'),
});
await page.getByTestId('editor-option-menu').click();
await page.getByTestId('change-theme-dark').click();
await page.waitForTimeout(50);
{
const themeMode = await root.evaluate(element =>
element.getAttribute('data-theme')
);
expect(themeMode).toBe('dark');
await page.getByTestId('editor-option-menu').click();
await page.getByTestId('change-theme-dark').click();
await page.waitForTimeout(50);
{
const themeMode = await root.evaluate(element =>
element.getAttribute('data-theme')
);
expect(themeMode).toBe('dark');
}
const themeSource = await electronApp.evaluate(({ nativeTheme }) => {
return nativeTheme.themeSource;
});
expect(themeSource).toBe('dark');
}
await page.screenshot({
path: resolve(testResultDir, 'affine-dark-theme-electron.png'),
});
});
test('affine cloud disabled', async () => {
test('affine cloud disabled', async ({ page }) => {
await page.getByTestId('new-page-button').click({
delay: 100,
});
@@ -79,7 +58,8 @@ test('affine cloud disabled', async () => {
state: 'visible',
});
});
test('affine onboarding button', async () => {
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]');

View File

@@ -0,0 +1,86 @@
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path="../layers/preload/preload.d.ts" />
/* eslint-disable no-empty-pattern */
import crypto from 'node:crypto';
import { resolve } from 'node:path';
import { test as base } from '@affine-test/kit/playwright';
import fs from 'fs-extra';
import type { ElectronApplication, Page } from 'playwright';
import { _electron as electron } from 'playwright';
function generateUUID() {
return crypto.randomUUID();
}
export const test = base.extend<{
page: Page;
electronApp: ElectronApplication;
appInfo: {
appPath: string;
appData: string;
sessionData: string;
};
workspace: {
// get current workspace
current: () => Promise<any>; // todo: type
};
}>({
page: async ({ electronApp }, use) => {
const page = await electronApp.firstWindow();
await page.getByTestId('onboarding-modal-close-button').click({
delay: 100,
});
if (!process.env.CI) {
await electronApp.evaluate(({ BrowserWindow }) => {
BrowserWindow.getAllWindows()[0].webContents.openDevTools({
mode: 'detach',
});
});
}
const logFilePath = await page.evaluate(async () => {
return window.apis?.debug.logFilePath();
});
await use(page);
await page.close();
if (logFilePath) {
const logs = await fs.readFile(logFilePath, 'utf-8');
console.log(logs);
}
},
electronApp: async ({}, use) => {
// a random id to avoid conflicts between tests
const id = generateUUID();
const electronApp = await electron.launch({
args: [resolve(__dirname, '..'), '--app-name', 'affine-test-' + id],
executablePath: resolve(__dirname, '../node_modules/.bin/electron'),
colorScheme: 'light',
});
const sessionDataPath = await electronApp.evaluate(async ({ app }) => {
return app.getPath('sessionData');
});
await use(electronApp);
await fs.rm(sessionDataPath, { recursive: true, force: true });
},
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);
},
workspace: async ({ page }, use) => {
await use({
current: async () => {
return await page.evaluate(async () => {
// @ts-expect-error
return globalThis.currentWorkspace;
});
},
});
},
});

View File

@@ -0,0 +1,7 @@
import { execSync } from 'node:child_process';
export default async function () {
execSync('yarn ts-node-esm scripts/', {
cwd: path.join(__dirname, '..'),
});
}

View File

@@ -0,0 +1,97 @@
import path from 'node:path';
import { expect } from '@playwright/test';
import fs from 'fs-extra';
import { test } from './fixture';
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('move workspace db file', async ({ page, appInfo, workspace }) => {
const w = await workspace.current();
const settingButton = page.getByTestId('slider-bar-workspace-setting-button');
// goto settings
await settingButton.click();
const tmpPath = path.join(appInfo.sessionData, w.id + '-tmp.db');
// 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);
});
test('export then add', async ({ page, appInfo, workspace }) => {
const w = await workspace.current();
const settingButton = page.getByTestId('slider-bar-workspace-setting-button');
// goto settings
await settingButton.click();
const originalId = w.id;
const newWorkspaceName = 'new-test-name';
// change workspace name
await page.getByTestId('workspace-name-input').fill(newWorkspaceName);
await page.getByTestId('save-workspace-name').click();
await page.waitForSelector('text="Update workspace name success"');
await page.click('[data-tab-key="export"]');
const tmpPath = path.join(appInfo.sessionData, w.id + '-tmp.db');
// move 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"');
expect(await fs.exists(tmpPath)).toBe(true);
// 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);
});