mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-19 00:10:39 +08:00
feat: improve provider testing (#1280)
This commit is contained in:
@@ -14,3 +14,4 @@ ENABLE_IDB_PROVIDER=1
|
|||||||
PREFETCH_WORKSPACE=1
|
PREFETCH_WORKSPACE=1
|
||||||
ENABLE_BC_PROVIDER=1
|
ENABLE_BC_PROVIDER=1
|
||||||
EXPOSE_INTERNAL=1
|
EXPOSE_INTERNAL=1
|
||||||
|
ENABLE_DEBUG_PAGE=
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ const nextConfig = {
|
|||||||
return profile;
|
return profile;
|
||||||
},
|
},
|
||||||
basePath: process.env.NEXT_BASE_PATH,
|
basePath: process.env.NEXT_BASE_PATH,
|
||||||
|
pageExtensions: [...(preset.enableDebugPage ? ['tsx', 'dev.tsx'] : ['tsx'])],
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseDir = process.env.LOCAL_BLOCK_SUITE ?? '/';
|
const baseDir = process.env.LOCAL_BLOCK_SUITE ?? '/';
|
||||||
|
|||||||
@@ -7,5 +7,6 @@ const config = {
|
|||||||
),
|
),
|
||||||
prefetchWorkspace: Boolean(process.env.PREFETCH_WORKSPACE ?? '1'),
|
prefetchWorkspace: Boolean(process.env.PREFETCH_WORKSPACE ?? '1'),
|
||||||
exposeInternal: Boolean(process.env.EXPOSE_INTERNAL ?? '1'),
|
exposeInternal: Boolean(process.env.EXPOSE_INTERNAL ?? '1'),
|
||||||
|
enableDebugPage: Boolean(process.env.ENABLE_DEBUG_PAGE ?? false),
|
||||||
};
|
};
|
||||||
export default config;
|
export default config;
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { DebugLogger } from '@affine/debug';
|
||||||
|
|
||||||
|
export const providerLogger = new DebugLogger('provider');
|
||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
} from 'y-protocols/awareness';
|
} from 'y-protocols/awareness';
|
||||||
|
|
||||||
import { BlockSuiteWorkspace, BroadCastChannelProvider } from '../../../shared';
|
import { BlockSuiteWorkspace, BroadCastChannelProvider } from '../../../shared';
|
||||||
|
import { providerLogger } from '../../logger';
|
||||||
import {
|
import {
|
||||||
AwarenessChanges,
|
AwarenessChanges,
|
||||||
BroadcastChannelMessageEvent,
|
BroadcastChannelMessageEvent,
|
||||||
@@ -83,7 +84,10 @@ export const createBroadCastChannelProvider = (
|
|||||||
onmessage: handleBroadcastChannelMessage,
|
onmessage: handleBroadcastChannelMessage,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
console.log('connect broadcast channel', blockSuiteWorkspace.room);
|
providerLogger.info(
|
||||||
|
'connect broadcast channel',
|
||||||
|
blockSuiteWorkspace.room
|
||||||
|
);
|
||||||
const docDiff = Y.encodeStateVector(doc);
|
const docDiff = Y.encodeStateVector(doc);
|
||||||
broadcastChannel.postMessage(['doc:diff', docDiff, awareness.clientID]);
|
broadcastChannel.postMessage(['doc:diff', docDiff, awareness.clientID]);
|
||||||
const docUpdateV2 = Y.encodeStateAsUpdate(doc);
|
const docUpdateV2 = Y.encodeStateAsUpdate(doc);
|
||||||
@@ -98,7 +102,10 @@ export const createBroadCastChannelProvider = (
|
|||||||
},
|
},
|
||||||
disconnect: () => {
|
disconnect: () => {
|
||||||
assertExists(broadcastChannel);
|
assertExists(broadcastChannel);
|
||||||
console.log('disconnect broadcast channel', blockSuiteWorkspace.room);
|
providerLogger.info(
|
||||||
|
'disconnect broadcast channel',
|
||||||
|
blockSuiteWorkspace.room
|
||||||
|
);
|
||||||
doc.off('update', handleDocUpdate);
|
doc.off('update', handleDocUpdate);
|
||||||
awareness.off('update', handleAwarenessUpdate);
|
awareness.off('update', handleAwarenessUpdate);
|
||||||
broadcastChannel.close();
|
broadcastChannel.close();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
LocalIndexedDBProvider,
|
LocalIndexedDBProvider,
|
||||||
} from '../../shared';
|
} from '../../shared';
|
||||||
import { apis } from '../../shared/apis';
|
import { apis } from '../../shared/apis';
|
||||||
|
import { providerLogger } from '../logger';
|
||||||
import { createBroadCastChannelProvider } from './broad-cast-channel';
|
import { createBroadCastChannelProvider } from './broad-cast-channel';
|
||||||
|
|
||||||
const createWebSocketProvider = (
|
const createWebSocketProvider = (
|
||||||
@@ -18,7 +19,8 @@ const createWebSocketProvider = (
|
|||||||
flavour: 'affine-websocket',
|
flavour: 'affine-websocket',
|
||||||
cleanup: () => {
|
cleanup: () => {
|
||||||
assertExists(webSocketProvider);
|
assertExists(webSocketProvider);
|
||||||
webSocketProvider?.destroy();
|
webSocketProvider.destroy();
|
||||||
|
webSocketProvider = null;
|
||||||
},
|
},
|
||||||
connect: () => {
|
connect: () => {
|
||||||
const wsUrl = `${
|
const wsUrl = `${
|
||||||
@@ -34,15 +36,17 @@ const createWebSocketProvider = (
|
|||||||
awareness: blockSuiteWorkspace.awarenessStore.awareness,
|
awareness: blockSuiteWorkspace.awarenessStore.awareness,
|
||||||
// we maintain broadcast channel by ourselves
|
// we maintain broadcast channel by ourselves
|
||||||
disableBc: true,
|
disableBc: true,
|
||||||
|
connect: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
console.log('connect', webSocketProvider.roomname);
|
providerLogger.info('connect', webSocketProvider.roomname);
|
||||||
webSocketProvider.connect();
|
webSocketProvider.connect();
|
||||||
},
|
},
|
||||||
disconnect: () => {
|
disconnect: () => {
|
||||||
assertExists(webSocketProvider);
|
assertExists(webSocketProvider);
|
||||||
console.log('disconnect', webSocketProvider.roomname);
|
providerLogger.info('disconnect', webSocketProvider.roomname);
|
||||||
webSocketProvider?.disconnect();
|
webSocketProvider.destroy();
|
||||||
|
webSocketProvider = null;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -58,7 +62,10 @@ const createIndexedDBProvider = (
|
|||||||
indexdbProvider.clearData();
|
indexdbProvider.clearData();
|
||||||
},
|
},
|
||||||
connect: () => {
|
connect: () => {
|
||||||
console.info('connect indexeddb provider', blockSuiteWorkspace.room);
|
providerLogger.info(
|
||||||
|
'connect indexeddb provider',
|
||||||
|
blockSuiteWorkspace.room
|
||||||
|
);
|
||||||
indexdbProvider = new IndexeddbPersistence(
|
indexdbProvider = new IndexeddbPersistence(
|
||||||
blockSuiteWorkspace.room as string,
|
blockSuiteWorkspace.room as string,
|
||||||
blockSuiteWorkspace.doc
|
blockSuiteWorkspace.doc
|
||||||
@@ -66,7 +73,10 @@ const createIndexedDBProvider = (
|
|||||||
},
|
},
|
||||||
disconnect: () => {
|
disconnect: () => {
|
||||||
assertExists(indexdbProvider);
|
assertExists(indexdbProvider);
|
||||||
console.info('disconnect indexeddb provider', blockSuiteWorkspace.room);
|
providerLogger.info(
|
||||||
|
'disconnect indexeddb provider',
|
||||||
|
blockSuiteWorkspace.room
|
||||||
|
);
|
||||||
indexdbProvider.destroy();
|
indexdbProvider.destroy();
|
||||||
indexdbProvider = null;
|
indexdbProvider = null;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# `_Debug` Pages
|
||||||
|
|
||||||
|
These pages are only available in development mode.
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import { Button, toast } from '@affine/component';
|
||||||
|
import { DebugLogger } from '@affine/debug';
|
||||||
|
import { nanoid } from '@blocksuite/store';
|
||||||
|
import { Typography } from '@mui/material';
|
||||||
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import { createBroadCastChannelProvider } from '../../blocksuite/providers';
|
||||||
|
import PageList from '../../components/blocksuite/block-suite-page-list/page-list';
|
||||||
|
import { StyledPage, StyledWrapper } from '../../layouts/styles';
|
||||||
|
import { BroadCastChannelProvider } from '../../shared';
|
||||||
|
import { createEmptyBlockSuiteWorkspace } from '../../utils';
|
||||||
|
|
||||||
|
const logger = new DebugLogger('broadcast');
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
|
var currentBroadCastChannel: BroadCastChannelProvider | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BroadcastPage: React.FC = () => {
|
||||||
|
const blockSuiteWorkspace = useMemo(
|
||||||
|
() => createEmptyBlockSuiteWorkspace('broadcast-test'),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
const [provider, setProvider] = useState<BroadCastChannelProvider | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
useEffect(() => {
|
||||||
|
globalThis.currentBlockSuiteWorkspace = blockSuiteWorkspace;
|
||||||
|
}, [blockSuiteWorkspace]);
|
||||||
|
useEffect(() => {
|
||||||
|
const provider = createBroadCastChannelProvider(blockSuiteWorkspace);
|
||||||
|
setProvider(provider);
|
||||||
|
globalThis.currentBroadCastChannel = provider;
|
||||||
|
provider.connect();
|
||||||
|
return () => {
|
||||||
|
provider.disconnect();
|
||||||
|
globalThis.currentBroadCastChannel = undefined;
|
||||||
|
setProvider(null);
|
||||||
|
};
|
||||||
|
}, [blockSuiteWorkspace]);
|
||||||
|
if (!provider) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<StyledPage>
|
||||||
|
<StyledWrapper>
|
||||||
|
<Typography variant="h5">Broadcast Provider Test</Typography>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
data-testid="create-page"
|
||||||
|
onClick={() => {
|
||||||
|
logger.info('create page');
|
||||||
|
blockSuiteWorkspace.createPage(nanoid());
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Create Page
|
||||||
|
</Button>
|
||||||
|
<PageList
|
||||||
|
blockSuiteWorkspace={blockSuiteWorkspace}
|
||||||
|
onClickPage={() => {
|
||||||
|
toast('do nothing');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</StyledWrapper>
|
||||||
|
</StyledPage>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BroadcastPage;
|
||||||
@@ -30,6 +30,7 @@ export const createEmptyBlockSuiteWorkspace = (
|
|||||||
) => {
|
) => {
|
||||||
return new BlockSuiteWorkspace({
|
return new BlockSuiteWorkspace({
|
||||||
room,
|
room,
|
||||||
|
isSSR: typeof window === 'undefined',
|
||||||
blobOptionsGetter,
|
blobOptionsGetter,
|
||||||
})
|
})
|
||||||
.register(builtInSchemas)
|
.register(builtInSchemas)
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ const config: PlaywrightTestConfig = {
|
|||||||
reuseExistingServer: !process.env.CI,
|
reuseExistingServer: !process.env.CI,
|
||||||
env: {
|
env: {
|
||||||
COVERAGE: process.env.COVERAGE || 'false',
|
COVERAGE: process.env.COVERAGE || 'false',
|
||||||
|
ENABLE_DEBUG_PAGE: '1',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { expect } from '@playwright/test';
|
||||||
|
|
||||||
|
import { test } from './libs/playwright';
|
||||||
|
|
||||||
|
test.describe('Debug page broadcast', () => {
|
||||||
|
test('should broadcast a message to all debug pages', async ({
|
||||||
|
page,
|
||||||
|
context,
|
||||||
|
}) => {
|
||||||
|
await page.goto('http://localhost:8080/_debug/broadcast');
|
||||||
|
const page2 = await context.newPage();
|
||||||
|
await page2.goto('http://localhost:8080/_debug/broadcast');
|
||||||
|
await page.waitForSelector('#__next');
|
||||||
|
await page2.waitForSelector('#__next');
|
||||||
|
await page.click('[data-testid="create-page"]');
|
||||||
|
expect(await page.locator('tr').count()).toBe(2);
|
||||||
|
expect(await page2.locator('tr').count()).toBe(2);
|
||||||
|
await page2.click('[data-testid="create-page"]');
|
||||||
|
expect(await page.locator('tr').count()).toBe(3);
|
||||||
|
expect(await page2.locator('tr').count()).toBe(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user