mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 20:08:37 +00:00
test: improve coverage on affine api (#1727)
This commit is contained in:
6
.github/actions/setup-node/action.yml
vendored
6
.github/actions/setup-node/action.yml
vendored
@@ -52,6 +52,12 @@ runs:
|
|||||||
restore-keys: |
|
restore-keys: |
|
||||||
yarn-download-cache-
|
yarn-download-cache-
|
||||||
|
|
||||||
|
- name: Restore node_modules cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: '**/node_modules'
|
||||||
|
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
|
||||||
- name: Restore yarn install state
|
- name: Restore yarn install state
|
||||||
id: yarn-install-state-cache
|
id: yarn-install-state-cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
|
|||||||
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -96,7 +96,6 @@ jobs:
|
|||||||
name: Unit Test
|
name: Unit Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
environment: development
|
environment: development
|
||||||
needs: [build]
|
|
||||||
services:
|
services:
|
||||||
octobase:
|
octobase:
|
||||||
image: ghcr.io/toeverything/cloud-self-hosted:nightly-latest
|
image: ghcr.io/toeverything/cloud-self-hosted:nightly-latest
|
||||||
@@ -111,11 +110,6 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
- name: Download artifact
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: artifact
|
|
||||||
path: ./apps/web/.next
|
|
||||||
|
|
||||||
- name: Unit Test
|
- name: Unit Test
|
||||||
run: yarn run test:unit:coverage
|
run: yarn run test:unit:coverage
|
||||||
|
|||||||
@@ -80,7 +80,11 @@ export const AffinePlugin: WorkspacePlugin<WorkspaceFlavour.AFFINE> = {
|
|||||||
const url = await blobs.get(id);
|
const url = await blobs.get(id);
|
||||||
if (url) {
|
if (url) {
|
||||||
const blob = await fetch(url).then(res => res.blob());
|
const blob = await fetch(url).then(res => res.blob());
|
||||||
await affineApis.uploadBlob(newWorkspaceId, blob);
|
await affineApis.uploadBlob(
|
||||||
|
newWorkspaceId,
|
||||||
|
await blob.arrayBuffer(),
|
||||||
|
blob.type
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@affine/cli": "workspace:*",
|
"@affine/cli": "workspace:*",
|
||||||
|
"@faker-js/faker": "^7.6.0",
|
||||||
"@istanbuljs/schema": "^0.1.3",
|
"@istanbuljs/schema": "^0.1.3",
|
||||||
"@perfsee/sdk": "^1.5.1",
|
"@perfsee/sdk": "^1.5.1",
|
||||||
"@playwright/test": "^1.32.1",
|
"@playwright/test": "^1.32.1",
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
*/
|
*/
|
||||||
import 'fake-indexeddb/auto';
|
import 'fake-indexeddb/auto';
|
||||||
|
|
||||||
|
import { readFile } from 'node:fs/promises';
|
||||||
|
|
||||||
import { MessageCode } from '@affine/env/constant';
|
import { MessageCode } from '@affine/env/constant';
|
||||||
import userA from '@affine-test/fixtures/userA.json';
|
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import { Workspace } from '@blocksuite/store';
|
import { Workspace } from '@blocksuite/store';
|
||||||
|
import { faker } from '@faker-js/faker';
|
||||||
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -24,40 +26,36 @@ import {
|
|||||||
let workspaceApis: ReturnType<typeof createWorkspaceApis>;
|
let workspaceApis: ReturnType<typeof createWorkspaceApis>;
|
||||||
let affineAuth: ReturnType<typeof createAffineAuth>;
|
let affineAuth: ReturnType<typeof createAffineAuth>;
|
||||||
|
|
||||||
|
const mockUser = {
|
||||||
|
name: faker.name.fullName(),
|
||||||
|
email: faker.internet.email(),
|
||||||
|
password: faker.internet.password(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// create a new user for each test, so that each test can be run independently
|
||||||
|
mockUser.name = faker.name.fullName();
|
||||||
|
mockUser.email = faker.internet.email();
|
||||||
|
mockUser.password = faker.internet.password();
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
affineAuth = createAffineAuth('http://localhost:3000/');
|
affineAuth = createAffineAuth('http://localhost:3000/');
|
||||||
workspaceApis = createWorkspaceApis('http://localhost:3000/');
|
workspaceApis = createWorkspaceApis('http://localhost:3000/');
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
let data;
|
const data = await fetch('http://localhost:3000/api/user/token', {
|
||||||
// first step: try to log in
|
|
||||||
const response = await fetch('http://localhost:3000/api/user/token', {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
type: 'DebugLoginUser',
|
type: 'DebugCreateUser',
|
||||||
email: userA.email,
|
...mockUser,
|
||||||
password: userA.password,
|
|
||||||
}),
|
}),
|
||||||
});
|
}).then(r => r.json());
|
||||||
if (!response.ok) {
|
setLoginStorage(data);
|
||||||
data = await fetch('http://localhost:3000/api/user/token', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
type: 'DebugCreateUser',
|
|
||||||
...userA,
|
|
||||||
}),
|
|
||||||
}).then(r => r.json());
|
|
||||||
setLoginStorage(data);
|
|
||||||
} else {
|
|
||||||
setLoginStorage((data = await response.json()));
|
|
||||||
}
|
|
||||||
loginResponseSchema.parse(data);
|
loginResponseSchema.parse(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -69,6 +67,18 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function createWorkspace(
|
||||||
|
workspaceApi: typeof workspaceApis
|
||||||
|
): Promise<string> {
|
||||||
|
const workspace = new Workspace({
|
||||||
|
id: faker.datatype.uuid(),
|
||||||
|
});
|
||||||
|
const binary = Workspace.Y.encodeStateAsUpdate(workspace.doc);
|
||||||
|
const data = await workspaceApi.createWorkspace(new Blob([binary]));
|
||||||
|
createWorkspaceResponseSchema.parse(data);
|
||||||
|
return data.id;
|
||||||
|
}
|
||||||
|
|
||||||
describe('api', () => {
|
describe('api', () => {
|
||||||
test('failed', async () => {
|
test('failed', async () => {
|
||||||
workspaceApis = createWorkspaceApis('http://localhost:10086/404/');
|
workspaceApis = createWorkspaceApis('http://localhost:10086/404/');
|
||||||
@@ -100,12 +110,8 @@ describe('api', () => {
|
|||||||
test(
|
test(
|
||||||
'create workspace',
|
'create workspace',
|
||||||
async () => {
|
async () => {
|
||||||
const workspace = new Workspace({
|
const id = await createWorkspace(workspaceApis);
|
||||||
id: 'test',
|
expect(id).toBeTypeOf('string');
|
||||||
});
|
|
||||||
const binary = Workspace.Y.encodeStateAsUpdate(workspace.doc);
|
|
||||||
const data = await workspaceApis.createWorkspace(new Blob([binary]));
|
|
||||||
createWorkspaceResponseSchema.parse(data);
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
@@ -115,13 +121,7 @@ describe('api', () => {
|
|||||||
test(
|
test(
|
||||||
'delete workspace',
|
'delete workspace',
|
||||||
async () => {
|
async () => {
|
||||||
const workspace = new Workspace({
|
const id = await createWorkspace(workspaceApis);
|
||||||
id: 'test',
|
|
||||||
});
|
|
||||||
const binary = Workspace.Y.encodeStateAsUpdate(workspace.doc);
|
|
||||||
const data = await workspaceApis.createWorkspace(new Blob([binary]));
|
|
||||||
createWorkspaceResponseSchema.parse(data);
|
|
||||||
const id = data.id;
|
|
||||||
const response = await workspaceApis.deleteWorkspace({
|
const response = await workspaceApis.deleteWorkspace({
|
||||||
id,
|
id,
|
||||||
});
|
});
|
||||||
@@ -131,4 +131,58 @@ describe('api', () => {
|
|||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test('get workspaces', async () => {
|
||||||
|
const id = await createWorkspace(workspaceApis);
|
||||||
|
const response = await workspaceApis.getWorkspaces();
|
||||||
|
expect(response).toBeInstanceOf(Array);
|
||||||
|
expect(response.length).toBe(1);
|
||||||
|
expect(response[0].id).toBe(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'blob',
|
||||||
|
async () => {
|
||||||
|
const workspace = new Workspace({
|
||||||
|
id: 'test',
|
||||||
|
});
|
||||||
|
const path = require.resolve('@affine-test/fixtures/smile.png');
|
||||||
|
const imageBuffer = await readFile(path);
|
||||||
|
const binary = Workspace.Y.encodeStateAsUpdate(workspace.doc);
|
||||||
|
const data = await workspaceApis.createWorkspace(new Blob([binary]));
|
||||||
|
createWorkspaceResponseSchema.parse(data);
|
||||||
|
const blobId = await workspaceApis.uploadBlob(
|
||||||
|
data.id,
|
||||||
|
imageBuffer,
|
||||||
|
'image/png'
|
||||||
|
);
|
||||||
|
expect(blobId).toBeTypeOf('string');
|
||||||
|
const arrayBuffer = await workspaceApis.getBlob(blobId);
|
||||||
|
expect(arrayBuffer).toBeInstanceOf(ArrayBuffer);
|
||||||
|
expect(arrayBuffer.byteLength).toEqual(imageBuffer.byteLength);
|
||||||
|
expect(Buffer.from(arrayBuffer)).toEqual(imageBuffer);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timeout: 30000,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'workspace binary',
|
||||||
|
async () => {
|
||||||
|
const id = await createWorkspace(workspaceApis);
|
||||||
|
await workspaceApis.updateWorkspace({
|
||||||
|
id,
|
||||||
|
public: true,
|
||||||
|
});
|
||||||
|
const binary = await workspaceApis.downloadWorkspace(id, false);
|
||||||
|
const publicBinary = await workspaceApis.downloadWorkspace(id, true);
|
||||||
|
expect(binary).toBeInstanceOf(ArrayBuffer);
|
||||||
|
expect(publicBinary).toBeInstanceOf(ArrayBuffer);
|
||||||
|
expect(binary.byteLength).toEqual(publicBinary.byteLength);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timeout: 30000,
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -295,22 +295,26 @@ export function createWorkspaceApis(prefixUrl = '/') {
|
|||||||
throw new RequestError(MessageCode.acceptInvitingFailed, e);
|
throw new RequestError(MessageCode.acceptInvitingFailed, e);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
uploadBlob: async (workspaceId: string, blob: Blob): Promise<string> => {
|
uploadBlob: async (
|
||||||
|
workspaceId: string,
|
||||||
|
arrayBuffer: ArrayBuffer,
|
||||||
|
type: string
|
||||||
|
): Promise<string> => {
|
||||||
const auth = getLoginStorage();
|
const auth = getLoginStorage();
|
||||||
assertExists(auth);
|
assertExists(auth);
|
||||||
return fetch(prefixUrl + 'api/blob', {
|
return fetch(prefixUrl + 'api/blob', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: blob,
|
body: arrayBuffer,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': blob.type,
|
'Content-Type': type,
|
||||||
Authorization: auth.token,
|
Authorization: auth.token,
|
||||||
},
|
},
|
||||||
}).then(r => r.text());
|
}).then(r => r.text());
|
||||||
},
|
},
|
||||||
getBlob: async (params: { blobId: string }): Promise<ArrayBuffer> => {
|
getBlob: async (blobId: string): Promise<ArrayBuffer> => {
|
||||||
const auth = getLoginStorage();
|
const auth = getLoginStorage();
|
||||||
assertExists(auth);
|
assertExists(auth);
|
||||||
return fetch(prefixUrl + `api/blob/${params.blobId}`, {
|
return fetch(prefixUrl + `api/blob/${blobId}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: auth.token,
|
Authorization: auth.token,
|
||||||
|
|||||||
@@ -2432,6 +2432,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@faker-js/faker@npm:^7.6.0":
|
||||||
|
version: 7.6.0
|
||||||
|
resolution: "@faker-js/faker@npm:7.6.0"
|
||||||
|
checksum: 942af6221774e8c98a0eb6bc75265e05fb81a941170377666c3439aab9495dd321d6beedc5406f07e6ad44262b3e43c20961f666d116ad150b78e7437dd1bb2b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@fal-works/esbuild-plugin-global-externals@npm:^2.1.2":
|
"@fal-works/esbuild-plugin-global-externals@npm:^2.1.2":
|
||||||
version: 2.1.2
|
version: 2.1.2
|
||||||
resolution: "@fal-works/esbuild-plugin-global-externals@npm:2.1.2"
|
resolution: "@fal-works/esbuild-plugin-global-externals@npm:2.1.2"
|
||||||
@@ -7328,6 +7335,7 @@ __metadata:
|
|||||||
resolution: "AFFiNE@workspace:."
|
resolution: "AFFiNE@workspace:."
|
||||||
dependencies:
|
dependencies:
|
||||||
"@affine/cli": "workspace:*"
|
"@affine/cli": "workspace:*"
|
||||||
|
"@faker-js/faker": ^7.6.0
|
||||||
"@istanbuljs/schema": ^0.1.3
|
"@istanbuljs/schema": ^0.1.3
|
||||||
"@perfsee/sdk": ^1.5.1
|
"@perfsee/sdk": ^1.5.1
|
||||||
"@playwright/test": ^1.32.1
|
"@playwright/test": ^1.32.1
|
||||||
|
|||||||
Reference in New Issue
Block a user