test: add test case for affine
This commit is contained in:
@@ -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);
|
||||||
|
// });
|
||||||
|
});
|
||||||
@@ -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;
|
||||||
@@ -1,18 +1,16 @@
|
|||||||
import { BaseProvider } from '../base';
|
import { BaseProvider } from '../base.js';
|
||||||
import type { ProviderConstructorParams } from '../base';
|
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 { Workspace } from '@blocksuite/store';
|
||||||
import { BlockSchema } from '@blocksuite/blocks/models';
|
import { BlockSchema } from '@blocksuite/blocks/models';
|
||||||
import { applyUpdate } from 'yjs';
|
import { applyUpdate } from 'yjs';
|
||||||
import { token, Callback } from './apis';
|
import { storage } from './storage.js';
|
||||||
import { varStorage as storage } from 'lib0/storage';
|
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import { getAuthorizer } from './apis/token';
|
import { WebsocketProvider } from './sync.js';
|
||||||
import { WebsocketProvider } from './sync';
|
|
||||||
// import { IndexedDBProvider } from '../local/indexeddb';
|
// import { IndexedDBProvider } from '../local/indexeddb';
|
||||||
import { getDefaultHeadImgBlob } from '../../utils';
|
import { getDefaultHeadImgBlob } from '../../utils/index.js';
|
||||||
import { getApis } from './apis/index.js';
|
import { getApis } from './apis/index.js';
|
||||||
import type { Apis, WorkspaceDetail } from './apis';
|
import type { Apis, WorkspaceDetail, Callback } from './apis';
|
||||||
|
|
||||||
export interface AffineProviderConstructorParams
|
export interface AffineProviderConstructorParams
|
||||||
extends ProviderConstructorParams {
|
extends ProviderConstructorParams {
|
||||||
@@ -23,8 +21,6 @@ export class AffineProvider extends BaseProvider {
|
|||||||
public id = 'affine';
|
public id = 'affine';
|
||||||
private _workspacesCache: Map<string, Workspace> = new Map();
|
private _workspacesCache: Map<string, Workspace> = new Map();
|
||||||
private _onTokenRefresh?: Callback = undefined;
|
private _onTokenRefresh?: Callback = undefined;
|
||||||
private readonly _authorizer = getAuthorizer();
|
|
||||||
private _user: User | undefined = undefined;
|
|
||||||
private _wsMap: Map<string, WebsocketProvider> = new Map();
|
private _wsMap: Map<string, WebsocketProvider> = new Map();
|
||||||
private _apis: Apis;
|
private _apis: Apis;
|
||||||
// private _idbMap: Map<string, IndexedDBProvider> = new Map();
|
// private _idbMap: Map<string, IndexedDBProvider> = new Map();
|
||||||
@@ -36,29 +32,29 @@ export class AffineProvider extends BaseProvider {
|
|||||||
|
|
||||||
override async init() {
|
override async init() {
|
||||||
this._onTokenRefresh = () => {
|
this._onTokenRefresh = () => {
|
||||||
if (token.refresh) {
|
if (this._apis.token.refresh) {
|
||||||
storage.setItem('token', token.refresh);
|
storage.setItem('token', this._apis.token.refresh);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
token.onChange(this._onTokenRefresh);
|
this._apis.token.onChange(this._onTokenRefresh);
|
||||||
|
|
||||||
// initial login token
|
// initial login token
|
||||||
if (token.isExpired) {
|
if (this._apis.token.isExpired) {
|
||||||
try {
|
try {
|
||||||
const refreshToken = storage.getItem('token');
|
const refreshToken = storage.getItem('token');
|
||||||
await token.refreshToken(refreshToken);
|
await this._apis.token.refreshToken(refreshToken);
|
||||||
|
|
||||||
if (token.refresh) {
|
if (this._apis.token.refresh) {
|
||||||
storage.set('token', token.refresh);
|
storage.set('token', this._apis.token.refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(token.isLogin);
|
assert(this._apis.token.isLogin);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// this._logger('Authorization failed, fallback to local mode');
|
// this._logger('Authorization failed, fallback to local mode');
|
||||||
}
|
}
|
||||||
} else {
|
} 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() {
|
override async loadWorkspaces() {
|
||||||
if (!token.isLogin) {
|
if (!this._apis.token.isLogin) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const workspacesList = await this._apis.getWorkspaces();
|
const workspacesList = await this._apis.getWorkspaces();
|
||||||
@@ -171,24 +167,26 @@ export class AffineProvider extends BaseProvider {
|
|||||||
override async auth() {
|
override async auth() {
|
||||||
const refreshToken = await storage.getItem('token');
|
const refreshToken = await storage.getItem('token');
|
||||||
if (refreshToken) {
|
if (refreshToken) {
|
||||||
await token.refreshToken(refreshToken);
|
await this._apis.token.refreshToken(refreshToken);
|
||||||
if (token.isLogin && !token.isExpired) {
|
if (this._apis.token.isLogin && !this._apis.token.isExpired) {
|
||||||
// login success
|
// login success
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const user = await this._authorizer[0]?.();
|
const user = await this._apis.signInWithGoogle?.();
|
||||||
assert(user);
|
assert(user);
|
||||||
this._user = {
|
|
||||||
id: user.id,
|
|
||||||
name: user.name,
|
|
||||||
avatar: user.avatar_url,
|
|
||||||
email: user.email,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async getUserInfo(): Promise<User | undefined> {
|
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> {
|
public override async deleteWorkspace(id: string): Promise<void> {
|
||||||
@@ -265,7 +263,7 @@ export class AffineProvider extends BaseProvider {
|
|||||||
owner: undefined,
|
owner: undefined,
|
||||||
isLocal: true,
|
isLocal: true,
|
||||||
memberCount: 1,
|
memberCount: 1,
|
||||||
provider: 'local',
|
provider: 'affine',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!meta.avatar) {
|
if (!meta.avatar) {
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
export { token } from './token.js';
|
// export { token } from './token.js';
|
||||||
export type { Callback } from './token.js';
|
export type { Callback } from './token.js';
|
||||||
|
|
||||||
import { getAuthorizer } from './token.js';
|
import { getAuthorizer } from './token.js';
|
||||||
import * as user from './user.js';
|
import * as user from './user.js';
|
||||||
import * as workspace from './workspace.js';
|
import * as workspace from './workspace.js';
|
||||||
|
import { token } from './token.js';
|
||||||
|
|
||||||
export type Apis = typeof user &
|
export type Apis = typeof user &
|
||||||
typeof workspace & {
|
typeof workspace & {
|
||||||
signInWithGoogle: ReturnType<typeof getAuthorizer>[0];
|
signInWithGoogle: ReturnType<typeof getAuthorizer>[0];
|
||||||
onAuthStateChanged: ReturnType<typeof getAuthorizer>[1];
|
onAuthStateChanged: ReturnType<typeof getAuthorizer>[1];
|
||||||
};
|
} & { token: typeof token };
|
||||||
|
|
||||||
export const getApis = (): Apis => {
|
export const getApis = (): Apis => {
|
||||||
const [signInWithGoogle, onAuthStateChanged] = getAuthorizer();
|
const [signInWithGoogle, onAuthStateChanged] = getAuthorizer();
|
||||||
@@ -18,6 +19,7 @@ export const getApis = (): Apis => {
|
|||||||
...workspace,
|
...workspace,
|
||||||
signInWithGoogle,
|
signInWithGoogle,
|
||||||
onAuthStateChanged,
|
onAuthStateChanged,
|
||||||
|
token,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { initializeApp } from 'firebase/app';
|
|||||||
import { getAuth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
|
import { getAuth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
|
||||||
import type { User } from 'firebase/auth';
|
import type { User } from 'firebase/auth';
|
||||||
|
|
||||||
import { getLogger } from '../../../logger';
|
import { getLogger } from '../../../logger.js';
|
||||||
import { bareClient } from './request';
|
import { bareClient } from './request.js';
|
||||||
|
|
||||||
export interface AccessTokenMessage {
|
export interface AccessTokenMessage {
|
||||||
create_at: number;
|
create_at: number;
|
||||||
@@ -46,6 +46,10 @@ class Token {
|
|||||||
this._setToken(); // fill with default value
|
this._setToken(); // fill with default value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get user() {
|
||||||
|
return this._user;
|
||||||
|
}
|
||||||
|
|
||||||
private _setToken(login?: LoginResponse) {
|
private _setToken(login?: LoginResponse) {
|
||||||
this._accessToken = login?.token || '';
|
this._accessToken = login?.token || '';
|
||||||
this._refreshToken = login?.refresh || '';
|
this._refreshToken = login?.refresh || '';
|
||||||
|
|||||||
1
packages/data-center/src/provider/affine/storage.ts
Normal file
1
packages/data-center/src/provider/affine/storage.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { varStorage as storage } from 'lib0/storage';
|
||||||
Reference in New Issue
Block a user