feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { vi, describe, it, expect, beforeEach, type Mock } from 'vitest';
|
||||
import { DeveloperApi, PlaygroundApi } from '@coze-arch/bot-api';
|
||||
|
||||
import { useUserStore, defaultState } from '../user';
|
||||
|
||||
vi.mock('@coze-arch/bot-api', () => ({
|
||||
DeveloperApi: {
|
||||
GetUserAuthList: vi.fn(),
|
||||
},
|
||||
PlaygroundApi: {
|
||||
MGetUserBasicInfo: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('useUserStore', () => {
|
||||
beforeEach(() => {
|
||||
useUserStore.setState(defaultState);
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should have the correct default state', () => {
|
||||
const state = useUserStore.getState();
|
||||
expect(state.isSettled).toBe(false);
|
||||
expect(state.userInfo).toBeNull();
|
||||
expect(state.hasError).toBe(false);
|
||||
expect(state.userAuthInfos).toEqual([]);
|
||||
expect(state.userLabel).toBeNull();
|
||||
});
|
||||
|
||||
describe('actions', () => {
|
||||
it('reset should reset state to default and set isSettled to true', () => {
|
||||
useUserStore.setState({
|
||||
userInfo: { user_id_str: '123' } as any,
|
||||
isSettled: false,
|
||||
});
|
||||
useUserStore.getState().reset();
|
||||
const state = useUserStore.getState();
|
||||
expect(state.userInfo).toBeNull();
|
||||
expect(state.userAuthInfos).toEqual([]);
|
||||
expect(state.userLabel).toBeNull();
|
||||
expect(state.isSettled).toBe(true);
|
||||
expect(state.hasError).toBe(false);
|
||||
});
|
||||
|
||||
it('setIsSettled should update isSettled', () => {
|
||||
useUserStore.getState().setIsSettled(true);
|
||||
expect(useUserStore.getState().isSettled).toBe(true);
|
||||
useUserStore.getState().setIsSettled(false);
|
||||
expect(useUserStore.getState().isSettled).toBe(false);
|
||||
});
|
||||
|
||||
describe('setUserInfo', () => {
|
||||
it('should update userInfo', () => {
|
||||
const newUserInfo = {
|
||||
user_id_str: 'testUser',
|
||||
name: 'Test User',
|
||||
} as any;
|
||||
useUserStore.getState().setUserInfo(newUserInfo);
|
||||
expect(useUserStore.getState().userInfo).toEqual(newUserInfo);
|
||||
});
|
||||
|
||||
it('should call fetchUserLabel if user_id_str changes', async () => {
|
||||
const newUserInfo = {
|
||||
user_id_str: 'newUser123',
|
||||
name: 'New User',
|
||||
} as any;
|
||||
const initialUserInfo = {
|
||||
user_id_str: 'oldUser456',
|
||||
name: 'Old User',
|
||||
} as any;
|
||||
|
||||
// Set an initial user
|
||||
useUserStore.setState({ userInfo: initialUserInfo });
|
||||
|
||||
(PlaygroundApi.MGetUserBasicInfo as Mock).mockResolvedValueOnce({
|
||||
id_user_info_map: {
|
||||
[newUserInfo.user_id_str]: {
|
||||
user_label: { label_type: 1, text: 'Test Label' },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
useUserStore.getState().setUserInfo(newUserInfo);
|
||||
expect(useUserStore.getState().userInfo).toEqual(newUserInfo);
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(PlaygroundApi.MGetUserBasicInfo).toHaveBeenCalledWith({
|
||||
user_ids: [newUserInfo.user_id_str],
|
||||
});
|
||||
});
|
||||
await vi.waitFor(() => {
|
||||
expect(useUserStore.getState().userLabel).toEqual({
|
||||
label_type: 1,
|
||||
text: 'Test Label',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not call fetchUserLabel if user_id_str is the same', () => {
|
||||
const userInfo = { user_id_str: 'user123', name: 'Test User' } as any;
|
||||
useUserStore.setState({ userInfo });
|
||||
|
||||
useUserStore.getState().setUserInfo(userInfo);
|
||||
expect(PlaygroundApi.MGetUserBasicInfo).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserAuthInfos', () => {
|
||||
it('should fetch and set userAuthInfos on success', async () => {
|
||||
const mockAuthInfos = [
|
||||
{ auth_type: 'email', auth_key: 'test@example.com' },
|
||||
];
|
||||
(DeveloperApi.GetUserAuthList as Mock).mockResolvedValueOnce({
|
||||
data: mockAuthInfos,
|
||||
});
|
||||
|
||||
await useUserStore.getState().getUserAuthInfos();
|
||||
|
||||
expect(DeveloperApi.GetUserAuthList).toHaveBeenCalledTimes(1);
|
||||
expect(useUserStore.getState().userAuthInfos).toEqual(mockAuthInfos);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
89
frontend/packages/foundation/account-base/src/store/user.ts
Normal file
89
frontend/packages/foundation/account-base/src/store/user.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { devtools, subscribeWithSelector } from 'zustand/middleware';
|
||||
import { create } from 'zustand';
|
||||
import {
|
||||
type UserAuthInfo,
|
||||
type UserLabel,
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
import { DeveloperApi, PlaygroundApi } from '@coze-arch/bot-api';
|
||||
|
||||
import { type UserInfo } from '../types';
|
||||
|
||||
export interface UserStoreState {
|
||||
isSettled: boolean;
|
||||
hasError: boolean;
|
||||
userInfo: UserInfo | null;
|
||||
userAuthInfos: UserAuthInfo[];
|
||||
userLabel: UserLabel | null;
|
||||
}
|
||||
|
||||
export interface UserStoreAction {
|
||||
reset: () => void;
|
||||
setIsSettled: (isSettled: boolean) => void;
|
||||
setUserInfo: (userInfo: UserInfo | null) => void;
|
||||
getUserAuthInfos: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const defaultState: UserStoreState = {
|
||||
isSettled: false,
|
||||
userInfo: null,
|
||||
hasError: false,
|
||||
userAuthInfos: [],
|
||||
userLabel: null,
|
||||
};
|
||||
|
||||
export const useUserStore = create<UserStoreState & UserStoreAction>()(
|
||||
devtools(
|
||||
subscribeWithSelector((set, get) => ({
|
||||
...defaultState,
|
||||
reset: () => {
|
||||
set({ ...defaultState, isSettled: true });
|
||||
},
|
||||
setIsSettled: isSettled => {
|
||||
set({
|
||||
isSettled,
|
||||
});
|
||||
},
|
||||
setUserInfo: (userInfo: UserInfo | null) => {
|
||||
if (
|
||||
userInfo?.user_id_str &&
|
||||
userInfo?.user_id_str !== get().userInfo?.user_id_str
|
||||
) {
|
||||
fetchUserLabel(userInfo?.user_id_str);
|
||||
}
|
||||
set({
|
||||
userInfo,
|
||||
});
|
||||
},
|
||||
getUserAuthInfos: async () => {
|
||||
const { data = [] } = await DeveloperApi.GetUserAuthList();
|
||||
set({ userAuthInfos: data });
|
||||
},
|
||||
})),
|
||||
{
|
||||
enabled: IS_DEV_MODE,
|
||||
name: 'botStudio.userStore',
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
const fetchUserLabel = async (id: string) => {
|
||||
const res = await PlaygroundApi.MGetUserBasicInfo({ user_ids: [id] });
|
||||
const userLabel = res?.id_user_info_map?.[id]?.user_label;
|
||||
useUserStore.setState({ userLabel });
|
||||
};
|
||||
Reference in New Issue
Block a user