feat(workspace): handle error on apis (#1700)

This commit is contained in:
Himself65 2023-03-27 15:25:30 -05:00 committed by GitHub
parent 628ce08d8d
commit 021bf6534b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 117 additions and 15 deletions

View File

@ -3,12 +3,17 @@
*/ */
import 'fake-indexeddb/auto'; import 'fake-indexeddb/auto';
import { MessageCode } from '@affine/datacenter';
import userA from '@affine-test/fixtures/userA.json'; 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 { beforeAll, beforeEach, describe, expect, test } from 'vitest'; import { beforeEach, describe, expect, test, vi } from 'vitest';
import { createWorkspaceApis, createWorkspaceResponseSchema } from '../api'; import {
createWorkspaceApis,
createWorkspaceResponseSchema,
RequestError,
} from '../api';
import { import {
createAffineAuth, createAffineAuth,
getLoginStorage, getLoginStorage,
@ -19,7 +24,7 @@ import {
let workspaceApis: ReturnType<typeof createWorkspaceApis>; let workspaceApis: ReturnType<typeof createWorkspaceApis>;
let affineAuth: ReturnType<typeof createAffineAuth>; let affineAuth: ReturnType<typeof createAffineAuth>;
beforeAll(() => { beforeEach(() => {
affineAuth = createAffineAuth('http://localhost:3000/'); affineAuth = createAffineAuth('http://localhost:3000/');
workspaceApis = createWorkspaceApis('http://localhost:3000/'); workspaceApis = createWorkspaceApis('http://localhost:3000/');
}); });
@ -56,7 +61,36 @@ beforeEach(async () => {
loginResponseSchema.parse(data); loginResponseSchema.parse(data);
}); });
declare global {
interface DocumentEventMap {
'affine-error': CustomEvent<{
code: MessageCode;
}>;
}
}
describe('api', () => { describe('api', () => {
test('failed', async () => {
workspaceApis = createWorkspaceApis('http://localhost:10086/404/');
const listener = vi.fn(
(
e: CustomEvent<{
code: MessageCode;
}>
) => {
expect(e.detail.code).toBe(MessageCode.loadListFailed);
}
);
document.addEventListener('affine-error', listener);
expect(listener).toBeCalledTimes(0);
await workspaceApis.getWorkspaces().catch(e => {
expect(e).toBeInstanceOf(RequestError);
});
expect(listener).toBeCalledTimes(1);
document.removeEventListener('affine-error', listener);
});
test('refresh token', async () => { test('refresh token', async () => {
const storage = getLoginStorage(); const storage = getLoginStorage();
assertExists(storage); assertExists(storage);

View File

@ -1,8 +1,28 @@
import { MessageCode, Messages } from '@affine/env';
import { assertExists } from '@blocksuite/global/utils'; import { assertExists } from '@blocksuite/global/utils';
import { z } from 'zod'; import { z } from 'zod';
import { getLoginStorage } from '../login'; import { getLoginStorage } from '../login';
export class RequestError extends Error {
constructor(code: MessageCode, cause: unknown | null = null) {
super(Messages[code].message);
sendMessage(code);
this.name = 'RequestError';
this.cause = cause;
}
}
function sendMessage(code: MessageCode) {
document.dispatchEvent(
new CustomEvent('affine-error', {
detail: {
code,
},
})
);
}
export interface User { export interface User {
id: string; id: string;
name: string; name: string;
@ -139,7 +159,11 @@ export function createWorkspaceApis(prefixUrl = '/') {
Authorization: auth.token, Authorization: auth.token,
'Cache-Control': 'no-cache', 'Cache-Control': 'no-cache',
}, },
}).then(r => r.json()); })
.then(r => r.json())
.catch(e => {
throw new RequestError(MessageCode.loadListFailed, e);
});
}, },
getWorkspaceDetail: async ( getWorkspaceDetail: async (
params: GetWorkspaceDetailParams params: GetWorkspaceDetailParams
@ -151,7 +175,11 @@ export function createWorkspaceApis(prefixUrl = '/') {
headers: { headers: {
Authorization: auth.token, Authorization: auth.token,
}, },
}).then(r => r.json()); })
.then(r => r.json())
.catch(e => {
throw new RequestError(MessageCode.loadListFailed, e);
});
}, },
getWorkspaceMembers: async ( getWorkspaceMembers: async (
params: GetWorkspaceDetailParams params: GetWorkspaceDetailParams
@ -163,7 +191,11 @@ export function createWorkspaceApis(prefixUrl = '/') {
headers: { headers: {
Authorization: auth.token, Authorization: auth.token,
}, },
}).then(r => r.json()); })
.then(r => r.json())
.catch(e => {
throw new RequestError(MessageCode.getMembersFailed, e);
});
}, },
createWorkspace: async (encodedYDoc: Blob): Promise<{ id: string }> => { createWorkspace: async (encodedYDoc: Blob): Promise<{ id: string }> => {
const auth = getLoginStorage(); const auth = getLoginStorage();
@ -174,7 +206,11 @@ export function createWorkspaceApis(prefixUrl = '/') {
headers: { headers: {
Authorization: auth.token, Authorization: auth.token,
}, },
}).then(r => r.json()); })
.then(r => r.json())
.catch(e => {
throw new RequestError(MessageCode.createWorkspaceFailed, e);
});
}, },
updateWorkspace: async ( updateWorkspace: async (
params: UpdateWorkspaceParams params: UpdateWorkspaceParams
@ -190,7 +226,11 @@ export function createWorkspaceApis(prefixUrl = '/') {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Authorization: auth.token, Authorization: auth.token,
}, },
}).then(r => r.json()); })
.then(r => r.json())
.catch(e => {
throw new RequestError(MessageCode.updateWorkspaceFailed, e);
});
}, },
deleteWorkspace: async ( deleteWorkspace: async (
params: DeleteWorkspaceParams params: DeleteWorkspaceParams
@ -202,7 +242,11 @@ export function createWorkspaceApis(prefixUrl = '/') {
headers: { headers: {
Authorization: auth.token, Authorization: auth.token,
}, },
}).then(r => r.ok); })
.then(r => r.ok)
.catch(e => {
throw new RequestError(MessageCode.deleteWorkspaceFailed, e);
});
}, },
/** /**
@ -220,7 +264,11 @@ export function createWorkspaceApis(prefixUrl = '/') {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Authorization: auth.token, Authorization: auth.token,
}, },
}).then(r => r.json()); })
.then(r => r.json())
.catch(e => {
throw new RequestError(MessageCode.inviteMemberFailed, e);
});
}, },
removeMember: async (params: RemoveMemberParams): Promise<void> => { removeMember: async (params: RemoveMemberParams): Promise<void> => {
const auth = getLoginStorage(); const auth = getLoginStorage();
@ -230,14 +278,22 @@ export function createWorkspaceApis(prefixUrl = '/') {
headers: { headers: {
Authorization: auth.token, Authorization: auth.token,
}, },
}).then(r => r.json()); })
.then(r => r.json())
.catch(e => {
throw new RequestError(MessageCode.removeMemberFailed, e);
});
}, },
acceptInviting: async ( acceptInviting: async (
params: AcceptInvitingParams params: AcceptInvitingParams
): Promise<Permission> => { ): Promise<Permission> => {
return fetch(prefixUrl + `api/invitation/${params.invitingCode}`, { return fetch(prefixUrl + `api/invitation/${params.invitingCode}`, {
method: 'POST', method: 'POST',
}).then(r => r.json()); })
.then(r => r.json())
.catch(e => {
throw new RequestError(MessageCode.acceptInvitingFailed, e);
});
}, },
uploadBlob: async (params: { blob: Blob }): Promise<string> => { uploadBlob: async (params: { blob: Blob }): Promise<string> => {
const auth = getLoginStorage(); const auth = getLoginStorage();
@ -258,7 +314,11 @@ export function createWorkspaceApis(prefixUrl = '/') {
headers: { headers: {
Authorization: auth.token, Authorization: auth.token,
}, },
}).then(r => r.arrayBuffer()); })
.then(r => r.arrayBuffer())
.catch(e => {
throw new RequestError(MessageCode.getBlobFailed, e);
});
}, },
leaveWorkspace: async ({ id }: LeaveWorkspaceParams) => { leaveWorkspace: async ({ id }: LeaveWorkspaceParams) => {
const auth = getLoginStorage(); const auth = getLoginStorage();
@ -268,7 +328,11 @@ export function createWorkspaceApis(prefixUrl = '/') {
headers: { headers: {
Authorization: auth.token, Authorization: auth.token,
}, },
}).then(r => r.json()); })
.then(r => r.json())
.catch(e => {
throw new RequestError(MessageCode.leaveWorkspaceFailed, e);
});
}, },
downloadWorkspace: async ( downloadWorkspace: async (
workspaceId: string, workspaceId: string,
@ -286,7 +350,11 @@ export function createWorkspaceApis(prefixUrl = '/') {
headers: { headers: {
Authorization: auth.token, Authorization: auth.token,
}, },
}).then(r => r.arrayBuffer()); })
.then(r => r.arrayBuffer())
.catch(e => {
throw new RequestError(MessageCode.downloadWorkspaceFailed, e);
});
} }
}, },
} as const; } as const;