test: add test case for affine

This commit is contained in:
alt0 2023-01-09 18:53:15 +08:00
parent 5095e2f27d
commit 9316bb4222
6 changed files with 112 additions and 35 deletions

View File

@ -0,0 +1,53 @@
import { test, expect } from '@playwright/test';
import { AffineProvider } from '../affine.js';
import { Workspaces } from '../../../workspaces/index.js';
import { apis } from './mock-apis.js';
import 'fake-indexeddb/auto';
test.describe.serial('affine provider', async () => {
const workspaces = new Workspaces();
const provider = new AffineProvider({
workspaces: workspaces.createScope(),
apis,
});
await provider.auth();
const workspaceName = 'workspace-test';
let workspaceId: string | undefined;
test('create workspace', async () => {
const w = await provider.createWorkspace({
name: workspaceName,
avatar: 'avatar-url-test',
});
workspaceId = w?.room;
expect(workspaces.workspaces.length).toEqual(1);
expect(workspaces.workspaces[0].name).toEqual(workspaceName);
});
// test('workspace list cache', async () => {
// const workspaces1 = new Workspaces();
// const provider1 = new AffineProvider({
// workspaces: workspaces1.createScope(),
// });
// await provider1.loadWorkspaces();
// expect(workspaces1.workspaces.length).toEqual(1);
// expect(workspaces1.workspaces[0].name).toEqual(workspaceName);
// expect(workspaces1.workspaces[0].id).toEqual(workspaceId);
// });
// test('update workspace', async () => {
// await provider.updateWorkspaceMeta(workspaceId!, {
// name: '1111',
// });
// expect(workspaces.workspaces[0].name).toEqual('1111');
// });
// test('delete workspace', async () => {
// expect(workspaces.workspaces.length).toEqual(1);
// await provider.deleteWorkspace(workspaces.workspaces[0].id);
// expect(workspaces.workspaces.length).toEqual(0);
// });
});

View File

@ -0,0 +1,19 @@
import type { Apis, AccessTokenMessage } from '../apis';
const user: AccessTokenMessage = {
create_at: Date.now(),
exp: 100000000,
email: 'demo@demo.demo',
id: '123',
name: 'demo',
avatar_url: 'demo-avatar-url',
};
export const apis = {
signInWithGoogle: () => {
return Promise.resolve(user);
},
createWorkspace: mate => {
return Promise.resolve({ id: 'test' });
},
} as Apis;

View File

