test: add test case for blocksuite editor (#1528)

This commit is contained in:
Himself65
2023-03-10 17:45:10 -06:00
committed by GitHub
parent 1c89841d6f
commit a795000363
19 changed files with 495 additions and 488 deletions

View File

@@ -7,6 +7,8 @@ const config = {
),
prefetchWorkspace: Boolean(process.env.PREFETCH_WORKSPACE ?? '1'),
exposeInternal: Boolean(process.env.EXPOSE_INTERNAL ?? '1'),
enableDebugPage: Boolean(process.env.ENABLE_DEBUG_PAGE ?? false),
enableDebugPage: Boolean(
process.env.ENABLE_DEBUG_PAGE ?? process.env.NODE_ENV === 'development'
),
};
export default config;

View File

@@ -0,0 +1,71 @@
'use client';
import { EditorContainer } from '@blocksuite/editor';
import { assertEquals, assertExists, Generator, Page } from '@blocksuite/store';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { createEmptyBlockSuiteWorkspace } from '../../../utils';
import { BlockSuiteEditor } from '../../blocksuite/block-suite-editor';
const blockSuiteWorkspace = createEmptyBlockSuiteWorkspace(
'test',
_ => undefined,
Generator.AutoIncrement
);
blockSuiteWorkspace.createPage('page0');
const Editor: React.FC<{
onInit: (page: Page, editor: Readonly<EditorContainer>) => void;
testType: 'empty' | 'importMarkdown';
}> = ({ onInit, testType }) => {
const page = blockSuiteWorkspace.getPage('page0');
const [, rerender] = useState(false);
const onceRef = useRef(false);
if (!onceRef.current) {
if (testType === 'importMarkdown') {
if (page) {
page.workspace.meta.setPageMeta(page.id, {
init: true,
});
} else {
blockSuiteWorkspace.slots.pageAdded.on(id => {
const page = blockSuiteWorkspace.getPage(id);
assertExists(page);
assertEquals(id, 'page0');
page.workspace.meta.setPageMeta(page.id, {
init: true,
});
});
}
}
}
useEffect(() => {
const cb = () => rerender(v => !v);
const dispose = blockSuiteWorkspace.slots.pageAdded.on(cb);
return () => {
dispose.dispose();
};
}, []);
const onLoad = useCallback((page: Page, editor: EditorContainer) => {
// @ts-ignore
globalThis.page = page;
// @ts-ignore
globalThis.editor = editor;
}, []);
if (!page) {
return <>loading...</>;
}
return (
<BlockSuiteEditor
blockSuiteWorkspace={blockSuiteWorkspace}
page={page}
mode="page"
onInit={onInit}
onLoad={onLoad}
/>
);
};
export default Editor;

View File

