diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cb4919409f..81f432235a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -276,6 +276,7 @@ jobs: name: E2E Migration Test runs-on: ubuntu-latest environment: development + needs: [build-web] steps: - uses: actions/checkout@v3 @@ -284,6 +285,12 @@ jobs: with: playwright-install: true + - name: Download next static + uses: actions/download-artifact@v3 + with: + name: next-js-static + path: ./apps/web/out + - name: Unzip run: yarn unzip working-directory: ./tests/affine-legacy/0.7.0-canary.18 @@ -292,6 +299,14 @@ jobs: run: yarn e2e --forbid-only working-directory: ./tests/affine-legacy/0.7.0-canary.18 + - name: Upload test results + if: ${{ failure() }} + uses: actions/upload-artifact@v3 + with: + name: test-results-e2e-migration + path: ./tests/affine-legacy/0.7.0-canary.18/test-results + if-no-files-found: ignore + desktop-test: name: Desktop Test runs-on: ${{ matrix.spec.os }} diff --git a/package.json b/package.json index 14507a36b3..23de058b49 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "build:storybook": "nx build @affine/storybook", "build:plugins": "./apps/electron/scripts/plugins/build-plugins.mjs", "start:web": "yarn workspace @affine/web start", + "start:web-static": "yarn exec serve apps/web/out -l 8080", "start:storybook": "yarn exec serve apps/storybook/storybook-static -l 6006", "serve:test-static": "yarn exec serve tests/fixtures --cors -p 8081", "lint": "eslint . --ext .js,mjs,.ts,.tsx --cache", diff --git a/playwright.config.ts b/playwright.config.ts index 07f21ef8ec..f2ad7caee2 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -71,8 +71,6 @@ const config: PlaywrightTestConfig = { reuseExistingServer: !process.env.CI, env: { COVERAGE: process.env.COVERAGE || 'false', - ENABLE_DEBUG_PAGE: '1', - API_SERVER_PROFILE: 'local', }, }, ], diff --git a/tests/affine-legacy/0.7.0-canary.18/.gitignore b/tests/affine-legacy/0.7.0-canary.18/.gitignore index afadae9297..c953fbf54e 100644 --- a/tests/affine-legacy/0.7.0-canary.18/.gitignore +++ b/tests/affine-legacy/0.7.0-canary.18/.gitignore @@ -1,2 +1,3 @@ static -tests/fixtures/*.ydoc +fixtures/*.ydoc +test-results diff --git a/tests/affine-legacy/0.7.0-canary.18/e2e/basic.spec.ts b/tests/affine-legacy/0.7.0-canary.18/e2e/basic.spec.ts new file mode 100644 index 0000000000..ddf1941765 --- /dev/null +++ b/tests/affine-legacy/0.7.0-canary.18/e2e/basic.spec.ts @@ -0,0 +1,87 @@ +import { resolve } from 'node:path'; + +import { test } from '@playwright/test'; +import express from 'express'; +import { createProxyMiddleware } from 'http-proxy-middleware'; + +let app: express.Express; +let server: ReturnType; + +process.env.DEBUG = 'http-proxy-middleware*'; + +async function switchToNext() { + // close previous express server + await new Promise((resolve, reject) => { + server.close(err => { + if (err) { + reject(err); + } + resolve(); + }); + }); + app = express(); + app.use( + createProxyMiddleware({ + target: 'http://localhost:8080', + pathFilter: ['**'], + changeOrigin: true, + }) + ); + return new Promise(resolve => { + server = app.listen(8081, () => { + console.log('proxy to next.js server'); + resolve(); + }); + }); +} + +test.beforeEach(() => { + app = express(); + app.use(express.static(resolve(__dirname, '..', 'static'))); + server = app.listen(8081); +}); + +test.afterEach(() => { + server.close(); +}); + +test('init page', async ({ page, context }) => { + { + // make sure 8080 is ready + const page = await context.newPage(); + await page.goto('http://localhost:8080/'); + await page.waitForSelector('v-line', { + timeout: 10000, + }); + await page.close(); + } + await page.goto('http://localhost:8081/'); + await page.waitForSelector('v-line', { + timeout: 10000, + }); + + const currentWorkspaceId: string = await page.evaluate( + () => (globalThis as any).currentWorkspace.id + ); + + const downloadPromise = page.waitForEvent('download'); + await page.evaluate(() => { + const workspace = (globalThis as any).currentWorkspace.blockSuiteWorkspace; + workspace.exportYDoc(); + }); + + const download = await downloadPromise; + const output = resolve( + __dirname, + '..', + 'fixtures', + currentWorkspaceId + '.ydoc' + ); + await download.saveAs(output); + await switchToNext(); + await page.waitForTimeout(1000); + await page.goto('http://localhost:8081/'); + await page.waitForSelector('v-line', { + timeout: 10000, + }); +}); diff --git a/tests/affine-legacy/0.7.0-canary.18/fixtures/.gitkeep b/tests/affine-legacy/0.7.0-canary.18/fixtures/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/affine-legacy/0.7.0-canary.18/package.json b/tests/affine-legacy/0.7.0-canary.18/package.json index 075733e1e4..ff82301f15 100644 --- a/tests/affine-legacy/0.7.0-canary.18/package.json +++ b/tests/affine-legacy/0.7.0-canary.18/package.json @@ -3,15 +3,23 @@ "description": "AFFiNE 0.7.0-canary.18 static output", "scripts": { "unzip": "unzip affine-web -d static", - "start": "yarn exec serve -s static -l 8081", - "e2e": "playwright test" + "start": "yarn exec serve -s static -l 8082", + "e2e": "playwright test && vitest --run" }, "devDependencies": { "@affine-test/fixtures": "workspace:*", "@affine-test/kit": "workspace:*", + "@affine/env": "workspace:*", + "@blocksuite/block-std": "0.0.0-20230627165830-836e6fd1-nightly", + "@blocksuite/blocks": "0.0.0-20230627165830-836e6fd1-nightly", + "@blocksuite/global": "0.0.0-20230627165830-836e6fd1-nightly", + "@blocksuite/store": "0.0.0-20230627165830-836e6fd1-nightly", "@playwright/test": "=1.33.0", + "express": "^4.18.2", + "http-proxy-middleware": "^3.0.0-beta.1", "playwright": "=1.33.0", - "serve": "^14.2.0" + "serve": "^14.2.0", + "vitest": "^0.32.2" }, "version": "0.7.0-canary.23" } diff --git a/tests/affine-legacy/0.7.0-canary.18/playwright.config.ts b/tests/affine-legacy/0.7.0-canary.18/playwright.config.ts index 1aec9a1442..3178c8d316 100644 --- a/tests/affine-legacy/0.7.0-canary.18/playwright.config.ts +++ b/tests/affine-legacy/0.7.0-canary.18/playwright.config.ts @@ -4,7 +4,7 @@ import type { } from '@playwright/test'; const config: PlaywrightTestConfig = { - testDir: './tests', + testDir: './e2e', fullyParallel: true, timeout: process.env.CI ? 50_000 : 30_000, use: { @@ -24,11 +24,15 @@ const config: PlaywrightTestConfig = { retries: 1, reporter: process.env.CI ? 'github' : 'list', webServer: [ + // Intentionally not building the web, reminds you to run it by yourself. { - command: 'yarn start', - port: 8081, + command: 'yarn -T run start:web-static', + port: 8080, timeout: 120 * 1000, reuseExistingServer: !process.env.CI, + env: { + COVERAGE: process.env.COVERAGE || 'false', + }, }, ], }; diff --git a/tests/affine-legacy/0.7.0-canary.18/tests/basic.spec.ts b/tests/affine-legacy/0.7.0-canary.18/tests/basic.spec.ts index 2179a5636c..2352984210 100644 --- a/tests/affine-legacy/0.7.0-canary.18/tests/basic.spec.ts +++ b/tests/affine-legacy/0.7.0-canary.18/tests/basic.spec.ts @@ -1,24 +1,41 @@ -import { resolve } from 'node:path'; +import { readdir, readFile } from 'node:fs/promises'; +import { extname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; -import { test } from '@playwright/test'; +import { migrateToSubdoc } from '@affine/env/blocksuite'; +import { Workspace } from '@blocksuite/store'; +import { test } from 'vitest'; -test('init page', async ({ page }) => { - await page.goto('http://localhost:8081/'); - await page.waitForSelector('v-line', { - timeout: 10000, - }); +const __dirname = fileURLToPath(new URL('.', import.meta.url)); - const currentWorkspaceId: string = await page.evaluate( - () => (globalThis.currentWorkspace as any).id - ); - - const downloadPromise = page.waitForEvent('download'); - await page.evaluate(() => { - const workspace = (globalThis.currentWorkspace as any).blockSuiteWorkspace; - workspace.exportYDoc(); - }); - - const download = await downloadPromise; - const output = resolve(__dirname, 'fixtures', currentWorkspaceId + '.ydoc'); - await download.saveAs(output); +test('basic', async () => { + const oldDoc = new Workspace.Y.Doc(); + const directory = resolve(__dirname, '..', 'fixtures'); + const files = await readdir(directory); + for (const file of files) { + if (extname(file) !== '.ydoc') { + continue; + } + const filePath = resolve(directory, file); + const buffer = await readFile(filePath); + Workspace.Y.applyUpdate(oldDoc, buffer); + const newDoc = migrateToSubdoc(oldDoc); + const workspace = new Workspace({ + id: 'test', + }); + Workspace.Y.applyUpdate( + workspace.doc, + Workspace.Y.encodeStateAsUpdate(newDoc) + ); + newDoc.subdocs.forEach(subdoc => { + workspace.doc.subdocs.forEach(workspaceSubDoc => { + if (subdoc.guid === workspaceSubDoc.guid) { + Workspace.Y.applyUpdate( + workspaceSubDoc, + Workspace.Y.encodeStateAsUpdate(subdoc) + ); + } + }); + }); + } }); diff --git a/tests/affine-legacy/0.7.0-canary.18/tsconfig.json b/tests/affine-legacy/0.7.0-canary.18/tsconfig.json new file mode 100644 index 0000000000..d539ee75c4 --- /dev/null +++ b/tests/affine-legacy/0.7.0-canary.18/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "esModuleInterop": true, + "outDir": "lib" + }, + "include": ["e2e"], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/tests/affine-legacy/0.7.0-canary.18/tsconfig.node.json b/tests/affine-legacy/0.7.0-canary.18/tsconfig.node.json new file mode 100644 index 0000000000..e111452b12 --- /dev/null +++ b/tests/affine-legacy/0.7.0-canary.18/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "composite": true, + "target": "ESNext", + "module": "ESNext", + "resolveJsonModule": true, + "moduleResolution": "Node", + "allowSyntheticDefaultImports": true, + "noEmit": false, + "outDir": "lib" + }, + "include": ["tests"], + "references": [ + { + "path": "../../../packages/env" + } + ] +} diff --git a/tests/affine-legacy/0.7.0-canary.18/vitest.config.ts b/tests/affine-legacy/0.7.0-canary.18/vitest.config.ts new file mode 100644 index 0000000000..ebd854eed3 --- /dev/null +++ b/tests/affine-legacy/0.7.0-canary.18/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + include: ['./tests/**/*.spec.ts'], + }, +}); diff --git a/tsconfig.json b/tsconfig.json index bd1adf2eaa..7d3f997c3d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -153,6 +153,9 @@ }, { "path": "./tsconfig.node.json" + }, + { + "path": "./tests/affine-legacy/0.7.0-canary.18" } ], "files": [], diff --git a/yarn.lock b/yarn.lock index b930b24149..95c76f6c0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,9 +18,17 @@ __metadata: dependencies: "@affine-test/fixtures": "workspace:*" "@affine-test/kit": "workspace:*" + "@affine/env": "workspace:*" + "@blocksuite/block-std": 0.0.0-20230627165830-836e6fd1-nightly + "@blocksuite/blocks": 0.0.0-20230627165830-836e6fd1-nightly + "@blocksuite/global": 0.0.0-20230627165830-836e6fd1-nightly + "@blocksuite/store": 0.0.0-20230627165830-836e6fd1-nightly "@playwright/test": =1.33.0 + express: ^4.18.2 + http-proxy-middleware: ^3.0.0-beta.1 playwright: =1.33.0 serve: ^14.2.0 + vitest: ^0.32.2 languageName: unknown linkType: soft @@ -12009,6 +12017,15 @@ __metadata: languageName: node linkType: hard +"@types/http-proxy@npm:^1.17.10": + version: 1.17.11 + resolution: "@types/http-proxy@npm:1.17.11" + dependencies: + "@types/node": "*" + checksum: 38ef4f8c91c7a5b664cf6dd4d90de7863f88549a9f8ef997f2f1184e4f8cf2e7b9b63c04f0b7b962f34a09983073a31a9856de5aae5159b2ddbb905a4c44dc9f + languageName: node + linkType: hard + "@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.4 resolution: "@types/istanbul-lib-coverage@npm:2.0.4" @@ -18120,7 +18137,7 @@ __metadata: languageName: node linkType: hard -"eventemitter3@npm:^4.0.4": +"eventemitter3@npm:^4.0.0, eventemitter3@npm:^4.0.4": version: 4.0.7 resolution: "eventemitter3@npm:4.0.7" checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374 @@ -18872,7 +18889,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.8, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.0": +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.8, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.0": version: 1.15.2 resolution: "follow-redirects@npm:1.15.2" peerDependenciesMeta: @@ -20256,6 +20273,31 @@ __metadata: languageName: node linkType: hard +"http-proxy-middleware@npm:^3.0.0-beta.1": + version: 3.0.0-beta.1 + resolution: "http-proxy-middleware@npm:3.0.0-beta.1" + dependencies: + "@types/http-proxy": ^1.17.10 + debug: ^4.3.4 + http-proxy: ^1.18.1 + is-glob: ^4.0.1 + is-plain-obj: ^3.0.0 + micromatch: ^4.0.5 + checksum: 683fe0cc27f5f499e9d07311294e3aca1f4f5ec7476fa64fba50bde260ef8d6199d12584b37ef7d4f398727f0763503a13ae47f07519a73fc84b07b85f9e451d + languageName: node + linkType: hard + +"http-proxy@npm:^1.18.1": + version: 1.18.1 + resolution: "http-proxy@npm:1.18.1" + dependencies: + eventemitter3: ^4.0.0 + follow-redirects: ^1.0.0 + requires-port: ^1.0.0 + checksum: f5bd96bf83e0b1e4226633dbb51f8b056c3e6321917df402deacec31dd7fe433914fc7a2c1831cf7ae21e69c90b3a669b8f434723e9e8b71fd68afe30737b6a5 + languageName: node + linkType: hard + "http2-wrapper@npm:^1.0.0-beta.5.2": version: 1.0.3 resolution: "http2-wrapper@npm:1.0.3" @@ -20977,6 +21019,13 @@ __metadata: languageName: node linkType: hard +"is-plain-obj@npm:^3.0.0": + version: 3.0.0 + resolution: "is-plain-obj@npm:3.0.0" + checksum: a6ebdf8e12ab73f33530641972a72a4b8aed6df04f762070d823808303e4f76d87d5ea5bd76f96a7bbe83d93f04ac7764429c29413bd9049853a69cb630fb21c + languageName: node + linkType: hard + "is-plain-object@npm:5.0.0, is-plain-object@npm:^5.0.0": version: 5.0.0 resolution: "is-plain-object@npm:5.0.0" @@ -27484,6 +27533,13 @@ __metadata: languageName: node linkType: hard +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: eee0e303adffb69be55d1a214e415cf42b7441ae858c76dfc5353148644f6fd6e698926fc4643f510d5c126d12a705e7c8ed7e38061113bdf37547ab356797ff + languageName: node + linkType: hard + "resolve-alpn@npm:^1.0.0": version: 1.2.1 resolution: "resolve-alpn@npm:1.2.1"