@ -1,18 +1,16 @@
import { BaseProvider } from '../base';
import { BaseProvider } from '../base.js';
import type { ProviderConstructorParams } from '../base';
import { User, Workspace as WS, WorkspaceMeta } from '../../types';
import type { User, Workspace as WS, WorkspaceMeta } from '../../types';
import { Workspace } from '@blocksuite/store';
import { BlockSchema } from '@blocksuite/blocks/models';
import { applyUpdate } from 'yjs';
import { token, Callback } from './apis';
import { varStorage as storage } from 'lib0/storage';
import { storage } from './storage.js';
import assert from 'assert';
import { getAuthorizer } from './apis/token';
import { WebsocketProvider } from './sync';
import { WebsocketProvider } from './sync.js';
// import { IndexedDBProvider } from '../local/indexeddb';
import { getDefaultHeadImgBlob } from '../../utils';
import { getDefaultHeadImgBlob } from '../../utils/index.js';
import { getApis } from './apis/index.js';
import type { Apis, WorkspaceDetail } from './apis';
import type { Apis, WorkspaceDetail, Callback } from './apis';
export interface AffineProviderConstructorParams
extends ProviderConstructorParams {
@ -23,8 +21,6 @@ export class AffineProvider extends BaseProvider {
public id = 'affine';
private _workspacesCache: Map<string, Workspace> = new Map();
private _onTokenRefresh?: Callback = undefined;
private readonly _authorizer = getAuthorizer();
private _user: User | undefined = undefined;
private _wsMap: Map<string, WebsocketProvider> = new Map();
private _apis: Apis;
// private _idbMap: Map<string, IndexedDBProvider> = new Map();
@ -36,29 +32,29 @@ export class AffineProvider extends BaseProvider {
override async init() {
this._onTokenRefresh = () => {
if (token.refresh) {
storage.setItem('token', token.refresh);
if (this._apis.token.refresh) {
storage.setItem('token', this._apis.token.refresh);
}
};
token.onChange(this._onTokenRefresh);
this._apis.token.onChange(this._onTokenRefresh);
// initial login token
if (token.isExpired) {
if (this._apis.token.isExpired) {
try {
const refreshToken = storage.getItem('token');
await token.refreshToken(refreshToken);
await this._apis.token.refreshToken(refreshToken);
if (token.refresh) {
storage.set('token', token.refresh);
if (this._apis.token.refresh) {
storage.set('token', this._apis.token.refresh);
}
assert(token.isLogin);
assert(this._apis.token.isLogin);
} catch (_) {
// this._logger('Authorization failed, fallback to local mode');
}
} else {
storage.setItem('token', token.refresh);
storage.setItem('token', this._apis.token.refresh);
}
}
@ -91,7 +87,7 @@ export class AffineProvider extends BaseProvider {
}
override async loadWorkspaces() {
if (!token.isLogin) {
if (!this._apis.token.isLogin) {
return [];
}
const workspacesList = await this._apis.getWorkspaces();
@ -171,24 +167,26 @@ export class AffineProvider extends BaseProvider {
override async auth() {
const refreshToken = await storage.getItem('token');
if (refreshToken) {
await token.refreshToken(refreshToken);
if (token.isLogin && !token.isExpired) {
await this._apis.token.refreshToken(refreshToken);
if (this._apis.token.isLogin && !this._apis.token.isExpired) {
// login success
return;
}
}
const user = await this._authorizer[0]?.();
const user = await this._apis.signInWithGoogle?.();
assert(user);
this._user = {
id: user.id,
name: user.name,
avatar: user.avatar_url,
email: user.email,
};
}
public override async getUserInfo(): Promise<User | undefined> {
return this._user;
const user = this._apis.token.user;
return user
? {
id: user.id,
name: user.name,
avatar: user.avatar_url,
email: user.email,
}
: undefined;
}
public override async deleteWorkspace(id: string): Promise<void> {
@ -265,7 +263,7 @@ export class AffineProvider extends BaseProvider {
owner: undefined,
isLocal: true,
memberCount: 1,
provider: 'local',
provider: 'affine',
};
if (!meta.avatar) {

View File

@ -1,15 +1,16 @@
export { token } from './token.js';
// export { token } from './token.js';
export type { Callback } from './token.js';
import { getAuthorizer } from './token.js';
import * as user from './user.js';
import * as workspace from './workspace.js';
import { token } from './token.js';
export type Apis = typeof user &
typeof workspace & {
signInWithGoogle: ReturnType<typeof getAuthorizer>[0];
onAuthStateChanged: ReturnType<typeof getAuthorizer>[1];
};
} & { token: typeof token };
export const getApis = (): Apis => {
const [signInWithGoogle, onAuthStateChanged] = getAuthorizer();
@ -18,6 +19,7 @@ export const getApis = (): Apis => {
...workspace,
signInWithGoogle,
onAuthStateChanged,
token,
};
};

View File

@ -2,8 +2,8 @@ import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
import type { User } from 'firebase/auth';
import { getLogger } from '../../../logger';
import { bareClient } from './request';
import { getLogger } from '../../../logger.js';
import { bareClient } from './request.js';
export interface AccessTokenMessage {
create_at: number;
@ -46,6 +46,10 @@ class Token {
this._setToken(); // fill with default value
}
get user() {
return this._user;
}
private _setToken(login?: LoginResponse) {
this._accessToken = login?.token || '';
this._refreshToken = login?.refresh || '';

View File

@ -0,0 +1 @@
export { varStorage as storage } from 'lib0/storage';