@lobehub/chat
Version:
Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.
259 lines (219 loc) • 8.16 kB
text/typescript
// @vitest-environment node
import { and, eq } from 'drizzle-orm/expressions';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { LobeChatDatabase } from '@/database/type';
import { sleep } from '@/utils/sleep';
import {
NewKnowledgeBase,
files,
globalFiles,
knowledgeBaseFiles,
knowledgeBases,
users,
} from '../../schemas';
import { KnowledgeBaseModel } from '../knowledgeBase';
import { getTestDB } from './_util';
const serverDB: LobeChatDatabase = await getTestDB();
const userId = 'session-group-model-test-user-id';
const knowledgeBaseModel = new KnowledgeBaseModel(serverDB, userId);
beforeEach(async () => {
await serverDB.delete(users);
await serverDB.delete(globalFiles);
await serverDB.insert(users).values([{ id: userId }, { id: 'user2' }]);
});
afterEach(async () => {
await serverDB.delete(users).where(eq(users.id, userId));
await serverDB.delete(knowledgeBases).where(eq(knowledgeBases.userId, userId));
});
describe('KnowledgeBaseModel', () => {
describe('create', () => {
it('should create a new knowledge base', async () => {
const params = {
name: 'Test Group',
} as NewKnowledgeBase;
const result = await knowledgeBaseModel.create(params);
expect(result.id).toBeDefined();
expect(result).toMatchObject({ ...params, userId });
const group = await serverDB.query.knowledgeBases.findFirst({
where: eq(knowledgeBases.id, result.id),
});
expect(group).toMatchObject({ ...params, userId });
});
});
describe('delete', () => {
it('should delete a knowledge base by id', async () => {
const { id } = await knowledgeBaseModel.create({ name: 'Test Group' });
await knowledgeBaseModel.delete(id);
const group = await serverDB.query.knowledgeBases.findFirst({
where: eq(knowledgeBases.id, id),
});
expect(group).toBeUndefined();
});
});
describe('deleteAll', () => {
it('should delete all knowledge bases for the user', async () => {
await knowledgeBaseModel.create({ name: 'Test Group 1' });
await knowledgeBaseModel.create({ name: 'Test Group 2' });
await knowledgeBaseModel.deleteAll();
const userGroups = await serverDB.query.knowledgeBases.findMany({
where: eq(knowledgeBases.userId, userId),
});
expect(userGroups).toHaveLength(0);
});
it('should only delete knowledge bases for the user, not others', async () => {
await knowledgeBaseModel.create({ name: 'Test Group 1' });
await knowledgeBaseModel.create({ name: 'Test Group 333' });
const anotherSessionGroupModel = new KnowledgeBaseModel(serverDB, 'user2');
await anotherSessionGroupModel.create({ name: 'Test Group 2' });
await knowledgeBaseModel.deleteAll();
const userGroups = await serverDB.query.knowledgeBases.findMany({
where: eq(knowledgeBases.userId, userId),
});
const total = await serverDB.query.knowledgeBases.findMany();
expect(userGroups).toHaveLength(0);
expect(total).toHaveLength(1);
});
});
describe('query', () => {
it('should query knowledge bases for the user', async () => {
await knowledgeBaseModel.create({ name: 'Test Group 1' });
await sleep(50);
await knowledgeBaseModel.create({ name: 'Test Group 2' });
const userGroups = await knowledgeBaseModel.query();
expect(userGroups).toHaveLength(2);
expect(userGroups[0].name).toBe('Test Group 2');
expect(userGroups[1].name).toBe('Test Group 1');
});
});
describe('findById', () => {
it('should find a knowledge base by id', async () => {
const { id } = await knowledgeBaseModel.create({ name: 'Test Group' });
const group = await knowledgeBaseModel.findById(id);
expect(group).toMatchObject({
id,
name: 'Test Group',
userId,
});
});
});
describe('update', () => {
it('should update a knowledge base', async () => {
const { id } = await knowledgeBaseModel.create({ name: 'Test Group' });
await knowledgeBaseModel.update(id, { name: 'Updated Test Group' });
const updatedGroup = await serverDB.query.knowledgeBases.findFirst({
where: eq(knowledgeBases.id, id),
});
expect(updatedGroup).toMatchObject({
id,
name: 'Updated Test Group',
userId,
});
});
});
const fileList = [
{
id: 'file1',
name: 'document.pdf',
url: 'https://example.com/document.pdf',
fileHash: 'hash1',
size: 1000,
fileType: 'application/pdf',
userId,
},
{
id: 'file2',
name: 'image.jpg',
url: 'https://example.com/image.jpg',
fileHash: 'hash2',
size: 500,
fileType: 'image/jpeg',
userId,
},
];
describe('addFilesToKnowledgeBase', () => {
it('should add files to a knowledge base', async () => {
await serverDB.insert(globalFiles).values([
{
hashId: 'hash1',
url: 'https://example.com/document.pdf',
size: 1000,
fileType: 'application/pdf',
creator: userId,
},
{
hashId: 'hash2',
url: 'https://example.com/image.jpg',
size: 500,
fileType: 'image/jpeg',
creator: userId,
},
]);
await serverDB.insert(files).values(fileList);
const { id: knowledgeBaseId } = await knowledgeBaseModel.create({ name: 'Test Group' });
const fileIds = ['file1', 'file2'];
const result = await knowledgeBaseModel.addFilesToKnowledgeBase(knowledgeBaseId, fileIds);
expect(result).toHaveLength(2);
expect(result).toEqual(
expect.arrayContaining(
fileIds.map((fileId) => expect.objectContaining({ fileId, knowledgeBaseId })),
),
);
const addedFiles = await serverDB.query.knowledgeBaseFiles.findMany({
where: eq(knowledgeBaseFiles.knowledgeBaseId, knowledgeBaseId),
});
expect(addedFiles).toHaveLength(2);
});
});
describe('removeFilesFromKnowledgeBase', () => {
it('should remove files from a knowledge base', async () => {
await serverDB.insert(globalFiles).values([
{
hashId: 'hash1',
url: 'https://example.com/document.pdf',
size: 1000,
fileType: 'application/pdf',
creator: userId,
},
{
hashId: 'hash2',
url: 'https://example.com/image.jpg',
size: 500,
fileType: 'image/jpeg',
creator: userId,
},
]);
await serverDB.insert(files).values(fileList);
const { id: knowledgeBaseId } = await knowledgeBaseModel.create({ name: 'Test Group' });
const fileIds = ['file1', 'file2'];
await knowledgeBaseModel.addFilesToKnowledgeBase(knowledgeBaseId, fileIds);
const filesToRemove = ['file1'];
await knowledgeBaseModel.removeFilesFromKnowledgeBase(knowledgeBaseId, filesToRemove);
const remainingFiles = await serverDB.query.knowledgeBaseFiles.findMany({
where: and(eq(knowledgeBaseFiles.knowledgeBaseId, knowledgeBaseId)),
});
expect(remainingFiles).toHaveLength(1);
expect(remainingFiles[0].fileId).toBe('file2');
});
});
describe('static findById', () => {
it('should find a knowledge base by id without user restriction', async () => {
const { id } = await knowledgeBaseModel.create({ name: 'Test Group' });
const group = await KnowledgeBaseModel.findById(serverDB, id);
expect(group).toMatchObject({
id,
name: 'Test Group',
userId,
});
});
it('should find a knowledge base created by another user', async () => {
const anotherKnowledgeBaseModel = new KnowledgeBaseModel(serverDB, 'user2');
const { id } = await anotherKnowledgeBaseModel.create({ name: 'Another User Group' });
const group = await KnowledgeBaseModel.findById(serverDB, id);
expect(group).toMatchObject({
id,
name: 'Another User Group',
userId: 'user2',
});
});
});
});