@@ -11,23 +11,11 @@ export type EditorProps = {
blockSuiteWorkspace: BlockSuiteWorkspace;
page: Page;
mode: 'page' | 'edgeless';
onInit?: (page: Page, editor: Readonly<EditorContainer>) => void;
onInit: (page: Page, editor: Readonly<EditorContainer>) => void;
onLoad?: (page: Page, editor: EditorContainer) => void;
style?: CSSProperties;
};
import markdown from '../../../templates/Welcome-to-AFFiNE.md';
const exampleTitle = markdown
.split('\n')
.splice(0, 1)
.join('')
.replaceAll('#', '')
.trim();
const exampleText = markdown.split('\n').slice(1).join('\n');
const kFirstPage = 'affine-first-page';
declare global {
// eslint-disable-next-line no-var
var currentBlockSuiteWorkspace: BlockSuiteWorkspace | undefined;
@@ -60,31 +48,7 @@ export const BlockSuiteEditor = (props: EditorProps) => {
editor.page = page;
if (page.root === null) {
if (props.onInit) {
props.onInit(page, editor);
} else {
console.debug('Initializing page with default content');
// Add page block and surface block at root level
const isFirstPage = page.meta.init === true;
if (isFirstPage) {
page.workspace.setPageMeta(page.id, {
init: false,
});
}
const title = isFirstPage ? exampleTitle : undefined;
const pageBlockId = page.addBlockByFlavour('affine:page', {
title: new page.Text(title),
});
page.addBlockByFlavour('affine:surface', {}, null);
const frameId = page.addBlockByFlavour('affine:frame', {}, pageBlockId);
page.addBlockByFlavour('affine:paragraph', {}, frameId);
if (isFirstPage) {
editor.clipboard.importMarkdown(exampleText, frameId);
props.blockSuiteWorkspace.setPageMeta(page.id, { title });
localStorage.setItem(kFirstPage, 'true');
}
page.resetHistory();
}
props.onInit(page, editor);
}
if (config.exposeInternal) {
globalThis.currentBlockSuiteWorkspace = props.blockSuiteWorkspace;

View File

@@ -15,7 +15,7 @@ export type PageDetailEditorProps = {
isPreview?: boolean;
blockSuiteWorkspace: BlockSuiteWorkspace;
pageId: string;
onInit?: (page: Page, editor: Readonly<EditorContainer>) => void;
onInit: (page: Page, editor: Readonly<EditorContainer>) => void;
onLoad?: (page: Page, editor: EditorContainer) => void;
header?: React.ReactNode;
};

View File

@@ -0,0 +1,41 @@
import { NoSsr } from '@mui/material';
import dynamic from 'next/dynamic';
import { useRouter } from 'next/router';
import { StyledPage, StyledWrapper } from '../../layouts/styles';
import { NextPageWithLayout } from '../../shared';
import { initPage } from '../../utils/blocksuite';
const Editor = dynamic(
() => import('../../components/__debug__/client/Editor'),
{
ssr: false,
}
);
const InitPagePage: NextPageWithLayout = () => {
const router = useRouter();
if (!router.isReady) {
return <>loading...</>;
}
let testType: 'empty' | 'importMarkdown' = 'empty';
if (router.query.type === 'importMarkdown') {
testType = 'importMarkdown';
} else if (router.query.type === 'empty') {
testType = 'empty';
}
return (
<StyledPage>
<StyledWrapper>
<Editor onInit={initPage} testType={testType} />
<div id="toolWrapper" />
</StyledWrapper>
</StyledPage>
);
};
export default InitPagePage;
InitPagePage.getLayout = page => {
return <NoSsr>{page}</NoSsr>;
};

View File

@@ -23,6 +23,7 @@ import { useBlockSuiteWorkspaceAvatarUrl } from '../../../hooks/use-blocksuite-w
import { useBlockSuiteWorkspaceName } from '../../../hooks/use-blocksuite-workspace-name';
import { WorkspaceLayout } from '../../../layouts';
import { NextPageWithLayout } from '../../../shared';
import { initPage } from '../../../utils/blocksuite';
export const NavContainer = styled('div')(({ theme }) => {
return {
@@ -85,6 +86,7 @@ const PublicWorkspaceDetailPageInner: React.FC<{
const { page } = editor;
page.awarenessStore.setReadonly(page, true);
}}
onInit={initPage}
header={
<NavContainer>
<Breadcrumbs>

View File

@@ -16,6 +16,7 @@ import {
} from '../../shared';
import { apis, clientAuth } from '../../shared/apis';
import { createEmptyBlockSuiteWorkspace } from '../../utils';
import { initPage } from '../../utils/blocksuite';
import { WorkspacePlugin } from '..';
import { QueryKey } from './fetcher';
@@ -215,6 +216,7 @@ export const AffinePlugin: WorkspacePlugin<RemWorkspaceFlavour.AFFINE> = {
<PageDetailEditor
pageId={currentPageId}
blockSuiteWorkspace={currentWorkspace.blockSuiteWorkspace}
onInit={initPage}
/>
</>
);

View File

@@ -17,6 +17,7 @@ import {
RemWorkspaceFlavour,
} from '../../shared';
import { createEmptyBlockSuiteWorkspace } from '../../utils';
import { initPage } from '../../utils/blocksuite';
import { WorkspacePlugin } from '..';
const getStorage = () => createJSONStorage(() => localStorage);
@@ -117,6 +118,7 @@ export const LocalPlugin: WorkspacePlugin<RemWorkspaceFlavour.LOCAL> = {
<>
<PageDetailEditor
pageId={currentPageId}
onInit={initPage}
blockSuiteWorkspace={currentWorkspace.blockSuiteWorkspace}
/>
</>

View File

@@ -0,0 +1,55 @@
import { DebugLogger } from '@affine/debug';
import { EditorContainer } from '@blocksuite/editor';
import { Page } from '@blocksuite/store';
import markdown from '../templates/Welcome-to-AFFiNE.md';
const demoTitle = markdown
.split('\n')
.splice(0, 1)
.join('')
.replaceAll('#', '')
.trim();
const demoText = markdown.split('\n').slice(1).join('\n');
const logger = new DebugLogger('init-page');
export function initPage(page: Page, editor: Readonly<EditorContainer>): void {
logger.debug('initEmptyPage', page.id);
// Add page block and surface block at root level
const isFirstPage = page.meta.init === true;
if (isFirstPage) {
page.workspace.setPageMeta(page.id, {
init: false,
});
_initPageWithDemoMarkdown(page, editor);
} else {
_initEmptyPage(page, editor);
}
page.resetHistory();
}
export function _initEmptyPage(page: Page, _: Readonly<EditorContainer>) {
const pageBlockId = page.addBlockByFlavour('affine:page', {
title: new page.Text(''),
});
page.addBlockByFlavour('affine:surface', {}, null);
const frameId = page.addBlockByFlavour('affine:frame', {}, pageBlockId);
page.addBlockByFlavour('affine:paragraph', {}, frameId);
}
export function _initPageWithDemoMarkdown(
page: Page,
editor: Readonly<EditorContainer>
): void {
logger.debug('initPageWithDefaultMarkdown', page.id);
const pageBlockId = page.addBlockByFlavour('affine:page', {
title: new page.Text(demoTitle),
});
page.addBlockByFlavour('affine:surface', {}, null);
const frameId = page.addBlockByFlavour('affine:frame', {}, pageBlockId);
page.addBlockByFlavour('affine:paragraph', {}, frameId);
editor.clipboard.importMarkdown(demoText, frameId);
page.workspace.setPageMeta(page.id, { demoTitle });
}

View File

@@ -1,5 +1,5 @@
import { __unstableSchemas, builtInSchemas } from '@blocksuite/blocks/models';
import type { BlobOptionsGetter } from '@blocksuite/store';
import type { BlobOptionsGetter, Generator } from '@blocksuite/store';
import { BlockSuiteWorkspace } from '../shared';
@@ -27,7 +27,8 @@ export function stringToColour(str: string) {
const hashMap = new Map<string, BlockSuiteWorkspace>();
export const createEmptyBlockSuiteWorkspace = (
id: string,
blobOptionsGetter?: BlobOptionsGetter
blobOptionsGetter?: BlobOptionsGetter,
idGenerator?: Generator
): BlockSuiteWorkspace => {
if (hashMap.has(id)) {
return hashMap.get(id) as BlockSuiteWorkspace;
@@ -36,6 +37,7 @@ export const createEmptyBlockSuiteWorkspace = (
id,
isSSR: typeof window === 'undefined',
blobOptionsGetter,
idGenerator,
})
.register(builtInSchemas)
.register(__unstableSchemas);