mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
4.8.11 test (#2843)
* feat: app version test * update doc * fix: paging num error * fix: doc api domain * rename variable * perf: memment node min size
This commit is contained in:
@@ -57,11 +57,25 @@ jest.mock('@/service/middleware/entry', () => {
|
||||
});
|
||||
|
||||
beforeAll(async () => {
|
||||
// 新建一个内存数据库,然后让 mongoose 连接这个数据库
|
||||
if (!global.mongod || !global.mongodb) {
|
||||
const mongod = await MongoMemoryServer.create();
|
||||
global.mongod = mongod;
|
||||
global.mongodb = mongoose;
|
||||
await global.mongodb.connect(mongod.getUri());
|
||||
|
||||
await global.mongodb.connect(mongod.getUri(), {
|
||||
bufferCommands: true,
|
||||
maxConnecting: 50,
|
||||
maxPoolSize: 50,
|
||||
minPoolSize: 20,
|
||||
connectTimeoutMS: 60000,
|
||||
waitQueueTimeoutMS: 60000,
|
||||
socketTimeoutMS: 60000,
|
||||
maxIdleTimeMS: 300000,
|
||||
retryWrites: true,
|
||||
retryReads: true
|
||||
});
|
||||
|
||||
await initMockData();
|
||||
}
|
||||
});
|
||||
|
@@ -13,34 +13,37 @@ export const root = {
|
||||
};
|
||||
|
||||
export const initMockData = async () => {
|
||||
// init root user
|
||||
const rootUser = await MongoUser.create({
|
||||
username: 'root',
|
||||
password: '123456'
|
||||
});
|
||||
const initRootUser = async () => {
|
||||
// init root user
|
||||
const rootUser = await MongoUser.create({
|
||||
username: 'root',
|
||||
password: '123456'
|
||||
});
|
||||
|
||||
const rootTeam = await MongoTeam.create({
|
||||
name: 'root-default-team',
|
||||
ownerId: rootUser._id
|
||||
});
|
||||
const rootTeam = await MongoTeam.create({
|
||||
name: 'root-default-team',
|
||||
ownerId: rootUser._id
|
||||
});
|
||||
|
||||
const rootTeamMember = await MongoTeamMember.create({
|
||||
teamId: rootTeam._id,
|
||||
userId: rootUser._id,
|
||||
name: 'root-default-team-member',
|
||||
status: 'active',
|
||||
role: TeamMemberRoleEnum.owner
|
||||
});
|
||||
const rootTeamMember = await MongoTeamMember.create({
|
||||
teamId: rootTeam._id,
|
||||
userId: rootUser._id,
|
||||
name: 'root-default-team-member',
|
||||
status: 'active',
|
||||
role: TeamMemberRoleEnum.owner
|
||||
});
|
||||
const rootApp = await MongoApp.create({
|
||||
name: 'root-default-app',
|
||||
teamId: rootTeam._id,
|
||||
tmbId: rootTeam._id,
|
||||
type: 'advanced'
|
||||
});
|
||||
|
||||
const rootApp = await MongoApp.create({
|
||||
name: 'root-default-app',
|
||||
teamId: rootTeam._id,
|
||||
tmbId: rootTeam._id,
|
||||
type: 'advanced'
|
||||
});
|
||||
root.uid = rootUser._id;
|
||||
root.tmbId = rootTeamMember._id;
|
||||
root.teamId = rootTeam._id;
|
||||
root.appId = rootApp._id;
|
||||
};
|
||||
|
||||
root.uid = rootUser._id;
|
||||
root.tmbId = rootTeamMember._id;
|
||||
root.teamId = rootTeam._id;
|
||||
root.appId = rootApp._id;
|
||||
await initRootUser();
|
||||
};
|
||||
|
55
projects/app/src/pages/api/core/app/version/latest.test.ts
Normal file
55
projects/app/src/pages/api/core/app/version/latest.test.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import '@/pages/api/__mocks__/base';
|
||||
import { root } from '@/pages/api/__mocks__/db/init';
|
||||
import { getTestRequest } from '@/test/utils';
|
||||
import handler, { getLatestVersionQuery, getLatestVersionResponse } from './latest';
|
||||
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
|
||||
|
||||
beforeAll(async () => {
|
||||
// 创建3个测试数据,其中2个是已发布的
|
||||
await MongoAppVersion.create([
|
||||
{
|
||||
appId: root.appId,
|
||||
nodes: [1],
|
||||
edges: [],
|
||||
chatConfig: {},
|
||||
isPublish: false,
|
||||
versionName: 'v1',
|
||||
tmbId: root.tmbId,
|
||||
time: new Date('2023-01-01')
|
||||
},
|
||||
{
|
||||
appId: root.appId,
|
||||
nodes: [2],
|
||||
edges: [],
|
||||
chatConfig: {},
|
||||
isPublish: true,
|
||||
versionName: 'v2',
|
||||
tmbId: root.tmbId,
|
||||
time: new Date('2023-01-02')
|
||||
},
|
||||
{
|
||||
appId: root.appId,
|
||||
nodes: [3],
|
||||
edges: [],
|
||||
chatConfig: {},
|
||||
isPublish: false,
|
||||
versionName: 'v3',
|
||||
tmbId: root.tmbId,
|
||||
time: new Date('2023-01-03')
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
test('获取最新版本并检查', async () => {
|
||||
const _res = (await handler(
|
||||
...getTestRequest<{}, getLatestVersionQuery>({
|
||||
query: {
|
||||
appId: root.appId
|
||||
},
|
||||
user: root
|
||||
})
|
||||
)) as any;
|
||||
const res = _res.data as getLatestVersionResponse;
|
||||
|
||||
expect(res.nodes[0]).toEqual(2);
|
||||
});
|
37
projects/app/src/pages/api/core/app/version/publish.test.ts
Normal file
37
projects/app/src/pages/api/core/app/version/publish.test.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import '@/pages/api/__mocks__/base';
|
||||
import { root } from '@/pages/api/__mocks__/db/init';
|
||||
import { getTestRequest } from '@/test/utils';
|
||||
import handler from './publish';
|
||||
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
|
||||
import { PostPublishAppProps } from '@/global/core/app/api';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
|
||||
describe('发布应用版本测试', () => {
|
||||
test('发布一个未发布的版本', async () => {
|
||||
const publishData: PostPublishAppProps = {
|
||||
nodes: [],
|
||||
edges: [],
|
||||
chatConfig: {},
|
||||
type: AppTypeEnum.simple,
|
||||
isPublish: false,
|
||||
versionName: '1'
|
||||
};
|
||||
|
||||
await handler(
|
||||
...getTestRequest<{ appId: string }, PostPublishAppProps>({
|
||||
body: publishData,
|
||||
query: { appId: root.appId },
|
||||
user: root
|
||||
})
|
||||
);
|
||||
|
||||
// 检查数据库是否插入成功
|
||||
const insertedVersion = await MongoAppVersion.countDocuments();
|
||||
|
||||
console.log(insertedVersion, '==-');
|
||||
|
||||
// expect(insertedVersion).toBeTruthy();
|
||||
// expect(insertedVersion?.isPublish).toBe(false);
|
||||
// expect(insertedVersion?.versionName).toBe('1');
|
||||
});
|
||||
});
|
@@ -8,7 +8,6 @@ import { beforeUpdateAppFormat } from '@fastgpt/service/core/app/controller';
|
||||
import { getNextTimeByCronStringAndTimezone } from '@fastgpt/global/common/string/time';
|
||||
import { PostPublishAppProps } from '@/global/core/app/api';
|
||||
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse<any>): Promise<{}> {
|
||||
const { appId } = req.query as { appId: string };
|
||||
|
@@ -9,7 +9,7 @@ import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const NodeComment = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
const NodeComment = ({ data }: NodeProps<FlowNodeItemType>) => {
|
||||
const { nodeId, inputs } = data;
|
||||
const { commentText, commentSize } = useMemo(
|
||||
() => ({
|
||||
@@ -39,8 +39,8 @@ const NodeComment = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
const deltaY = e.clientY - initialY.current;
|
||||
const deltaX = e.clientX - initialX.current;
|
||||
setSize((prevSize) => ({
|
||||
width: prevSize.width + deltaX < 240 ? 240 : prevSize.width + deltaX,
|
||||
height: prevSize.height + deltaY < 140 ? 140 : prevSize.height + deltaY
|
||||
width: prevSize.width + deltaX < 120 ? 120 : prevSize.width + deltaX,
|
||||
height: prevSize.height + deltaY < 60 ? 60 : prevSize.height + deltaY
|
||||
}));
|
||||
initialY.current = e.clientY;
|
||||
initialX.current = e.clientX;
|
||||
@@ -70,59 +70,63 @@ const NodeComment = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
[commentSize, nodeId, onChangeNode, size.height, size.width]
|
||||
);
|
||||
|
||||
return (
|
||||
<NodeCard
|
||||
selected={false}
|
||||
{...data}
|
||||
minW={`${size.width}px`}
|
||||
minH={`${size.height}px`}
|
||||
menuForbid={{
|
||||
debug: true
|
||||
}}
|
||||
border={'none'}
|
||||
rounded={'none'}
|
||||
bg={'#D8E9FF'}
|
||||
boxShadow={
|
||||
'0px 4px 10px 0px rgba(19, 51, 107, 0.10), 0px 0px 1px 0px rgba(19, 51, 107, 0.10)'
|
||||
}
|
||||
>
|
||||
<Box w={'full'} h={'full'} position={'relative'}>
|
||||
<Box
|
||||
position={'absolute'}
|
||||
right={'0'}
|
||||
bottom={'-2'}
|
||||
zIndex={9}
|
||||
cursor={'nwse-resize'}
|
||||
px={'2px'}
|
||||
className="nodrag"
|
||||
onMouseDown={handleMouseDown}
|
||||
>
|
||||
<MyIcon name={'common/editor/resizer'} width={'14px'} height={'14px'} />
|
||||
const Render = useMemo(() => {
|
||||
return (
|
||||
<NodeCard
|
||||
selected={false}
|
||||
{...data}
|
||||
minW={`${size.width}px`}
|
||||
minH={`${size.height}px`}
|
||||
menuForbid={{
|
||||
debug: true
|
||||
}}
|
||||
border={'none'}
|
||||
rounded={'none'}
|
||||
bg={'#D8E9FF'}
|
||||
boxShadow={
|
||||
'0px 4px 10px 0px rgba(19, 51, 107, 0.10), 0px 0px 1px 0px rgba(19, 51, 107, 0.10)'
|
||||
}
|
||||
>
|
||||
<Box w={'full'} h={'full'} position={'relative'}>
|
||||
<Box
|
||||
position={'absolute'}
|
||||
right={'0'}
|
||||
bottom={'-2'}
|
||||
zIndex={9}
|
||||
cursor={'nwse-resize'}
|
||||
px={'2px'}
|
||||
className="nodrag"
|
||||
onMouseDown={handleMouseDown}
|
||||
>
|
||||
<MyIcon name={'common/editor/resizer'} width={'14px'} height={'14px'} />
|
||||
</Box>
|
||||
<Textarea
|
||||
value={commentText?.value}
|
||||
border={'none'}
|
||||
rounded={'none'}
|
||||
minH={`${size.height}px`}
|
||||
minW={`${size.width}px`}
|
||||
resize={'none'}
|
||||
placeholder={t('workflow:enter_comment')}
|
||||
onChange={(e) => {
|
||||
commentText &&
|
||||
onChangeNode({
|
||||
nodeId: nodeId,
|
||||
type: 'updateInput',
|
||||
key: NodeInputKeyEnum.commentText,
|
||||
value: {
|
||||
...commentText,
|
||||
value: e.target.value
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Textarea
|
||||
value={commentText?.value}
|
||||
border={'none'}
|
||||
rounded={'none'}
|
||||
minH={`${size.height}px`}
|
||||
minW={`${size.width}px`}
|
||||
resize={'none'}
|
||||
placeholder={t('workflow:enter_comment')}
|
||||
onChange={(e) => {
|
||||
commentText &&
|
||||
onChangeNode({
|
||||
nodeId: nodeId,
|
||||
type: 'updateInput',
|
||||
key: NodeInputKeyEnum.commentText,
|
||||
value: {
|
||||
...commentText,
|
||||
value: e.target.value
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</NodeCard>
|
||||
);
|
||||
</NodeCard>
|
||||
);
|
||||
}, [commentText, data, handleMouseDown, nodeId, onChangeNode, size.height, size.width, t]);
|
||||
|
||||
return Render;
|
||||
};
|
||||
|
||||
export default React.memo(NodeComment);
|
||||
|
@@ -14,7 +14,7 @@ import { useForm } from 'react-hook-form';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||
import { fnValueTypeSelect } from '@/web/core/workflow/constants/dataType';
|
||||
import { toolValueTypeList } from '@fastgpt/global/core/workflow/constants';
|
||||
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
||||
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
|
||||
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
@@ -82,7 +82,7 @@ const ExtractFieldModal = ({
|
||||
</FormLabel>
|
||||
<Box flex={'1 0 0'}>
|
||||
<MySelect<string>
|
||||
list={fnValueTypeSelect}
|
||||
list={toolValueTypeList}
|
||||
value={valueType}
|
||||
onchange={(e) => {
|
||||
setValue('valueType', e as any);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { fnValueTypeSelect } from '@/web/core/workflow/constants/dataType';
|
||||
import { toolValueTypeList } from '@fastgpt/global/core/workflow/constants';
|
||||
import { Box, Button, Flex, Input, ModalBody, ModalFooter, Textarea } from '@chakra-ui/react';
|
||||
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
@@ -121,7 +121,7 @@ const ToolParamsEditModal = ({
|
||||
<FormLabel flex={'0 0 80px'}>{t('common:core.module.Data Type')}</FormLabel>
|
||||
<Box flex={'1 0 0'}>
|
||||
<MySelect
|
||||
list={fnValueTypeSelect}
|
||||
list={toolValueTypeList}
|
||||
value={valueType}
|
||||
onchange={(e: any) => {
|
||||
setValue('valueType', e);
|
||||
|
@@ -36,7 +36,7 @@ const NodeToolParams = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
|
||||
<NodeCard selected={selected} {...data}>
|
||||
<Container>
|
||||
<Flex alignItems={'center'} justifyContent={'space-between'} mb={1.5}>
|
||||
<FormLabel>{t('workflow:custom_tool_input')}</FormLabel>
|
||||
<FormLabel>{t('workflow:tool_custom_field')}</FormLabel>
|
||||
<Button
|
||||
variant={'whiteBase'}
|
||||
leftIcon={<SmallAddIcon />}
|
||||
|
@@ -6,7 +6,6 @@ import Divider from '../components/Divider';
|
||||
import Container from '../components/Container';
|
||||
import RenderInput from './render/RenderInput';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { ToolSourceHandle } from './render/Handle/ToolHandle';
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import IOTitle from '../components/IOTitle';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
|
@@ -19,7 +19,7 @@ import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io.d';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { WorkflowContext } from '@/pages/app/detail/components/WorkflowComponents/context';
|
||||
import { fnValueTypeSelect } from '@/web/core/workflow/constants/dataType';
|
||||
import { toolValueTypeList } from '@fastgpt/global/core/workflow/constants';
|
||||
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
|
||||
@@ -95,7 +95,7 @@ const EditFieldModal = ({
|
||||
<Box flex={'0 0 80px'}>{t('common:core.module.Data Type')}</Box>
|
||||
<Box flex={'1 0 0'}>
|
||||
<MySelect
|
||||
list={fnValueTypeSelect}
|
||||
list={toolValueTypeList}
|
||||
value={valueType}
|
||||
onchange={(e: any) => {
|
||||
setValue('valueType', e);
|
||||
@@ -150,7 +150,7 @@ export const defaultEditFormData: FlowNodeInputItemType = {
|
||||
required: true,
|
||||
canEdit: true,
|
||||
customInputConfig: {
|
||||
selectValueTypeList: Object.values(fnValueTypeSelect).map((item) => item.value),
|
||||
selectValueTypeList: Object.values(toolValueTypeList).map((item) => item.value),
|
||||
showDescription: true
|
||||
}
|
||||
};
|
||||
|
@@ -15,7 +15,6 @@ import {
|
||||
putDatasetCollectionById
|
||||
} from '@/web/core/dataset/api';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { debounce } from 'lodash';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyInput from '@/components/MyInput';
|
||||
|
@@ -69,7 +69,7 @@ const Detail = ({ datasetId, currentTab }: Props) => {
|
||||
<Flex h={'100%'} py={3} pl={1} pr={3} gap={2}>
|
||||
<Flex flex={1} w={0} bg={'white'} flexDir={'column'} boxShadow={'2'} borderRadius={'md'}>
|
||||
{currentTab !== TabEnum.import && <NavBar currentTab={currentTab} />}
|
||||
<Box flex={'1'} overflow={'auto'}>
|
||||
<Box flex={'1'} overflowY={'auto'}>
|
||||
{currentTab === TabEnum.collectionCard && (
|
||||
<CollectionPageContextProvider>
|
||||
<CollectionCard />
|
||||
|
@@ -31,8 +31,8 @@ export function getTestRequest<Q = any, B = any>({
|
||||
// authApiKey = false,
|
||||
user
|
||||
}: {
|
||||
body?: Partial<B>;
|
||||
query?: Partial<Q>;
|
||||
body?: Partial<B>;
|
||||
authToken?: boolean;
|
||||
authRoot?: boolean;
|
||||
authApiKey?: boolean;
|
||||
|
@@ -1,28 +0,0 @@
|
||||
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
|
||||
export const fnValueTypeSelect = [
|
||||
{
|
||||
label: WorkflowIOValueTypeEnum.string,
|
||||
value: WorkflowIOValueTypeEnum.string
|
||||
},
|
||||
{
|
||||
label: WorkflowIOValueTypeEnum.number,
|
||||
value: WorkflowIOValueTypeEnum.number
|
||||
},
|
||||
{
|
||||
label: WorkflowIOValueTypeEnum.boolean,
|
||||
value: WorkflowIOValueTypeEnum.boolean
|
||||
},
|
||||
{
|
||||
label: 'array<string>',
|
||||
value: WorkflowIOValueTypeEnum.arrayString
|
||||
},
|
||||
{
|
||||
label: 'array<number>',
|
||||
value: WorkflowIOValueTypeEnum.arrayNumber
|
||||
},
|
||||
{
|
||||
label: 'array<boolean>',
|
||||
value: WorkflowIOValueTypeEnum.arrayBoolean
|
||||
}
|
||||
];
|
@@ -1,4 +1,4 @@
|
||||
export const strToBase64 = (str: string, prefix: string) => {
|
||||
export const strToBase64 = (str: string, prefix: string = '') => {
|
||||
const base64_string = Buffer.from(str, 'utf-8').toString('base64');
|
||||
|
||||
return `${prefix}${base64_string}`;
|
||||
|
Reference in New Issue
Block a user