Skip to content
This repository has been archived by the owner on Jan 8, 2024. It is now read-only.

feat: support multiple workspace #34

Merged
merged 32 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ on:
pull_request:
branches: [ main ]

env:
COVERAGE: true

jobs:
lint:
name: Lint
Expand Down Expand Up @@ -90,6 +93,16 @@ jobs:
- name: Test
run: pnpm test
working-directory: apps/desktop
- name: Collect coverage
run: pnpm exec nyc report -t .nyc_output --report-dir coverage --reporter=json
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
with:
name: refine-desktop
flags: apps
token: ${{ secrets.CODECOV_TOKEN }}
directory: ./coverage

test-server:
name: Test Server
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
},
"dependencies": {
"@blocksuite/editor": "0.0.0-20231101080734-aa27dc89-nightly",
"@blocksuite/store": "0.0.0-20231101080734-aa27dc89-nightly",
"@refine/core": "workspace:*",
"jotai": "^2.5.1",
"jotai-inject": "workspace:*",
Expand All @@ -24,6 +25,7 @@
"dmg-builder": "24.8.1",
"electron": "27.0.3",
"electron-builder": "24.7.0",
"v8-to-istanbul": "^9.1.3",
"vite": "^4.5.0",
"vite-plugin-electron": "^0.15.2",
"vite-plugin-electron-renderer": "^0.14.5"
Expand Down
8 changes: 6 additions & 2 deletions apps/desktop/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import type { PlaywrightTestConfig } from '@playwright/test'
* See https://playwright.dev/docs/test-configuration.
*/
const config: PlaywrightTestConfig = {
testDir: './tests',
testDir: './test',
fullyParallel: true,
timeout: process.env.CI ? 50_000 : 30_000,
webServer: {
command: 'pnpm run dev',
port: 5173
port: 5173,
reuseExistingServer: !process.env.CI,
env: {
COVERAGE: process.env.COVERAGE === 'true' ? 'true' : '',
}
},
reporter: process.env.CI
? [
Expand Down
60 changes: 43 additions & 17 deletions apps/desktop/src/web/main.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,63 @@
import { StrictMode, lazy } from 'react'
import { createRoot } from 'react-dom/client'
import '@blocksuite/editor/themes/affine.css'
import { themeAtom } from '@refine/core/store'
import { inject } from 'jotai-inject'
import './index.css'
import { workspaceManager } from '@refine/core/store'
import { getDefaultStore } from 'jotai/vanilla'
import { Workspace } from '@blocksuite/store'

declare global {
interface Window {
apis: {
getTheme (): Promise<'light' | 'dark'>
changeTheme (theme: 'light' | 'dark'): Promise<void>
}
workspace: Workspace
}
}

inject(
themeAtom,
() => window.apis.getTheme(),
(theme) => {
window.apis.changeTheme(theme).catch(console.error)
document.documentElement.setAttribute('data-theme', theme)
}
)
const workspaceAtom = workspaceManager.getWorkspaceAtom('workspace:0')
const store = getDefaultStore()

const promise = workspaceManager.withLocalProvider().
then(workspaceManager.inject).
then(
() => store.get(workspaceAtom).then(async workspace => {
window.workspace = workspace
const page = workspace.getPage('page0')
if (!page) {
const page = workspace.createPage({
id: 'page0'
})
await page.waitForLoaded()
const pageBlockId = page.addBlock('affine:page', {
children: [],
title: new page.Text('Untitled')
})
page.addBlock('affine:surface', {}, pageBlockId)
const noteBlockId = page.addBlock('affine:note', {}, pageBlockId)
page.addBlock('affine:paragraph', {}, noteBlockId)
} else {
await page.waitForLoaded()
}
})
)

export const LazyApp = lazy(
() => import('@refine/core/app').then(({ App }) => ({ default: App })))
export const Editor = lazy(
() => import('@refine/core/components').then(
({ Editor }) => ({ default: Editor })))

const div = document.getElementById('root')
if (!div) throw new Error('Root element not found')

const root = createRoot(div)
root.render(
<StrictMode>
<LazyApp/>
</StrictMode>
)
promise.then(() => {
root.render(
<StrictMode>
<Editor
workspaceId="workspace:0"
pageId="page0"
/>
</StrictMode>
)
})
111 changes: 111 additions & 0 deletions apps/desktop/test/basic.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import {
expect,
_electron as electron,
type ConsoleMessage,
type ElectronApplication
} from '@playwright/test'
import path, { resolve } from 'node:path'
import { main } from '../package.json'
import { test as baseTest } from '@playwright/test'
import crypto from 'node:crypto'
import fs from 'node:fs/promises'
import type { Workspace } from '@blocksuite/store'
import { Page } from '@blocksuite/store'

const istanbulTempDir = path.join(__dirname, '..', '..', '..', '.nyc_output')

declare global {
interface Window {
__coverage__: Record<string, unknown>

collectIstanbulCoverage (coverageJson: string): Promise<void>
workspace: Workspace
}
}

const test = baseTest.extend<{
electronApp: ElectronApplication,
firstWindow: Awaited<ReturnType<ElectronApplication['firstWindow']>>,
context: never
}>({
// eslint-disable-next-line no-empty-pattern
electronApp: async ({}, use) => {
const cacheDir = resolve(__dirname, '.cache')
const guid = crypto.randomUUID()
const electronApp = await electron.launch({
colorScheme: 'light',
args: [
main,
'--force-device-scale-factor=1',
'--disable-dev-shm-usage',
'--no-sandbox',
'--enable-logging'
],
cwd: resolve(__dirname, '..'),
locale: 'en-US',
executablePath: require('electron/index.js'),
env: {
VITE_DEV_SERVER_URL: 'http://localhost:5173',
SESSION_DATA_PATH: resolve(cacheDir, guid)
}
})
await use(electronApp)
await electronApp.close()
},
firstWindow: async ({ electronApp }, use) => {
const firstWindow = await electronApp.firstWindow()
const enableCoverage = process.env.COVERAGE === 'true'
if (enableCoverage) {
await firstWindow.addInitScript(() =>
window.addEventListener('beforeunload', () =>
window.collectIstanbulCoverage(JSON.stringify(window.__coverage__))
)
)
await fs.mkdir(istanbulTempDir, { recursive: true })
await firstWindow.exposeFunction('collectIstanbulCoverage',
async (coverageJSON: string) => {
if (coverageJSON)
await fs.writeFile(
path.join(
istanbulTempDir,
`playwright_coverage_${crypto.randomUUID()}.json`
),
coverageJSON
)
})
}
await use(firstWindow)
if (enableCoverage) {
await firstWindow.evaluate(() => {
window.collectIstanbulCoverage(JSON.stringify(window.__coverage__))
})
}
await firstWindow.close()
},
page: async ({ firstWindow: page }, use) => {
const callback = (msg: ConsoleMessage) => {
console.log(`${msg.type()}: ${msg.text()}`)
}
page.on('console', callback)
await use(page)
page.off('console', callback)
}
})

test.describe('app basic functionality', () => {
test('should editor basic functionality works', async ({ page }) => {
await expect(page.getByText('Untitled')).toBeVisible()
await page.evaluate(async () => {
const workspace = window.workspace
const pageId = [...workspace.pages.keys()][0]
const page = workspace.getPage(pageId) as Page
const noteId = page.getBlockByFlavour('affine:note')[0].id
page.addBlock('affine:paragraph', {
text: new page.Text('test')
}, noteId)
})
await expect(page.getByText('test')).toBeVisible()
await page.reload()
await expect(page.getByText('test')).toBeVisible()
})
})
56 changes: 0 additions & 56 deletions apps/desktop/tests/basic.spec.ts

This file was deleted.

11 changes: 11 additions & 0 deletions apps/desktop/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,21 @@
"tsBuildInfoFile": "./dist/node/.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["DOM"],
"types": ["node"]
},
"include": [
"./test",
"package.json",
"vite.config.ts",
"rollup.config.ts"
],
"references": [
{
"path": "./tsconfig.src.json"
},
{
"path": "./tsconfig.web.json"
}
]
}
3 changes: 0 additions & 3 deletions apps/desktop/tsconfig.src.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
"references": [
{
"path": "./tsconfig.web.json"
},
{
"path": "./tsconfig.node.json"
}
]
}
Loading