mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-18 23:07:02 +08:00
chore: remove createEmptyEditor legacy test misc (#10291)
This commit is contained in:
@@ -2,32 +2,20 @@ import '../../style.css';
|
|||||||
|
|
||||||
import * as blockStd from '@blocksuite/block-std';
|
import * as blockStd from '@blocksuite/block-std';
|
||||||
import * as blocks from '@blocksuite/blocks';
|
import * as blocks from '@blocksuite/blocks';
|
||||||
import {
|
|
||||||
CommunityCanvasTextFonts,
|
|
||||||
DocModeProvider,
|
|
||||||
FontConfigExtension,
|
|
||||||
ParseDocUrlProvider,
|
|
||||||
QuickSearchProvider,
|
|
||||||
RefNodeSlotsProvider,
|
|
||||||
} from '@blocksuite/blocks';
|
|
||||||
import { effects as blocksEffects } from '@blocksuite/blocks/effects';
|
import { effects as blocksEffects } from '@blocksuite/blocks/effects';
|
||||||
import * as globalUtils from '@blocksuite/global/utils';
|
import * as globalUtils from '@blocksuite/global/utils';
|
||||||
import * as editor from '@blocksuite/presets';
|
import * as editor from '@blocksuite/presets';
|
||||||
import { effects as presetsEffects } from '@blocksuite/presets/effects';
|
import { effects as presetsEffects } from '@blocksuite/presets/effects';
|
||||||
import type { ExtensionType } from '@blocksuite/store';
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
import * as store from '@blocksuite/store';
|
import * as store from '@blocksuite/store';
|
||||||
|
|
||||||
import {
|
|
||||||
mockDocModeService,
|
|
||||||
mockEditorSetting,
|
|
||||||
} from '../_common/mock-services.js';
|
|
||||||
import { setupEdgelessTemplate } from '../_common/setup.js';
|
import { setupEdgelessTemplate } from '../_common/setup.js';
|
||||||
import {
|
import {
|
||||||
createStarterDocCollection,
|
createStarterDocCollection,
|
||||||
initStarterDocCollection,
|
initStarterDocCollection,
|
||||||
} from './utils/collection.js';
|
} from './utils/collection.js';
|
||||||
import { mountDefaultDocEditor } from './utils/editor.js';
|
import { mountDefaultDocEditor } from './utils/editor.js';
|
||||||
|
import { prepareTestApp } from './utils/test';
|
||||||
|
|
||||||
blocksEffects();
|
blocksEffects();
|
||||||
presetsEffects();
|
presetsEffects();
|
||||||
@@ -50,24 +38,9 @@ async function main() {
|
|||||||
global: { utils: globalUtils },
|
global: { utils: globalUtils },
|
||||||
editor,
|
editor,
|
||||||
blockStd: blockStd,
|
blockStd: blockStd,
|
||||||
identifiers: {
|
|
||||||
QuickSearchProvider,
|
|
||||||
DocModeProvider,
|
|
||||||
RefNodeSlotsProvider,
|
|
||||||
ParseDocUrlService: ParseDocUrlProvider,
|
|
||||||
},
|
|
||||||
defaultExtensions: (): ExtensionType[] => [
|
|
||||||
FontConfigExtension(CommunityCanvasTextFonts),
|
|
||||||
blocks.EditorSettingExtension(mockEditorSetting()),
|
|
||||||
],
|
|
||||||
extensions: {
|
|
||||||
FontConfigExtension: FontConfigExtension(CommunityCanvasTextFonts),
|
|
||||||
},
|
|
||||||
mockServices: {
|
|
||||||
mockDocModeService,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
await prepareTestApp(collection);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
176
blocksuite/playground/apps/starter/utils/test.ts
Normal file
176
blocksuite/playground/apps/starter/utils/test.ts
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
import {
|
||||||
|
type BlockSuiteFlags,
|
||||||
|
CommunityCanvasTextFonts,
|
||||||
|
DocModeProvider,
|
||||||
|
EditorSettingExtension,
|
||||||
|
FeatureFlagService,
|
||||||
|
FontConfigExtension,
|
||||||
|
ParseDocUrlProvider,
|
||||||
|
RefNodeSlotsProvider,
|
||||||
|
} from '@blocksuite/blocks';
|
||||||
|
import type { Container } from '@blocksuite/global/di';
|
||||||
|
import type { ExtensionType, Store, Workspace } from '@blocksuite/store';
|
||||||
|
|
||||||
|
import {
|
||||||
|
mockDocModeService,
|
||||||
|
mockEditorSetting,
|
||||||
|
} from '../../_common/mock-services';
|
||||||
|
|
||||||
|
export async function prepareTestApp(collection: Workspace) {
|
||||||
|
const params = new URLSearchParams(location.search);
|
||||||
|
const allFlags = params.getAll('flag');
|
||||||
|
const flags = allFlags.reduce(
|
||||||
|
(acc, flag) => {
|
||||||
|
acc[flag] = true;
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{} as Record<string, boolean>
|
||||||
|
);
|
||||||
|
const noInit = params.get('noInit') === 'true';
|
||||||
|
const store = await getStore(collection, noInit);
|
||||||
|
await createTestApp(store, collection, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getStore(
|
||||||
|
collection: Workspace,
|
||||||
|
noInit: boolean
|
||||||
|
): Promise<Store> {
|
||||||
|
if (!noInit) {
|
||||||
|
collection.meta.initialize();
|
||||||
|
const doc = collection.createDoc({ id: 'doc:home' });
|
||||||
|
window.doc = doc;
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const doc = collection.docs.values().next().value;
|
||||||
|
const firstDoc = doc?.getStore();
|
||||||
|
if (firstDoc) {
|
||||||
|
window.doc = firstDoc;
|
||||||
|
return firstDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { resolve, reject, promise } = Promise.withResolvers<Store>();
|
||||||
|
collection.slots.docListUpdated.on(() => {
|
||||||
|
const doc = collection.docs.values().next().value;
|
||||||
|
const firstDoc = doc?.getStore();
|
||||||
|
if (!firstDoc) {
|
||||||
|
reject(new Error(`Failed to get doc`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.doc = firstDoc;
|
||||||
|
resolve(firstDoc);
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createTestApp(
|
||||||
|
doc: Store,
|
||||||
|
collection: Workspace,
|
||||||
|
flags: Partial<BlockSuiteFlags> = {}
|
||||||
|
) {
|
||||||
|
doc.load();
|
||||||
|
|
||||||
|
if (!doc.root) {
|
||||||
|
await new Promise(resolve => doc.slots.rootAdded.once(resolve));
|
||||||
|
}
|
||||||
|
|
||||||
|
// add app root from https://github.com/toeverything/blocksuite/commit/947201981daa64c5ceeca5fd549460c34e2dabfa
|
||||||
|
const appRoot = document.querySelector('#app');
|
||||||
|
if (!appRoot) {
|
||||||
|
throw new Error('Cannot find app root element(#app).');
|
||||||
|
}
|
||||||
|
|
||||||
|
const editor = createEditor(doc, collection, appRoot, flags);
|
||||||
|
await editor.updateComplete;
|
||||||
|
|
||||||
|
const debugMenu = document.createElement('starter-debug-menu');
|
||||||
|
const docsPanel = document.createElement('docs-panel');
|
||||||
|
const framePanel = document.createElement('custom-frame-panel');
|
||||||
|
const outlinePanel = document.createElement('custom-outline-panel');
|
||||||
|
const outlineViewer = document.createElement('custom-outline-viewer');
|
||||||
|
const leftSidePanel = document.createElement('left-side-panel');
|
||||||
|
docsPanel.editor = editor;
|
||||||
|
framePanel.editor = editor;
|
||||||
|
outlinePanel.editor = editor;
|
||||||
|
outlineViewer.editor = editor;
|
||||||
|
debugMenu.collection = collection;
|
||||||
|
debugMenu.editor = editor;
|
||||||
|
debugMenu.docsPanel = docsPanel;
|
||||||
|
debugMenu.framePanel = framePanel;
|
||||||
|
debugMenu.outlineViewer = outlineViewer;
|
||||||
|
debugMenu.outlinePanel = outlinePanel;
|
||||||
|
debugMenu.leftSidePanel = leftSidePanel;
|
||||||
|
document.body.append(debugMenu);
|
||||||
|
document.body.append(leftSidePanel);
|
||||||
|
document.body.append(framePanel);
|
||||||
|
document.body.append(outlinePanel);
|
||||||
|
document.body.append(outlineViewer);
|
||||||
|
|
||||||
|
window.editor = editor;
|
||||||
|
window.doc = doc;
|
||||||
|
Object.defineProperty(globalThis, 'host', {
|
||||||
|
get() {
|
||||||
|
return document.querySelector('editor-host');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Object.defineProperty(globalThis, 'std', {
|
||||||
|
get() {
|
||||||
|
return document.querySelector('editor-host')?.std;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEditor(
|
||||||
|
doc: Store,
|
||||||
|
collection: Workspace,
|
||||||
|
appRoot: Element,
|
||||||
|
flags: Partial<BlockSuiteFlags> = {}
|
||||||
|
) {
|
||||||
|
const editor = document.createElement('affine-editor-container');
|
||||||
|
for (const [key, value] of Object.entries(flags)) {
|
||||||
|
doc.get(FeatureFlagService).setFlag(key as keyof BlockSuiteFlags, value);
|
||||||
|
}
|
||||||
|
doc.get(FeatureFlagService).setFlag('enable_advanced_block_visibility', true);
|
||||||
|
|
||||||
|
editor.doc = doc;
|
||||||
|
editor.autofocus = true;
|
||||||
|
const defaultExtensions: ExtensionType[] = [
|
||||||
|
FontConfigExtension(CommunityCanvasTextFonts),
|
||||||
|
EditorSettingExtension(mockEditorSetting()),
|
||||||
|
{
|
||||||
|
setup: (di: Container) => {
|
||||||
|
di.addImpl(ParseDocUrlProvider, {
|
||||||
|
parseDocUrl() {
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
setup: (di: Container) => {
|
||||||
|
di.override(
|
||||||
|
DocModeProvider,
|
||||||
|
mockDocModeService(
|
||||||
|
() => editor.mode,
|
||||||
|
(mode: 'page' | 'edgeless') => editor.switchEditor(mode)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
editor.pageSpecs = [...editor.pageSpecs, ...defaultExtensions];
|
||||||
|
editor.edgelessSpecs = [...editor.edgelessSpecs, ...defaultExtensions];
|
||||||
|
|
||||||
|
editor.std
|
||||||
|
.get(RefNodeSlotsProvider)
|
||||||
|
.docLinkClicked.on(({ pageId: docId }) => {
|
||||||
|
const newDoc = collection.getDoc(docId);
|
||||||
|
if (!newDoc) {
|
||||||
|
throw new Error(`Failed to jump to page ${docId}`);
|
||||||
|
}
|
||||||
|
editor.doc = newDoc;
|
||||||
|
});
|
||||||
|
appRoot.append(editor);
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
@@ -99,7 +99,6 @@ test(scoped`basic multi user state`, async ({ context, page: pageA }) => {
|
|||||||
|
|
||||||
const pageB = await context.newPage();
|
const pageB = await context.newPage();
|
||||||
await enterPlaygroundRoom(pageB, {
|
await enterPlaygroundRoom(pageB, {
|
||||||
flags: {},
|
|
||||||
room,
|
room,
|
||||||
noInit: true,
|
noInit: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,23 +1,21 @@
|
|||||||
import '../declare-test-window.js';
|
import '../declare-test-window.js';
|
||||||
|
|
||||||
import type { EditorHost } from '@blocksuite/block-std';
|
|
||||||
import type {
|
import type {
|
||||||
BlockSuiteFlags,
|
BlockSuiteFlags,
|
||||||
DatabaseBlockModel,
|
DatabaseBlockModel,
|
||||||
ListType,
|
ListType,
|
||||||
RichText,
|
RichText,
|
||||||
} from '@blocksuite/blocks';
|
} from '@blocksuite/blocks';
|
||||||
import type { Container } from '@blocksuite/global/di';
|
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import type { InlineRange, InlineRootElement } from '@blocksuite/inline';
|
import type { InlineRange, InlineRootElement } from '@blocksuite/inline';
|
||||||
import type { AffineEditorContainer } from '@blocksuite/presets';
|
import type { AffineEditorContainer } from '@blocksuite/presets';
|
||||||
import type { BlockModel, ExtensionType } from '@blocksuite/store';
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
import { uuidv4 } from '@blocksuite/store';
|
import { uuidv4 } from '@blocksuite/store';
|
||||||
import type { ConsoleMessage, Locator, Page } from '@playwright/test';
|
import type { ConsoleMessage, Locator, Page } from '@playwright/test';
|
||||||
import { expect } from '@playwright/test';
|
import { expect } from '@playwright/test';
|
||||||
import lz from 'lz-string';
|
import lz from 'lz-string';
|
||||||
|
|
||||||
import { currentEditorIndex, multiEditor } from '../multiple-editor.js';
|
import { currentEditorIndex } from '../multiple-editor.js';
|
||||||
import {
|
import {
|
||||||
pressArrowRight,
|
pressArrowRight,
|
||||||
pressEnter,
|
pressEnter,
|
||||||
@@ -29,12 +27,6 @@ import {
|
|||||||
type,
|
type,
|
||||||
} from './keyboard.js';
|
} from './keyboard.js';
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface WindowEventMap {
|
|
||||||
'blocksuite:doc-ready': CustomEvent<string>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const defaultPlaygroundURL = new URL(
|
export const defaultPlaygroundURL = new URL(
|
||||||
`http://localhost:${process.env.CI ? 4173 : 5173}/`
|
`http://localhost:${process.env.CI ? 4173 : 5173}/`
|
||||||
);
|
);
|
||||||
@@ -55,186 +47,6 @@ export const getSelectionRect = async (page: Page): Promise<DOMRect> => {
|
|||||||
return rect;
|
return rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @example
|
|
||||||
* ```ts
|
|
||||||
* await initEmptyEditor(page, { enable_some_flag: true });
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
async function initEmptyEditor({
|
|
||||||
page,
|
|
||||||
flags = {},
|
|
||||||
noInit = false,
|
|
||||||
multiEditor = false,
|
|
||||||
}: {
|
|
||||||
page: Page;
|
|
||||||
flags?: Partial<BlockSuiteFlags>;
|
|
||||||
noInit?: boolean;
|
|
||||||
multiEditor?: boolean;
|
|
||||||
}) {
|
|
||||||
await page.evaluate(
|
|
||||||
([flags, noInit, multiEditor]) => {
|
|
||||||
const { collection } = window;
|
|
||||||
|
|
||||||
async function waitForMountPageEditor(
|
|
||||||
doc: ReturnType<typeof collection.createDoc>
|
|
||||||
) {
|
|
||||||
doc.load();
|
|
||||||
|
|
||||||
if (!doc.root) {
|
|
||||||
await new Promise(resolve => doc.slots.rootAdded.once(resolve));
|
|
||||||
}
|
|
||||||
|
|
||||||
// add app root from https://github.com/toeverything/blocksuite/commit/947201981daa64c5ceeca5fd549460c34e2dabfa
|
|
||||||
const appRoot = document.querySelector('#app');
|
|
||||||
if (!appRoot) {
|
|
||||||
throw new Error('Cannot find app root element(#app).');
|
|
||||||
}
|
|
||||||
const createEditor = () => {
|
|
||||||
const editor = document.createElement('affine-editor-container');
|
|
||||||
for (const [key, value] of Object.entries(flags)) {
|
|
||||||
doc
|
|
||||||
.get(window.$blocksuite.blocks.FeatureFlagService)
|
|
||||||
.setFlag(key as keyof BlockSuiteFlags, value);
|
|
||||||
}
|
|
||||||
doc
|
|
||||||
.get(window.$blocksuite.blocks.FeatureFlagService)
|
|
||||||
.setFlag('enable_advanced_block_visibility', true);
|
|
||||||
editor.doc = doc;
|
|
||||||
editor.autofocus = true;
|
|
||||||
const defaultExtensions: ExtensionType[] = [
|
|
||||||
...window.$blocksuite.defaultExtensions(),
|
|
||||||
{
|
|
||||||
setup: (di: Container) => {
|
|
||||||
di.addImpl(window.$blocksuite.identifiers.ParseDocUrlService, {
|
|
||||||
parseDocUrl() {
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
setup: (di: Container) => {
|
|
||||||
di.override(
|
|
||||||
window.$blocksuite.identifiers.DocModeProvider,
|
|
||||||
// @ts-expect-error set mock service
|
|
||||||
window.$blocksuite.mockServices.mockDocModeService(
|
|
||||||
() => editor.mode,
|
|
||||||
(mode: 'page' | 'edgeless') => editor.switchEditor(mode)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
editor.pageSpecs = [...editor.pageSpecs, ...defaultExtensions];
|
|
||||||
editor.edgelessSpecs = [
|
|
||||||
...editor.edgelessSpecs,
|
|
||||||
...defaultExtensions,
|
|
||||||
];
|
|
||||||
|
|
||||||
editor.std
|
|
||||||
.get(window.$blocksuite.identifiers.RefNodeSlotsProvider)
|
|
||||||
.docLinkClicked.on(({ pageId: docId }) => {
|
|
||||||
const newDoc = collection.getDoc(docId);
|
|
||||||
if (!newDoc) {
|
|
||||||
throw new Error(`Failed to jump to page ${docId}`);
|
|
||||||
}
|
|
||||||
editor.doc = newDoc;
|
|
||||||
});
|
|
||||||
appRoot.append(editor);
|
|
||||||
return editor;
|
|
||||||
};
|
|
||||||
|
|
||||||
const editor = createEditor();
|
|
||||||
if (multiEditor) createEditor();
|
|
||||||
|
|
||||||
editor.updateComplete
|
|
||||||
.then(() => {
|
|
||||||
const debugMenu = document.createElement('starter-debug-menu');
|
|
||||||
const docsPanel = document.createElement('docs-panel');
|
|
||||||
const framePanel = document.createElement('custom-frame-panel');
|
|
||||||
const outlinePanel = document.createElement('custom-outline-panel');
|
|
||||||
const outlineViewer = document.createElement(
|
|
||||||
'custom-outline-viewer'
|
|
||||||
);
|
|
||||||
const leftSidePanel = document.createElement('left-side-panel');
|
|
||||||
// @ts-expect-error set test editor
|
|
||||||
docsPanel.editor = editor;
|
|
||||||
// @ts-expect-error set test editor
|
|
||||||
framePanel.editor = editor;
|
|
||||||
// @ts-expect-error set test editor
|
|
||||||
outlinePanel.editor = editor;
|
|
||||||
// @ts-expect-error set test editor
|
|
||||||
outlineViewer.editor = editor;
|
|
||||||
// @ts-expect-error set test collection
|
|
||||||
debugMenu.collection = collection;
|
|
||||||
// @ts-expect-error set test editor
|
|
||||||
debugMenu.editor = editor;
|
|
||||||
// @ts-expect-error set test docsPanel
|
|
||||||
debugMenu.docsPanel = docsPanel;
|
|
||||||
// @ts-expect-error set test framePanel
|
|
||||||
debugMenu.framePanel = framePanel;
|
|
||||||
// @ts-expect-error set test outlineViewer
|
|
||||||
debugMenu.outlineViewer = outlineViewer;
|
|
||||||
// @ts-expect-error set test outlinePanel
|
|
||||||
debugMenu.outlinePanel = outlinePanel;
|
|
||||||
// @ts-expect-error set test leftSidePanel
|
|
||||||
debugMenu.leftSidePanel = leftSidePanel;
|
|
||||||
document.body.append(debugMenu);
|
|
||||||
document.body.append(leftSidePanel);
|
|
||||||
document.body.append(framePanel);
|
|
||||||
document.body.append(outlinePanel);
|
|
||||||
document.body.append(outlineViewer);
|
|
||||||
|
|
||||||
window.debugMenu = debugMenu;
|
|
||||||
window.editor = editor;
|
|
||||||
window.doc = doc;
|
|
||||||
Object.defineProperty(globalThis, 'host', {
|
|
||||||
get() {
|
|
||||||
return document.querySelector<EditorHost>('editor-host');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Object.defineProperty(globalThis, 'std', {
|
|
||||||
get() {
|
|
||||||
return document.querySelector<EditorHost>('editor-host')?.std;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
window.dispatchEvent(
|
|
||||||
new CustomEvent('blocksuite:doc-ready', { detail: doc.id })
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noInit) {
|
|
||||||
const firstDoc = collection.docs.values().next().value?.getStore() as
|
|
||||||
| ReturnType<typeof collection.createDoc>
|
|
||||||
| undefined;
|
|
||||||
if (firstDoc) {
|
|
||||||
window.doc = firstDoc;
|
|
||||||
waitForMountPageEditor(firstDoc).catch;
|
|
||||||
} else {
|
|
||||||
collection.slots.docCreated.on(docId => {
|
|
||||||
const doc = collection.getDoc(docId);
|
|
||||||
if (!doc) {
|
|
||||||
throw new Error(`Failed to get doc ${docId}`);
|
|
||||||
}
|
|
||||||
window.doc = doc;
|
|
||||||
waitForMountPageEditor(doc).catch(console.error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
collection.meta.initialize();
|
|
||||||
const doc = collection.createDoc({ id: 'doc:home' });
|
|
||||||
window.doc = doc;
|
|
||||||
waitForMountPageEditor(doc).catch(console.error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[flags, noInit, multiEditor] as const
|
|
||||||
);
|
|
||||||
await waitNextFrame(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getEditorLocator = (page: Page) => {
|
export const getEditorLocator = (page: Page) => {
|
||||||
return page.locator('affine-editor-container').nth(currentEditorIndex);
|
return page.locator('affine-editor-container').nth(currentEditorIndex);
|
||||||
};
|
};
|
||||||
@@ -316,6 +128,14 @@ export async function enterPlaygroundRoom(
|
|||||||
}
|
}
|
||||||
url.searchParams.set('room', room);
|
url.searchParams.set('room', room);
|
||||||
url.searchParams.set('blobSource', blobSource?.join(',') || 'idb');
|
url.searchParams.set('blobSource', blobSource?.join(',') || 'idb');
|
||||||
|
for (const [key, value] of Object.entries(ops?.flags || {})) {
|
||||||
|
if (value) {
|
||||||
|
url.searchParams.append('flag', key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ops?.noInit) {
|
||||||
|
url.searchParams.set('noInit', 'true');
|
||||||
|
}
|
||||||
await page.goto(url.toString());
|
await page.goto(url.toString());
|
||||||
|
|
||||||
// See https://github.com/microsoft/playwright/issues/5546
|
// See https://github.com/microsoft/playwright/issues/5546
|
||||||
@@ -353,13 +173,6 @@ export async function enterPlaygroundRoom(
|
|||||||
throw new Error(`Uncaught exception: "${exception}"\n${exception.stack}`);
|
throw new Error(`Uncaught exception: "${exception}"\n${exception.stack}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
await initEmptyEditor({
|
|
||||||
page,
|
|
||||||
flags: ops?.flags,
|
|
||||||
noInit: ops?.noInit,
|
|
||||||
multiEditor,
|
|
||||||
});
|
|
||||||
|
|
||||||
const locator = page.locator('affine-editor-container');
|
const locator = page.locator('affine-editor-container');
|
||||||
await locator.isVisible();
|
await locator.isVisible();
|
||||||
await page.evaluate(async () => {
|
await page.evaluate(async () => {
|
||||||
@@ -419,7 +232,6 @@ export async function enterPlaygroundWithList(
|
|||||||
) {
|
) {
|
||||||
const room = generateRandomRoomId();
|
const room = generateRandomRoomId();
|
||||||
await page.goto(`${DEFAULT_PLAYGROUND}?room=${room}`);
|
await page.goto(`${DEFAULT_PLAYGROUND}?room=${room}`);
|
||||||
await initEmptyEditor({ page });
|
|
||||||
|
|
||||||
await page.evaluate(
|
await page.evaluate(
|
||||||
({ contents, type }: { contents: string[]; type: ListType }) => {
|
({ contents, type }: { contents: string[]; type: ListType }) => {
|
||||||
@@ -1439,7 +1251,7 @@ export async function mockParseDocUrlService(
|
|||||||
) {
|
) {
|
||||||
await page.evaluate(mapping => {
|
await page.evaluate(mapping => {
|
||||||
const parseDocUrlService = window.host.std.get(
|
const parseDocUrlService = window.host.std.get(
|
||||||
window.$blocksuite.identifiers.ParseDocUrlService
|
window.$blocksuite.blocks.ParseDocUrlProvider
|
||||||
);
|
);
|
||||||
parseDocUrlService.parseDocUrl = (url: string) => {
|
parseDocUrlService.parseDocUrl = (url: string) => {
|
||||||
const docId = mapping[url];
|
const docId = mapping[url];
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ import {
|
|||||||
inlineEditorInnerTextToString,
|
inlineEditorInnerTextToString,
|
||||||
} from './actions/misc.js';
|
} from './actions/misc.js';
|
||||||
import { getStringFromRichText } from './inline-editor.js';
|
import { getStringFromRichText } from './inline-editor.js';
|
||||||
import { currentEditorIndex } from './multiple-editor.js';
|
|
||||||
|
|
||||||
export { assertExists };
|
export { assertExists };
|
||||||
|
|
||||||
@@ -170,15 +169,14 @@ export async function assertRichTextInlineDeltas(
|
|||||||
i = 0
|
i = 0
|
||||||
) {
|
) {
|
||||||
const actual = await page.evaluate(
|
const actual = await page.evaluate(
|
||||||
([i, currentEditorIndex]) => {
|
([i]) => {
|
||||||
const editorHost =
|
const editorHost = document.querySelector('editor-host');
|
||||||
document.querySelectorAll('editor-host')[currentEditorIndex];
|
const inlineRoot = editorHost?.querySelectorAll<InlineRootElement>(
|
||||||
const inlineRoot = editorHost.querySelectorAll<InlineRootElement>(
|
|
||||||
'rich-text [data-v-root="true"]'
|
'rich-text [data-v-root="true"]'
|
||||||
)[i];
|
)[i];
|
||||||
return inlineRoot.inlineEditor.yTextDeltas;
|
return inlineRoot?.inlineEditor.yTextDeltas;
|
||||||
},
|
},
|
||||||
[i, currentEditorIndex]
|
[i]
|
||||||
);
|
);
|
||||||
expect(actual).toEqual(deltas);
|
expect(actual).toEqual(deltas);
|
||||||
}
|
}
|
||||||
@@ -194,9 +192,8 @@ export async function assertTextContain(page: Page, text: string, i = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function assertRichTexts(page: Page, texts: string[]) {
|
export async function assertRichTexts(page: Page, texts: string[]) {
|
||||||
const actualTexts = await page.evaluate(currentEditorIndex => {
|
const actualTexts = await page.evaluate(() => {
|
||||||
const editorHost =
|
const editorHost = document.querySelector('editor-host');
|
||||||
document.querySelectorAll('editor-host')[currentEditorIndex];
|
|
||||||
const richTexts = Array.from(
|
const richTexts = Array.from(
|
||||||
editorHost?.querySelectorAll<RichText>('rich-text') ?? []
|
editorHost?.querySelectorAll<RichText>('rich-text') ?? []
|
||||||
);
|
);
|
||||||
@@ -204,7 +201,7 @@ export async function assertRichTexts(page: Page, texts: string[]) {
|
|||||||
const editor = richText.inlineEditor as AffineInlineEditor;
|
const editor = richText.inlineEditor as AffineInlineEditor;
|
||||||
return editor.yText.toString();
|
return editor.yText.toString();
|
||||||
});
|
});
|
||||||
}, currentEditorIndex);
|
});
|
||||||
expect(actualTexts).toEqual(texts);
|
expect(actualTexts).toEqual(texts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,14 +315,13 @@ export async function assertRichTextInlineRange(
|
|||||||
rangeLength = 0
|
rangeLength = 0
|
||||||
) {
|
) {
|
||||||
const actual = await page.evaluate(
|
const actual = await page.evaluate(
|
||||||
([richTextIndex, currentEditorIndex]) => {
|
([richTextIndex]) => {
|
||||||
const editorHost =
|
const editorHost = document.querySelector('editor-host');
|
||||||
document.querySelectorAll('editor-host')[currentEditorIndex];
|
|
||||||
const richText = editorHost?.querySelectorAll('rich-text')[richTextIndex];
|
const richText = editorHost?.querySelectorAll('rich-text')[richTextIndex];
|
||||||
const inlineEditor = richText.inlineEditor;
|
const inlineEditor = richText?.inlineEditor;
|
||||||
return inlineEditor?.getInlineRange();
|
return inlineEditor?.getInlineRange();
|
||||||
},
|
},
|
||||||
[richTextIndex, currentEditorIndex]
|
[richTextIndex]
|
||||||
);
|
);
|
||||||
expect(actual).toEqual({ index: rangeIndex, length: rangeLength });
|
expect(actual).toEqual({ index: rangeIndex, length: rangeLength });
|
||||||
}
|
}
|
||||||
@@ -365,11 +361,10 @@ export async function assertTextFormat(
|
|||||||
resultObj: unknown
|
resultObj: unknown
|
||||||
) {
|
) {
|
||||||
const actual = await page.evaluate(
|
const actual = await page.evaluate(
|
||||||
({ richTextIndex, index, currentEditorIndex }) => {
|
({ richTextIndex, index }) => {
|
||||||
const editorHost =
|
const editorHost = document.querySelector('editor-host');
|
||||||
document.querySelectorAll('editor-host')[currentEditorIndex];
|
const richText = editorHost?.querySelectorAll('rich-text')[richTextIndex];
|
||||||
const richText = editorHost.querySelectorAll('rich-text')[richTextIndex];
|
const inlineEditor = richText?.inlineEditor;
|
||||||
const inlineEditor = richText.inlineEditor;
|
|
||||||
if (!inlineEditor) {
|
if (!inlineEditor) {
|
||||||
throw new Error('Inline editor is undefined');
|
throw new Error('Inline editor is undefined');
|
||||||
}
|
}
|
||||||
@@ -380,7 +375,7 @@ export async function assertTextFormat(
|
|||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
{ richTextIndex, index, currentEditorIndex }
|
{ richTextIndex, index }
|
||||||
);
|
);
|
||||||
expect(actual).toEqual(resultObj);
|
expect(actual).toEqual(resultObj);
|
||||||
}
|
}
|
||||||
@@ -391,26 +386,25 @@ export async function assertRichTextModelType(
|
|||||||
index = 0
|
index = 0
|
||||||
) {
|
) {
|
||||||
const actual = await page.evaluate(
|
const actual = await page.evaluate(
|
||||||
({ index, BLOCK_ID_ATTR, currentEditorIndex }) => {
|
({ index, BLOCK_ID_ATTR }) => {
|
||||||
const editorHost =
|
const editorHost = document.querySelector('editor-host');
|
||||||
document.querySelectorAll('editor-host')[currentEditorIndex];
|
const richText = editorHost?.querySelectorAll('rich-text')[index];
|
||||||
const richText = editorHost.querySelectorAll('rich-text')[index];
|
const block = richText?.closest<BlockComponent>(`[${BLOCK_ID_ATTR}]`);
|
||||||
const block = richText.closest<BlockComponent>(`[${BLOCK_ID_ATTR}]`);
|
|
||||||
|
|
||||||
if (!block) {
|
if (!block) {
|
||||||
throw new Error('block component is undefined');
|
throw new Error('block component is undefined');
|
||||||
}
|
}
|
||||||
return (block.model as BlockModel<{ type: string }>).type;
|
return (block.model as BlockModel<{ type: string }>).type;
|
||||||
},
|
},
|
||||||
{ index, BLOCK_ID_ATTR, currentEditorIndex }
|
{ index, BLOCK_ID_ATTR }
|
||||||
);
|
);
|
||||||
expect(actual).toEqual(type);
|
expect(actual).toEqual(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function assertTextFormats(page: Page, resultObj: unknown[]) {
|
export async function assertTextFormats(page: Page, resultObj: unknown[]) {
|
||||||
const actual = await page.evaluate(index => {
|
const actual = await page.evaluate(() => {
|
||||||
const editorHost = document.querySelectorAll('editor-host')[index];
|
const editorHost = document.querySelector('editor-host');
|
||||||
const elements = editorHost.querySelectorAll('rich-text');
|
const elements = editorHost?.querySelectorAll('rich-text') ?? [];
|
||||||
return Array.from(elements).map(el => {
|
return Array.from(elements).map(el => {
|
||||||
const inlineEditor = el.inlineEditor;
|
const inlineEditor = el.inlineEditor;
|
||||||
if (!inlineEditor) {
|
if (!inlineEditor) {
|
||||||
@@ -423,7 +417,7 @@ export async function assertTextFormats(page: Page, resultObj: unknown[]) {
|
|||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
}, currentEditorIndex);
|
});
|
||||||
expect(actual).toEqual(resultObj);
|
expect(actual).toEqual(resultObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,16 +614,16 @@ export async function assertBlockProps(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function assertBlockTypes(page: Page, blockTypes: string[]) {
|
export async function assertBlockTypes(page: Page, blockTypes: string[]) {
|
||||||
const actual = await page.evaluate(index => {
|
const actual = await page.evaluate(() => {
|
||||||
const editor = document.querySelectorAll('affine-editor-container')[index];
|
const editor = document.querySelector('affine-editor-container');
|
||||||
const elements = editor?.querySelectorAll('[data-block-id]');
|
const elements = editor?.querySelectorAll('[data-block-id]') ?? [];
|
||||||
return (
|
return (
|
||||||
Array.from(elements)
|
Array.from(elements)
|
||||||
.slice(2)
|
.slice(2)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
.map(el => el.model.type)
|
.map(el => el.model.type)
|
||||||
);
|
);
|
||||||
}, currentEditorIndex);
|
});
|
||||||
expect(actual).toEqual(blockTypes);
|
expect(actual).toEqual(blockTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,6 @@
|
|||||||
import type {
|
|
||||||
DocModeProvider,
|
|
||||||
DocModeService,
|
|
||||||
ParseDocUrlProvider,
|
|
||||||
QuickSearchProvider,
|
|
||||||
ThemeProvider,
|
|
||||||
} from '@blocksuite/affine-shared/services';
|
|
||||||
import type { EditorHost } from '@blocksuite/block-std';
|
import type { EditorHost } from '@blocksuite/block-std';
|
||||||
import type { RefNodeSlotsProvider } from '@blocksuite/blocks';
|
|
||||||
import type { AffineEditorContainer } from '@blocksuite/presets';
|
import type { AffineEditorContainer } from '@blocksuite/presets';
|
||||||
import type {
|
import type { Store, Transformer, Workspace } from '@blocksuite/store';
|
||||||
BlockModel,
|
|
||||||
ExtensionType,
|
|
||||||
Store,
|
|
||||||
Transformer,
|
|
||||||
Workspace,
|
|
||||||
} from '@blocksuite/store';
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@@ -29,22 +15,9 @@ declare global {
|
|||||||
};
|
};
|
||||||
editor: typeof import('@blocksuite/presets');
|
editor: typeof import('@blocksuite/presets');
|
||||||
blockStd: typeof import('@blocksuite/block-std');
|
blockStd: typeof import('@blocksuite/block-std');
|
||||||
identifiers: {
|
|
||||||
QuickSearchProvider: typeof QuickSearchProvider;
|
|
||||||
DocModeProvider: typeof DocModeProvider;
|
|
||||||
ThemeProvider: typeof ThemeProvider;
|
|
||||||
RefNodeSlotsProvider: typeof RefNodeSlotsProvider;
|
|
||||||
ParseDocUrlService: typeof ParseDocUrlProvider;
|
|
||||||
};
|
|
||||||
defaultExtensions: () => ExtensionType[];
|
|
||||||
mockServices: {
|
|
||||||
mockDocModeService: typeof DocModeService;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
collection: Workspace;
|
collection: Workspace;
|
||||||
blockSchema: Record<string, typeof BlockModel>;
|
|
||||||
doc: Store;
|
doc: Store;
|
||||||
debugMenu: HTMLElement;
|
|
||||||
editor: AffineEditorContainer;
|
editor: AffineEditorContainer;
|
||||||
host: EditorHost;
|
host: EditorHost;
|
||||||
job: Transformer;
|
job: Transformer;
|
||||||
|
|||||||
@@ -3,13 +3,9 @@ import fs from 'node:fs';
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import process from 'node:process';
|
import process from 'node:process';
|
||||||
|
|
||||||
import { expect, type Page, test as baseTest } from '@playwright/test';
|
import { test as baseTest } from '@playwright/test';
|
||||||
|
|
||||||
import {
|
import { scope } from './multiple-editor.js';
|
||||||
enterPlaygroundRoom,
|
|
||||||
initEmptyParagraphState,
|
|
||||||
} from './actions/misc.js';
|
|
||||||
import { currentEditorIndex, scope } from './multiple-editor.js';
|
|
||||||
|
|
||||||
const istanbulTempDir = process.env.ISTANBUL_TEMP_DIR
|
const istanbulTempDir = process.env.ISTANBUL_TEMP_DIR
|
||||||
? path.resolve(process.env.ISTANBUL_TEMP_DIR)
|
? path.resolve(process.env.ISTANBUL_TEMP_DIR)
|
||||||
@@ -59,52 +55,3 @@ export const test = baseTest.extend<{}>({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (scope) {
|
|
||||||
test.beforeEach(async ({ browser }, testInfo) => {
|
|
||||||
if (!testInfo.title.startsWith(scope!)) {
|
|
||||||
testInfo.fn = () => {
|
|
||||||
testInfo.skip();
|
|
||||||
};
|
|
||||||
testInfo.skip();
|
|
||||||
await browser.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let page: Page;
|
|
||||||
|
|
||||||
test.beforeAll(async ({ browser }) => {
|
|
||||||
page = await browser.newPage();
|
|
||||||
});
|
|
||||||
|
|
||||||
// oxlint-disable-next-line no-empty-pattern
|
|
||||||
test.afterAll(async ({}, testInfo) => {
|
|
||||||
if (!testInfo.title.startsWith(scope!)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const focusInSecondEditor = await page.evaluate(
|
|
||||||
([currentEditorIndex]) => {
|
|
||||||
const editor = document.querySelectorAll('affine-editor-container')[
|
|
||||||
currentEditorIndex
|
|
||||||
];
|
|
||||||
const selection = getSelection();
|
|
||||||
if (!selection || selection.rangeCount === 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// once the range exists, it must be in the corresponding editor
|
|
||||||
return editor.contains(selection.getRangeAt(0).startContainer);
|
|
||||||
},
|
|
||||||
[currentEditorIndex]
|
|
||||||
);
|
|
||||||
expect(focusInSecondEditor).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('ensure enable two editor', async ({ page }) => {
|
|
||||||
await enterPlaygroundRoom(page);
|
|
||||||
await initEmptyParagraphState(page);
|
|
||||||
const count = await page.evaluate(() => {
|
|
||||||
return document.querySelectorAll('affine-editor-container').length;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(count).toBe(2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user