feat: 修改补充单测 (#437)

This commit is contained in:
luch 2024-09-30 18:23:28 +08:00 committed by luch1994
parent b59ec7b14f
commit 2ddfe84148
37 changed files with 1261 additions and 743 deletions

View File

@ -95,7 +95,9 @@
"^.+\\.(t|j)s$": "ts-jest" "^.+\\.(t|j)s$": "ts-jest"
}, },
"collectCoverageFrom": [ "collectCoverageFrom": [
"**/*.(t|j)s" "**/*.(t|j)s",
"!**/*.module.ts",
"!**/upgrade.*.ts"
], ],
"coverageDirectory": "../coverage", "coverageDirectory": "../coverage",
"testEnvironment": "node", "testEnvironment": "node",

View File

@ -1,30 +0,0 @@
import { BaseEntity } from '../base.entity';
import { RECORD_STATUS } from 'src/enums';
describe('BaseEntity', () => {
let baseEntity: BaseEntity;
beforeEach(() => {
baseEntity = new BaseEntity();
});
it('should initialize default info before insert', () => {
const now = Date.now();
baseEntity.initDefaultInfo();
expect(baseEntity.curStatus.status).toBe(RECORD_STATUS.NEW);
expect(baseEntity.curStatus.date).toBeCloseTo(now, -3);
expect(baseEntity.statusList).toHaveLength(1);
expect(baseEntity.statusList[0].status).toBe(RECORD_STATUS.NEW);
expect(baseEntity.statusList[0].date).toBeCloseTo(now, -3);
expect(baseEntity.createDate).toBeCloseTo(now, -3);
expect(baseEntity.updateDate).toBeCloseTo(now, -3);
});
it('should update updateDate before update', () => {
const now = Date.now();
baseEntity.onUpdate();
expect(baseEntity.updateDate).toBeCloseTo(now, -3);
});
});

View File

@ -0,0 +1,57 @@
import { SurveyMeta } from '../surveyMeta.entity';
import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums';
// 模拟日期
const mockDateNow = Date.now();
describe('SurveyMeta Entity', () => {
let surveyMeta: SurveyMeta;
// 在每个测试之前,初始化 SurveyMeta 实例
beforeEach(() => {
surveyMeta = new SurveyMeta();
// 模拟 Date.now() 返回固定的时间
jest.spyOn(Date, 'now').mockReturnValue(mockDateNow);
});
afterEach(() => {
jest.restoreAllMocks(); // 每次测试后还原所有 mock
});
it('should set default curStatus and subStatus on insert when they are not provided', () => {
surveyMeta.initDefaultInfo();
// 验证 curStatus 是否被初始化为默认值
expect(surveyMeta.curStatus).toEqual({
status: RECORD_STATUS.NEW,
date: mockDateNow,
});
// 验证 statusList 是否包含 curStatus
expect(surveyMeta.statusList).toEqual([
{
status: RECORD_STATUS.NEW,
date: mockDateNow,
},
]);
// 验证 subStatus 是否被初始化为默认值
expect(surveyMeta.subStatus).toEqual({
status: RECORD_SUB_STATUS.DEFAULT,
date: mockDateNow,
});
});
it('should initialize statusList if curStatus is provided but statusList is empty', () => {
surveyMeta.curStatus = null;
surveyMeta.initDefaultInfo();
expect(surveyMeta.statusList).toEqual([
{
status: RECORD_STATUS.NEW,
date: expect.any(Number),
},
]);
});
});

View File

@ -206,8 +206,8 @@ describe('UserService', () => {
it('should return a list of users by username', async () => { it('should return a list of users by username', async () => {
const username = 'test'; const username = 'test';
const userList = [ const userList = [
{ _id: new ObjectId(), username: 'testUser1', createDate: new Date() }, { _id: new ObjectId(), username: 'testUser1', createdAt: new Date() },
{ _id: new ObjectId(), username: 'testUser2', createDate: new Date() }, { _id: new ObjectId(), username: 'testUser2', createdAt: new Date() },
]; ];
jest jest
@ -226,7 +226,7 @@ describe('UserService', () => {
}, },
skip: 0, skip: 0,
take: 10, take: 10,
select: ['_id', 'username', 'createDate'], select: ['_id', 'username', 'createdAt'],
}); });
expect(result).toEqual(userList); expect(result).toEqual(userList);
}); });
@ -237,12 +237,12 @@ describe('UserService', () => {
{ {
_id: new ObjectId(idList[0]), _id: new ObjectId(idList[0]),
username: 'testUser1', username: 'testUser1',
createDate: new Date(), createdAt: new Date(),
}, },
{ {
_id: new ObjectId(idList[1]), _id: new ObjectId(idList[1]),
username: 'testUser2', username: 'testUser2',
createDate: new Date(), createdAt: new Date(),
}, },
]; ];
@ -258,7 +258,7 @@ describe('UserService', () => {
$in: idList.map((id) => new ObjectId(id)), $in: idList.map((id) => new ObjectId(id)),
}, },
}, },
select: ['_id', 'username', 'createDate'], select: ['_id', 'username', 'createdAt'],
}); });
expect(result).toEqual(userList); expect(result).toEqual(userList);
}); });

View File

@ -8,7 +8,6 @@ import {
MESSAGE_PUSHING_TYPE, MESSAGE_PUSHING_TYPE,
MESSAGE_PUSHING_HOOK, MESSAGE_PUSHING_HOOK,
} from 'src/enums/messagePushing'; } from 'src/enums/messagePushing';
import { RECORD_STATUS } from 'src/enums';
describe('MessagePushingTaskDto', () => { describe('MessagePushingTaskDto', () => {
let dto: MessagePushingTaskDto; let dto: MessagePushingTaskDto;
@ -34,9 +33,9 @@ describe('MessagePushingTaskDto', () => {
}); });
it('should have a type', () => { it('should have a type', () => {
dto.type = MESSAGE_PUSHING_TYPE.HTTP; // Set your desired type here dto.type = MESSAGE_PUSHING_TYPE.HTTP;
expect(dto.type).toBeDefined(); expect(dto.type).toBeDefined();
expect(dto.type).toEqual(MESSAGE_PUSHING_TYPE.HTTP); // Adjust based on your enum expect(dto.type).toEqual(MESSAGE_PUSHING_TYPE.HTTP);
}); });
it('should have a push address', () => { it('should have a push address', () => {
@ -46,13 +45,13 @@ describe('MessagePushingTaskDto', () => {
}); });
it('should have a trigger hook', () => { it('should have a trigger hook', () => {
dto.triggerHook = MESSAGE_PUSHING_HOOK.RESPONSE_INSERTED; // Set your desired hook here dto.triggerHook = MESSAGE_PUSHING_HOOK.RESPONSE_INSERTED;
expect(dto.triggerHook).toBeDefined(); expect(dto.triggerHook).toBeDefined();
expect(dto.triggerHook).toEqual(MESSAGE_PUSHING_HOOK.RESPONSE_INSERTED); // Adjust based on your enum expect(dto.triggerHook).toEqual(MESSAGE_PUSHING_HOOK.RESPONSE_INSERTED);
}); });
it('should have an array of surveys', () => { it('should have an array of surveys', () => {
dto.surveys = ['survey1', 'survey2']; // Set your desired surveys here dto.surveys = ['survey1', 'survey2'];
expect(dto.surveys).toBeDefined(); expect(dto.surveys).toBeDefined();
expect(dto.surveys).toEqual(['survey1', 'survey2']); expect(dto.surveys).toEqual(['survey1', 'survey2']);
}); });
@ -62,13 +61,6 @@ describe('MessagePushingTaskDto', () => {
expect(dto.owner).toBeDefined(); expect(dto.owner).toBeDefined();
expect(dto.owner).toBe('test_owner'); expect(dto.owner).toBe('test_owner');
}); });
it('should have current status', () => {
dto.curStatus = { status: RECORD_STATUS.NEW, date: Date.now() };
expect(dto.curStatus).toBeDefined();
expect(dto.curStatus.status).toEqual(RECORD_STATUS.NEW);
expect(dto.curStatus.date).toBeDefined();
});
}); });
describe('CodeDto', () => { describe('CodeDto', () => {

View File

@ -117,6 +117,9 @@ describe('MessagePushingTaskService', () => {
expect(result).toEqual(tasks); expect(result).toEqual(tasks);
expect(repository.find).toHaveBeenCalledWith({ expect(repository.find).toHaveBeenCalledWith({
where: { where: {
isDeleted: {
$ne: true,
},
ownerId: mockOwnerId, ownerId: mockOwnerId,
surveys: { $all: [surveyId] }, surveys: { $all: [surveyId] },
triggerHook: hook, triggerHook: hook,
@ -144,9 +147,19 @@ describe('MessagePushingTaskService', () => {
where: { where: {
ownerId: mockOwnerId, ownerId: mockOwnerId,
_id: new ObjectId(taskId), _id: new ObjectId(taskId),
isDeleted: {
$ne: true,
},
}, },
}); });
}); });
it('should throw an error when message pushing task is not found', async () => {
const taskId = '65afc62904d5db18534c0f78';
jest.spyOn(repository, 'findOne').mockResolvedValue(null); // 模拟未找到任务
const mockOwnerId = '66028642292c50f8b71a9eee';
await expect(service.findOne({ id: taskId, ownerId: mockOwnerId }));
});
}); });
describe('update', () => { describe('update', () => {
@ -183,6 +196,20 @@ describe('MessagePushingTaskService', () => {
}); });
expect(repository.save).toHaveBeenCalledWith(updatedTask); expect(repository.save).toHaveBeenCalledWith(updatedTask);
}); });
it('should throw an error if the task to be updated is not found', async () => {
const taskId = '65afc62904d5db18534c0f78';
const updateDto: UpdateMessagePushingTaskDto = { name: 'Updated Task' };
jest.spyOn(repository, 'findOne').mockResolvedValue(null); // 模拟任务未找到
const mockOwnerId = '66028642292c50f8b71a9eee';
await expect(
service.update({
ownerId: mockOwnerId,
id: taskId,
updateData: updateDto,
}),
).rejects.toThrow(`Message pushing task with id ${taskId} not found`);
});
}); });
describe('remove', () => { describe('remove', () => {
@ -204,16 +231,40 @@ describe('MessagePushingTaskService', () => {
expect(result).toEqual(updateResult); expect(result).toEqual(updateResult);
expect(repository.updateOne).toHaveBeenCalledWith( expect(repository.updateOne).toHaveBeenCalledWith(
{ {
ownerId: mockOperatorId,
_id: new ObjectId(taskId), _id: new ObjectId(taskId),
}, },
{ {
$set: { $set: {
isDeleted: true, isDeleted: true,
operatorId: mockOperatorId,
operator: mockOperator,
deletedAt: expect.any(Date),
}, },
}, },
); );
}); });
it('should throw an error if the task to be removed is not found', async () => {
const taskId = '65afc62904d5db18534c0f78';
jest
.spyOn(repository, 'updateOne')
.mockResolvedValue({ modifiedCount: 0 }); // 模拟删除失败
const mockOperatorId = '66028642292c50f8b71a9eee';
const mockOperator = 'mockOperator';
const result = await service.remove({
id: taskId,
operatorId: mockOperatorId,
operator: mockOperator,
});
expect(result.modifiedCount).toBe(0);
expect(repository.updateOne).toHaveBeenCalledWith(
{
_id: new ObjectId(taskId),
},
expect.any(Object),
);
});
}); });
describe('surveyAuthorizeTask', () => { describe('surveyAuthorizeTask', () => {
@ -243,7 +294,34 @@ describe('MessagePushingTaskService', () => {
$push: { $push: {
surveys: surveyId, surveys: surveyId,
}, },
$set: {
updatedAt: expect.any(Date),
}, },
},
);
});
it('should not add the surveyId if it already exists in the task', async () => {
const taskId = '65afc62904d5db18534c0f78';
const surveyId = '65af380475b64545e5277dd9';
const mockOwnerId = '66028642292c50f8b71a9eee';
jest
.spyOn(repository, 'updateOne')
.mockResolvedValue({ modifiedCount: 0 }); // 模拟重复添加
const result = await service.surveyAuthorizeTask({
taskId,
surveyId,
ownerId: mockOwnerId,
});
expect(result.modifiedCount).toBe(0);
expect(repository.updateOne).toHaveBeenCalledWith(
{
_id: new ObjectId(taskId),
surveys: { $nin: [surveyId] }, // 确保只有不包含时才插入
ownerId: mockOwnerId,
},
expect.any(Object),
); );
}); });
}); });

View File

@ -37,9 +37,4 @@ describe('UpdateMessagePushingTaskDto', () => {
dto.surveys = null; dto.surveys = null;
expect(dto.surveys).toBeNull(); expect(dto.surveys).toBeNull();
}); });
it('should have a nullable curStatus', () => {
dto.curStatus = null;
expect(dto.curStatus).toBeNull();
});
}); });

View File

@ -63,14 +63,14 @@ export class MessagePushingTaskService {
}); });
} }
async findOne({ findOne({
id, id,
ownerId, ownerId,
}: { }: {
id: string; id: string;
ownerId: string; ownerId: string;
}): Promise<MessagePushingTask> { }): Promise<MessagePushingTask> {
return await this.messagePushingTaskRepository.findOne({ return this.messagePushingTaskRepository.findOne({
where: { where: {
ownerId, ownerId,
_id: new ObjectId(id), _id: new ObjectId(id),

View File

@ -75,6 +75,25 @@ describe('CollaboratorService', () => {
}); });
}); });
describe('deleteCollaborator', () => {
it('should delete a collaborator by userId and surveyId', async () => {
const deleteOneSpy = jest
.spyOn(repository, 'deleteOne')
.mockResolvedValue({ acknowledged: true, deletedCount: 1 });
const result = await service.deleteCollaborator({
userId: '1',
surveyId: '1',
});
expect(deleteOneSpy).toHaveBeenCalledWith({
userId: '1',
surveyId: '1',
});
expect(result).toEqual({ acknowledged: true, deletedCount: 1 });
});
});
describe('batchCreate', () => { describe('batchCreate', () => {
it('should batch create collaborators', async () => { it('should batch create collaborators', async () => {
const insertManySpy = jest const insertManySpy = jest
@ -86,15 +105,193 @@ describe('CollaboratorService', () => {
const result = await service.batchCreate({ const result = await service.batchCreate({
surveyId: '1', surveyId: '1',
collaboratorList: [{ userId: '1', permissions: [] }], collaboratorList: [{ userId: '1', permissions: [] }],
creator: 'testCreator',
creatorId: 'testCreatorId',
}); });
expect(insertManySpy).toHaveBeenCalledWith([ expect(insertManySpy).toHaveBeenCalledWith([
{ surveyId: '1', userId: '1', permissions: [] }, {
userId: '1',
permissions: [],
surveyId: '1',
createdAt: expect.any(Date),
updatedAt: expect.any(Date),
creator: 'testCreator',
creatorId: 'testCreatorId',
},
]); ]);
expect(result).toEqual({ insertedCount: 1 }); expect(result).toEqual({ insertedCount: 1 });
}); });
}); });
describe('changeUserPermission', () => {
it("should update a user's permissions", async () => {
const updateOneSpy = jest
.spyOn(repository, 'updateOne')
.mockResolvedValue({});
const result = await service.changeUserPermission({
userId: '1',
surveyId: '1',
permission: 'read',
operator: 'testOperator',
operatorId: 'testOperatorId',
});
expect(updateOneSpy).toHaveBeenCalledWith(
{
surveyId: '1',
userId: '1',
},
{
$set: {
permission: 'read',
operator: 'testOperator',
operatorId: 'testOperatorId',
updatedAt: expect.any(Date),
},
},
);
expect(result).toEqual({});
});
});
describe('batchDelete', () => {
it('should batch delete collaborators', async () => {
const mockResult = { acknowledged: true, deletedCount: 1 };
const deleteManySpy = jest
.spyOn(repository, 'deleteMany')
.mockResolvedValue(mockResult);
const collaboratorId = new ObjectId().toString();
const result = await service.batchDelete({
surveyId: '1',
idList: [collaboratorId],
});
const expectedQuery = {
surveyId: '1',
$or: [
{
_id: {
$in: [new ObjectId(collaboratorId)],
},
},
],
};
expect(logger.info).toHaveBeenCalledWith(JSON.stringify(expectedQuery));
expect(deleteManySpy).toHaveBeenCalledWith(expectedQuery);
expect(result).toEqual(mockResult);
});
it('should batch delete collaborators by idList and userIdList', async () => {
const collaboratorId = new ObjectId().toString();
const deleteManySpy = jest
.spyOn(repository, 'deleteMany')
.mockResolvedValue({ acknowledged: true, deletedCount: 2 });
const result = await service.batchDelete({
idList: [collaboratorId],
userIdList: ['user1', 'user2'],
surveyId: '1',
});
const expectedQuery = {
surveyId: '1',
$or: [
{
userId: {
$in: ['user1', 'user2'],
},
},
{
_id: {
$in: [new ObjectId(collaboratorId)],
},
},
],
};
expect(deleteManySpy).toHaveBeenCalledWith(expectedQuery);
expect(result).toEqual({ acknowledged: true, deletedCount: 2 });
});
it('should handle batch delete with neIdList only', async () => {
const neCollaboratorId = new ObjectId().toString();
const deleteManySpy = jest
.spyOn(repository, 'deleteMany')
.mockResolvedValue({ acknowledged: true, deletedCount: 1 });
const result = await service.batchDelete({
neIdList: [neCollaboratorId],
surveyId: '1',
});
const expectedQuery = {
surveyId: '1',
$or: [
{
_id: {
$nin: [new ObjectId(neCollaboratorId)],
},
},
],
};
expect(deleteManySpy).toHaveBeenCalledWith(expectedQuery);
expect(result).toEqual({ acknowledged: true, deletedCount: 1 });
});
});
describe('batchDeleteBySurveyId', () => {
it('should batch delete collaborators by survey id', async () => {
const mockResult = { acknowledged: true, deletedCount: 1 };
const deleteManySpy = jest
.spyOn(repository, 'deleteMany')
.mockResolvedValue(mockResult);
const surveyId = new ObjectId().toString();
const result = await service.batchDeleteBySurveyId(surveyId);
expect(deleteManySpy).toHaveBeenCalledWith({
surveyId,
});
expect(result).toEqual(mockResult);
});
});
describe('updateById', () => {
it('should update collaborator by id', async () => {
const updateOneSpy = jest
.spyOn(repository, 'updateOne')
.mockResolvedValue({});
const collaboratorId = new ObjectId().toString();
const result = await service.updateById({
collaboratorId,
permissions: [],
operator: 'testOperator',
operatorId: 'testOperatorId',
});
expect(updateOneSpy).toHaveBeenCalledWith(
{
_id: new ObjectId(collaboratorId),
},
{
$set: {
permissions: [],
operator: 'testOperator',
operatorId: 'testOperatorId',
updatedAt: expect.any(Date),
},
},
);
expect(result).toEqual({});
});
});
describe('getSurveyCollaboratorList', () => { describe('getSurveyCollaboratorList', () => {
it('should return a list of collaborators for a survey', async () => { it('should return a list of collaborators for a survey', async () => {
const collaboratorId = new ObjectId().toString(); const collaboratorId = new ObjectId().toString();
@ -121,38 +318,6 @@ describe('CollaboratorService', () => {
}); });
}); });
describe('getCollaboratorListByIds', () => {
it('should return a list of collaborators by ids', async () => {
const collaboratorId = new ObjectId().toString();
const findSpy = jest.spyOn(repository, 'find').mockResolvedValue([
{
_id: new ObjectId(collaboratorId),
surveyId: '1',
userId: '1',
permissions: [],
},
] as Collaborator[]);
const result = await service.getCollaboratorListByIds({
idList: [collaboratorId],
});
expect(findSpy).toHaveBeenCalledWith({
_id: {
$in: [new ObjectId(collaboratorId)],
},
});
expect(result).toEqual([
{
_id: new ObjectId(collaboratorId),
surveyId: '1',
userId: '1',
permissions: [],
},
]);
});
});
describe('getCollaborator', () => { describe('getCollaborator', () => {
it('should return a collaborator', async () => { it('should return a collaborator', async () => {
const collaboratorId = new ObjectId().toString(); const collaboratorId = new ObjectId().toString();
@ -183,127 +348,6 @@ describe('CollaboratorService', () => {
}); });
}); });
describe('changeUserPermission', () => {
it("should update a user's permissions", async () => {
const updateOneSpy = jest
.spyOn(repository, 'updateOne')
.mockResolvedValue({});
const result = await service.changeUserPermission({
userId: '1',
surveyId: '1',
permission: 'read',
});
expect(updateOneSpy).toHaveBeenCalledWith(
{
surveyId: '1',
userId: '1',
},
{
$set: {
permission: 'read',
},
},
);
expect(result).toEqual({});
});
});
describe('deleteCollaborator', () => {
it('should delete a collaborator', async () => {
const mockResult = { acknowledged: true, deletedCount: 1 };
const deleteOneSpy = jest
.spyOn(repository, 'deleteOne')
.mockResolvedValue(mockResult);
const result = await service.deleteCollaborator({
userId: '1',
surveyId: '1',
});
expect(deleteOneSpy).toHaveBeenCalledWith({
userId: '1',
surveyId: '1',
});
expect(result).toEqual(mockResult);
});
});
describe('batchDelete', () => {
it('should batch delete collaborators', async () => {
const mockResult = { acknowledged: true, deletedCount: 1 };
const deleteManySpy = jest
.spyOn(repository, 'deleteMany')
.mockResolvedValue(mockResult);
const collaboratorId = new ObjectId().toString();
const result = await service.batchDelete({
surveyId: '1',
idList: [collaboratorId],
});
const expectedQuery = {
surveyId: '1',
$or: [
{
_id: {
$in: [new ObjectId(collaboratorId)],
},
},
],
};
expect(logger.info).toHaveBeenCalledWith(JSON.stringify(expectedQuery));
expect(deleteManySpy).toHaveBeenCalledWith(expectedQuery);
expect(result).toEqual(mockResult);
});
});
describe('batchDeleteBySurveyId', () => {
it('should batch delete collaborators by survey id', async () => {
const mockResult = { acknowledged: true, deletedCount: 1 };
const deleteManySpy = jest
.spyOn(repository, 'deleteMany')
.mockResolvedValue(mockResult);
const surveyId = new ObjectId().toString();
const result = await service.batchDeleteBySurveyId(surveyId);
expect(deleteManySpy).toHaveBeenCalledWith({
surveyId,
});
expect(result).toEqual(mockResult);
});
});
describe('updateById', () => {
it('should update collaborator by id', async () => {
const updateOneSpy = jest
.spyOn(repository, 'updateOne')
.mockResolvedValue({});
const collaboratorId = new ObjectId().toString();
const result = await service.updateById({
collaboratorId,
permissions: [],
});
expect(updateOneSpy).toHaveBeenCalledWith(
{
_id: new ObjectId(collaboratorId),
},
{
$set: {
permissions: [],
},
},
);
expect(result).toEqual({});
});
});
describe('getCollaboratorListByUserId', () => { describe('getCollaboratorListByUserId', () => {
it('should return a list of collaborators by user id', async () => { it('should return a list of collaborators by user id', async () => {
const userId = new ObjectId().toString(); const userId = new ObjectId().toString();
@ -327,5 +371,48 @@ describe('CollaboratorService', () => {
{ _id: '1', surveyId: '1', userId, permissions: [] }, { _id: '1', surveyId: '1', userId, permissions: [] },
]); ]);
}); });
it('should return a list of collaborators by their IDs', async () => {
const collaboratorId1 = new ObjectId().toString();
const collaboratorId2 = new ObjectId().toString();
const findSpy = jest.spyOn(repository, 'find').mockResolvedValue([
{
_id: new ObjectId(collaboratorId1),
surveyId: '1',
userId: 'user1',
permissions: [],
},
{
_id: new ObjectId(collaboratorId2),
surveyId: '2',
userId: 'user2',
permissions: [],
},
] as Collaborator[]);
const result = await service.getCollaboratorListByIds({
idList: [collaboratorId1, collaboratorId2],
});
expect(findSpy).toHaveBeenCalledWith({
_id: {
$in: [new ObjectId(collaboratorId1), new ObjectId(collaboratorId2)],
},
});
expect(result).toEqual([
{
_id: new ObjectId(collaboratorId1),
surveyId: '1',
userId: 'user1',
permissions: [],
},
{
_id: new ObjectId(collaboratorId2),
surveyId: '2',
userId: 'user2',
permissions: [],
},
]);
});
}); });
}); });

View File

@ -109,8 +109,8 @@ describe('DataStatisticController', () => {
}, },
], ],
listBody: [ listBody: [
{ diffTime: '0.5', createDate: '2024-02-11' }, { diffTime: '0.5', createdAt: '2024-02-11' },
{ diffTime: '0.5', createDate: '2024-02-11' }, { diffTime: '0.5', createdAt: '2024-02-11' },
], ],
}; };
@ -155,8 +155,8 @@ describe('DataStatisticController', () => {
}, },
], ],
listBody: [ listBody: [
{ diffTime: '0.5', createDate: '2024-02-11', data123: '15200000000' }, { diffTime: '0.5', createdAt: '2024-02-11', data123: '15200000000' },
{ diffTime: '0.5', createDate: '2024-02-11', data123: '13800000000' }, { diffTime: '0.5', createdAt: '2024-02-11', data123: '13800000000' },
], ],
}; };
@ -212,8 +212,8 @@ describe('DataStatisticController', () => {
date: 1717158851823, date: 1717158851823,
}, },
], ],
createDate: 1717158851823, createdAt: 1717158851823,
updateDate: 1717159136025, updatedAt: 1717159136025,
title: '问卷调研', title: '问卷调研',
surveyPath: 'ZdGNzTTR', surveyPath: 'ZdGNzTTR',
code: { code: {

View File

@ -151,8 +151,8 @@ describe('DataStatisticService', () => {
date: 1710340863123.0, date: 1710340863123.0,
}, },
], ],
createDate: 1710340863123.0, createdAt: 1710340863123.0,
updateDate: 1710340863123.0, updatedAt: 1710340863123.0,
}, },
] as unknown as Array<SurveyResponse>; ] as unknown as Array<SurveyResponse>;
@ -196,7 +196,7 @@ describe('DataStatisticService', () => {
data413: expect.any(Number), data413: expect.any(Number),
data863: expect.any(String), data863: expect.any(String),
diffTime: expect.any(String), diffTime: expect.any(String),
createDate: expect.any(String), createdAt: expect.any(String),
}), }),
]), ]),
}); });
@ -273,8 +273,8 @@ describe('DataStatisticService', () => {
date: 1710400232161.0, date: 1710400232161.0,
}, },
], ],
createDate: 1710400232161.0, createdAt: 1710400232161.0,
updateDate: 1710400232161.0, updatedAt: 1710400232161.0,
}, },
] as unknown as Array<SurveyResponse>; ] as unknown as Array<SurveyResponse>;
@ -295,7 +295,7 @@ describe('DataStatisticService', () => {
expect(result.listBody).toEqual( expect(result.listBody).toEqual(
expect.arrayContaining([ expect.arrayContaining([
expect.objectContaining({ expect.objectContaining({
createDate: expect.any(String), createdAt: expect.any(String),
data405: expect.any(String), data405: expect.any(String),
data450: expect.any(String), data450: expect.any(String),
data458: expect.any(String), data458: expect.any(String),

View File

@ -145,7 +145,7 @@ describe('DownloadTaskController', () => {
filename: 'mockFile.csv', filename: 'mockFile.csv',
url: 'http://mock-url.com', url: 'http://mock-url.com',
fileSize: 1024, fileSize: 1024,
createDate: Date.now(), createdAt: Date.now(),
}, },
], ],
}; };
@ -219,10 +219,13 @@ describe('DownloadTaskController', () => {
describe('deleteFileByName', () => { describe('deleteFileByName', () => {
it('should delete a download task successfully', async () => { it('should delete a download task successfully', async () => {
const mockBody = { taskId: 'mockTaskId' }; const mockBody = { taskId: 'mockTaskId' };
const mockReq = { user: { _id: 'mockUserId' } }; const mockUserId = new ObjectId();
const mockReq = {
user: { _id: mockUserId, username: 'mockUsername' },
};
const mockTaskInfo: any = { const mockTaskInfo: any = {
_id: new ObjectId(), _id: new ObjectId(),
creatorId: 'mockUserId', creatorId: mockUserId.toString(),
}; };
const mockDelRes = { modifiedCount: 1 }; const mockDelRes = { modifiedCount: 1 };
@ -237,6 +240,8 @@ describe('DownloadTaskController', () => {
expect(downloadTaskService.deleteDownloadTask).toHaveBeenCalledWith({ expect(downloadTaskService.deleteDownloadTask).toHaveBeenCalledWith({
taskId: mockBody.taskId, taskId: mockBody.taskId,
operator: mockReq.user.username,
operatorId: mockReq.user._id.toString(),
}); });
expect(result).toEqual({ code: 200, data: true }); expect(result).toEqual({ code: 200, data: true });
}); });

View File

@ -9,7 +9,7 @@ import { DataStatisticService } from '../services/dataStatistic.service';
import { FileService } from 'src/modules/file/services/file.service'; import { FileService } from 'src/modules/file/services/file.service';
import { Logger } from 'src/logger'; import { Logger } from 'src/logger';
import { ObjectId } from 'mongodb'; import { ObjectId } from 'mongodb';
import { RECORD_STATUS } from 'src/enums'; import { DOWNLOAD_TASK_STATUS } from 'src/enums/downloadTaskStatus';
describe('DownloadTaskService', () => { describe('DownloadTaskService', () => {
let service: DownloadTaskService; let service: DownloadTaskService;
@ -93,6 +93,7 @@ describe('DownloadTaskService', () => {
title: mockParams.responseSchema.title, title: mockParams.responseSchema.title,
}, },
filename: expect.any(String), filename: expect.any(String),
status: DOWNLOAD_TASK_STATUS.WAITING,
}); });
expect(downloadTaskRepository.save).toHaveBeenCalled(); expect(downloadTaskRepository.save).toHaveBeenCalled();
expect(result).toEqual(mockTaskId); expect(result).toEqual(mockTaskId);
@ -118,10 +119,11 @@ describe('DownloadTaskService', () => {
expect(downloadTaskRepository.findAndCount).toHaveBeenCalledWith({ expect(downloadTaskRepository.findAndCount).toHaveBeenCalledWith({
where: { where: {
creatorId: mockCreatorId, creatorId: mockCreatorId,
isDeleted: { $ne: true },
}, },
take: 10, take: 10,
skip: 0, skip: 0,
order: { createDate: -1 }, order: { createdAt: -1 },
}); });
expect(result).toEqual({ expect(result).toEqual({
@ -160,32 +162,84 @@ describe('DownloadTaskService', () => {
}); });
describe('deleteDownloadTask', () => { describe('deleteDownloadTask', () => {
it('should update task status to REMOVED', async () => { it('should mark task as deleted and set deletedAt', async () => {
const mockTaskId = new ObjectId().toString(); const mockTaskId = new ObjectId().toString();
const mockOperator = 'operatorName';
const mockOperatorId = 'operatorId1';
const mockUpdateResult = { matchedCount: 1 }; const mockUpdateResult = { matchedCount: 1 };
jest jest
.spyOn(downloadTaskRepository, 'updateOne') .spyOn(downloadTaskRepository, 'updateOne')
.mockResolvedValue(mockUpdateResult as any); .mockResolvedValue(mockUpdateResult as any);
const result = await service.deleteDownloadTask({ taskId: mockTaskId }); const result = await service.deleteDownloadTask({
taskId: mockTaskId,
operator: mockOperator,
operatorId: mockOperatorId,
});
expect(downloadTaskRepository.updateOne).toHaveBeenCalledWith( expect(downloadTaskRepository.updateOne).toHaveBeenCalledWith(
{ { _id: new ObjectId(mockTaskId) },
_id: new ObjectId(mockTaskId),
'curStatus.status': { $ne: RECORD_STATUS.REMOVED },
},
{ {
$set: { $set: {
curStatus: { isDeleted: true,
status: RECORD_STATUS.REMOVED, operator: mockOperator,
date: expect.any(Number), operatorId: mockOperatorId,
deletedAt: expect.any(Date),
}, },
}, },
$push: { statusList: expect.any(Object) },
},
); );
expect(result).toEqual(mockUpdateResult); expect(result).toEqual(mockUpdateResult);
}); });
}); });
describe('processDownloadTask', () => {
it('should push task to queue and execute if not executing', async () => {
const mockTaskId = new ObjectId().toString();
jest.spyOn(service, 'executeTask').mockImplementation(jest.fn());
service.processDownloadTask({ taskId: mockTaskId });
expect(DownloadTaskService.taskList).toContain(mockTaskId);
expect(service.executeTask).toHaveBeenCalled();
});
it('should handle already executing case', async () => {
const mockTaskId = new ObjectId().toString();
DownloadTaskService.isExecuting = true;
jest.spyOn(service, 'executeTask').mockImplementation(jest.fn());
service.processDownloadTask({ taskId: mockTaskId });
expect(DownloadTaskService.taskList).toContain(mockTaskId);
expect(service.executeTask).not.toHaveBeenCalled();
});
});
describe('executeTask', () => {
it('should process and execute tasks in queue', async () => {
const mockTaskId = new ObjectId().toString();
DownloadTaskService.taskList.push(mockTaskId);
jest.spyOn(service, 'getDownloadTaskById').mockResolvedValue({
_id: new ObjectId(mockTaskId),
isDeleted: false,
} as any);
jest.spyOn(service, 'handleDownloadTask').mockResolvedValue(undefined);
await service.executeTask();
expect(service.getDownloadTaskById).toHaveBeenCalledWith({
taskId: mockTaskId,
});
expect(service.handleDownloadTask).toHaveBeenCalled();
});
it('should stop executing when queue is empty', async () => {
DownloadTaskService.taskList = [];
await service.executeTask();
expect(DownloadTaskService.isExecuting).toBe(false);
});
});
}); });

View File

@ -14,8 +14,8 @@ export const mockSensitiveResponseSchema: ResponseSchema = {
date: 1710399368439, date: 1710399368439,
}, },
], ],
createDate: 1710399368440, createdAt: 1710399368440,
updateDate: 1710399368440, updatedAt: 1710399368440,
title: '加密全流程', title: '加密全流程',
surveyPath: 'EBzdmnSp', surveyPath: 'EBzdmnSp',
code: { code: {
@ -654,6 +654,6 @@ export const mockResponseSchema: ResponseSchema = {
}, },
}, },
pageId: '65afc62904d5db18534c0f78', pageId: '65afc62904d5db18534c0f78',
createDate: 1710340841289, createdAt: 1710340841289,
updateDate: 1710340841289.0, updatedAt: 1710340841289.0,
} as unknown as ResponseSchema; } as unknown as ResponseSchema;

View File

@ -0,0 +1,144 @@
import { Test, TestingModule } from '@nestjs/testing';
import { MongoRepository } from 'typeorm';
import { getRepositoryToken } from '@nestjs/typeorm';
import { SessionService } from '../services/session.service';
import { Session } from 'src/models/session.entity';
import { ObjectId } from 'mongodb';
import { SESSION_STATUS } from 'src/enums/surveySessionStatus';
describe('SessionService', () => {
let service: SessionService;
let repository: MongoRepository<Session>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
SessionService,
{
provide: getRepositoryToken(Session),
useClass: MongoRepository,
},
],
}).compile();
service = module.get<SessionService>(SessionService);
repository = module.get<MongoRepository<Session>>(
getRepositoryToken(Session),
);
});
afterEach(() => {
jest.clearAllMocks();
});
describe('create', () => {
it('should create and save a new session', async () => {
const mockSession = {
surveyId: 'survey123',
userId: 'user123',
status: SESSION_STATUS.DEACTIVATED,
};
const createdSession: any = { ...mockSession, _id: new ObjectId() };
jest.spyOn(repository, 'create').mockReturnValue(createdSession);
jest.spyOn(repository, 'save').mockResolvedValue(createdSession);
const result = await service.create({
surveyId: mockSession.surveyId,
userId: mockSession.userId,
});
expect(result).toEqual(createdSession);
expect(repository.create).toHaveBeenCalledWith(mockSession);
expect(repository.save).toHaveBeenCalledWith(createdSession);
});
});
describe('findOne', () => {
it('should find a session by id', async () => {
const sessionId = '65afc62904d5db18534c0f78';
const foundSession = {
_id: new ObjectId(sessionId),
surveyId: 'survey123',
userId: 'user123',
status: SESSION_STATUS.ACTIVATED,
};
jest
.spyOn(repository, 'findOne')
.mockResolvedValue(foundSession as Session);
const result = await service.findOne(sessionId);
expect(result).toEqual(foundSession);
expect(repository.findOne).toHaveBeenCalledWith({
where: { _id: new ObjectId(sessionId) },
});
});
});
describe('findLatestEditingOne', () => {
it('should find the latest editing session for a survey', async () => {
const surveyId = 'survey123';
const latestSession = {
_id: new ObjectId(),
surveyId: surveyId,
userId: 'user123',
status: SESSION_STATUS.ACTIVATED,
};
jest
.spyOn(repository, 'findOne')
.mockResolvedValue(latestSession as Session);
const result = await service.findLatestEditingOne({ surveyId });
expect(result).toEqual(latestSession);
expect(repository.findOne).toHaveBeenCalledWith({
where: {
surveyId,
status: SESSION_STATUS.ACTIVATED,
},
});
});
});
describe('updateSessionToEditing', () => {
it('should update a session to editing and deactivate other sessions', async () => {
const sessionId = '65afc62904d5db18534c0f78';
const surveyId = 'survey123';
const updateResult: any = { affected: 1 };
const updateManyResult = { modifiedCount: 1 };
jest.spyOn(repository, 'update').mockResolvedValue(updateResult);
jest.spyOn(repository, 'updateMany').mockResolvedValue(updateManyResult);
const result = await service.updateSessionToEditing({
sessionId,
surveyId,
});
expect(result).toEqual([updateResult, updateManyResult]);
expect(repository.update).toHaveBeenCalledWith(
{ _id: new ObjectId(sessionId) },
{
status: SESSION_STATUS.ACTIVATED,
updatedAt: expect.any(Date),
},
);
expect(repository.updateMany).toHaveBeenCalledWith(
{
surveyId,
_id: { $ne: new ObjectId(sessionId) },
},
{
$set: {
status: SESSION_STATUS.DEACTIVATED,
updatedAt: expect.any(Date),
},
},
);
});
});
});

View File

@ -5,13 +5,12 @@ import { SurveyConfService } from '../services/surveyConf.service';
import { ResponseSchemaService } from '../../surveyResponse/services/responseScheme.service'; import { ResponseSchemaService } from '../../surveyResponse/services/responseScheme.service';
import { ContentSecurityService } from '../services/contentSecurity.service'; import { ContentSecurityService } from '../services/contentSecurity.service';
import { SurveyHistoryService } from '../services/surveyHistory.service'; import { SurveyHistoryService } from '../services/surveyHistory.service';
import { CounterService } from '../../surveyResponse/services/counter.service';
import { SessionService } from '../services/session.service'; import { SessionService } from '../services/session.service';
import { UserService } from '../../auth/services/user.service'; import { UserService } from '../../auth/services/user.service';
import { ObjectId } from 'mongodb'; import { ObjectId } from 'mongodb';
import { SurveyMeta } from 'src/models/surveyMeta.entity';
import { SurveyConf } from 'src/models/surveyConf.entity';
import { Logger } from 'src/logger'; import { Logger } from 'src/logger';
import { HttpException } from 'src/exceptions/httpException';
import { Authentication } from 'src/guards/authentication.guard';
jest.mock('../services/surveyMeta.service'); jest.mock('../services/surveyMeta.service');
jest.mock('../services/surveyConf.service'); jest.mock('../services/surveyConf.service');
@ -19,9 +18,7 @@ jest.mock('../../surveyResponse/services/responseScheme.service');
jest.mock('../services/contentSecurity.service'); jest.mock('../services/contentSecurity.service');
jest.mock('../services/surveyHistory.service'); jest.mock('../services/surveyHistory.service');
jest.mock('../services/session.service'); jest.mock('../services/session.service');
jest.mock('../../surveyResponse/services/counter.service');
jest.mock('../../auth/services/user.service'); jest.mock('../../auth/services/user.service');
jest.mock('src/guards/authentication.guard'); jest.mock('src/guards/authentication.guard');
jest.mock('src/guards/survey.guard'); jest.mock('src/guards/survey.guard');
jest.mock('src/guards/workspace.guard'); jest.mock('src/guards/workspace.guard');
@ -31,28 +28,17 @@ describe('SurveyController', () => {
let surveyMetaService: SurveyMetaService; let surveyMetaService: SurveyMetaService;
let surveyConfService: SurveyConfService; let surveyConfService: SurveyConfService;
let responseSchemaService: ResponseSchemaService; let responseSchemaService: ResponseSchemaService;
let surveyHistoryService: SurveyHistoryService;
let sessionService: SessionService;
beforeEach(async () => { beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({ const module: TestingModule = await Test.createTestingModule({
controllers: [SurveyController], controllers: [SurveyController],
providers: [ providers: [
SurveyMetaService, SurveyMetaService,
{ SurveyConfService,
provide: SurveyConfService,
useValue: {
getSurveyConfBySurveyId: jest.fn(),
getSurveyContentByCode: jest.fn(),
createSurveyConf: jest.fn(),
saveSurveyConf: jest.fn(),
},
},
ResponseSchemaService, ResponseSchemaService,
ContentSecurityService, ContentSecurityService,
SurveyHistoryService, SurveyHistoryService,
SessionService, SessionService,
CounterService,
UserService, UserService,
{ {
provide: Logger, provide: Logger,
@ -61,6 +47,12 @@ describe('SurveyController', () => {
info: jest.fn(), info: jest.fn(),
}, },
}, },
{
provide: Authentication,
useClass: jest.fn().mockImplementation(() => ({
canActivate: () => true,
})),
},
], ],
}).compile(); }).compile();
@ -70,9 +62,6 @@ describe('SurveyController', () => {
responseSchemaService = module.get<ResponseSchemaService>( responseSchemaService = module.get<ResponseSchemaService>(
ResponseSchemaService, ResponseSchemaService,
); );
surveyHistoryService =
module.get<SurveyHistoryService>(SurveyHistoryService);
sessionService = module.get<SessionService>(SessionService);
}); });
describe('getBannerData', () => { describe('getBannerData', () => {
@ -94,12 +83,11 @@ describe('SurveyController', () => {
const newId = new ObjectId(); const newId = new ObjectId();
jest.spyOn(surveyMetaService, 'createSurveyMeta').mockResolvedValue({ jest.spyOn(surveyMetaService, 'createSurveyMeta').mockResolvedValue({
_id: newId, _id: newId,
} as SurveyMeta); } as any);
jest.spyOn(surveyConfService, 'createSurveyConf').mockResolvedValue({ jest.spyOn(surveyConfService, 'createSurveyConf').mockResolvedValue({
_id: new ObjectId(), _id: new ObjectId(),
pageId: newId.toString(), } as any);
} as SurveyConf);
const result = await controller.createSurvey(surveyInfo, { const result = await controller.createSurvey(surveyInfo, {
user: { username: 'testUser', _id: new ObjectId() }, user: { username: 'testUser', _id: new ObjectId() },
@ -113,13 +101,15 @@ describe('SurveyController', () => {
}); });
}); });
it('should throw an error if validation fails', async () => {
const surveyInfo = {}; // Invalid data
await expect(
controller.createSurvey(surveyInfo as any, { user: {} }),
).rejects.toThrow(HttpException);
});
it('should create a new survey by copy', async () => { it('should create a new survey by copy', async () => {
const existsSurveyId = new ObjectId(); const existsSurveyId = new ObjectId();
const existsSurveyMeta = {
_id: existsSurveyId,
surveyType: 'exam',
owner: 'testUser',
} as SurveyMeta;
const params = { const params = {
surveyType: 'normal', surveyType: 'normal',
remark: '问卷调研', remark: '问卷调研',
@ -128,15 +118,15 @@ describe('SurveyController', () => {
createFrom: existsSurveyId.toString(), createFrom: existsSurveyId.toString(),
}; };
jest.spyOn(surveyMetaService, 'createSurveyMeta').mockResolvedValue({
_id: new ObjectId(),
} as SurveyMeta);
const request = { const request = {
user: { username: 'testUser', _id: new ObjectId() }, user: { username: 'testUser', _id: new ObjectId() },
surveyMeta: existsSurveyMeta, surveyMeta: { _id: existsSurveyId, surveyType: 'exam' },
}; };
jest.spyOn(surveyMetaService, 'createSurveyMeta').mockResolvedValue({
_id: new ObjectId(),
} as any);
const result = await controller.createSurvey(params, request); const result = await controller.createSurvey(params, request);
expect(result?.data?.id).toBeDefined(); expect(result?.data?.id).toBeDefined();
}); });
@ -145,69 +135,30 @@ describe('SurveyController', () => {
describe('updateConf', () => { describe('updateConf', () => {
it('should update survey configuration', async () => { it('should update survey configuration', async () => {
const surveyId = new ObjectId(); const surveyId = new ObjectId();
const surveyMeta = {
_id: surveyId,
surveyType: 'exam',
owner: 'testUser',
} as SurveyMeta;
jest
.spyOn(surveyConfService, 'saveSurveyConf')
.mockResolvedValue(undefined);
jest
.spyOn(surveyHistoryService, 'addHistory')
.mockResolvedValue(undefined);
jest
.spyOn(sessionService, 'findLatestEditingOne')
.mockResolvedValue(null);
jest
.spyOn(sessionService, 'updateSessionToEditing')
.mockResolvedValue(undefined);
const reqBody = { const reqBody = {
surveyId: surveyId.toString(), surveyId: surveyId.toString(),
configData: { configData: {
bannerConf: { /* ... your config data here ... */
titleConfig: {},
bannerConfig: {},
},
baseConf: {
beginTime: '2024-01-23 21:59:05',
endTime: '2034-01-23 21:59:05',
},
bottomConf: { logoImage: '/imgs/Logo.webp', logoImageWidth: '60%' },
skinConf: {
skinColor: '#4a4c5b',
inputBgColor: '#ffffff',
backgroundConf: {
color: '#fff',
type: 'color',
image: '',
},
themeConf: {
color: '#ffa600',
},
contentConf: {
opacity: 100,
},
},
submitConf: {},
dataConf: {
dataList: [],
},
}, },
sessionId: 'mock-session-id', sessionId: 'mock-session-id',
}; };
const result = await controller.updateConf(reqBody, { const result = await controller.updateConf(reqBody, {
user: { username: 'testUser', _id: 'testUserId' }, user: { username: 'testUser', _id: 'testUserId' },
surveyMeta, surveyMeta: { _id: surveyId },
}); });
expect(result).toEqual({ expect(result).toEqual({
code: 200, code: 200,
}); });
}); });
it('should throw an error if validation fails', async () => {
const reqBody = {}; // Invalid data
await expect(
controller.updateConf(reqBody, { user: {} }),
).rejects.toThrow(HttpException);
});
}); });
describe('deleteSurvey', () => { describe('deleteSurvey', () => {
@ -217,7 +168,7 @@ describe('SurveyController', () => {
_id: surveyId, _id: surveyId,
surveyType: 'exam', surveyType: 'exam',
owner: 'testUser', owner: 'testUser',
} as SurveyMeta; };
jest jest
.spyOn(surveyMetaService, 'deleteSurveyMeta') .spyOn(surveyMetaService, 'deleteSurveyMeta')
@ -227,13 +178,10 @@ describe('SurveyController', () => {
.mockResolvedValue(undefined); .mockResolvedValue(undefined);
const result = await controller.deleteSurvey({ const result = await controller.deleteSurvey({
user: { username: 'testUser' },
surveyMeta, surveyMeta,
user: { username: 'testUser', _id: new ObjectId() },
}); });
expect(result).toEqual({ code: 200 });
expect(result).toEqual({
code: 200,
});
}); });
}); });
@ -244,23 +192,19 @@ describe('SurveyController', () => {
_id: surveyId, _id: surveyId,
surveyType: 'exam', surveyType: 'exam',
owner: 'testUser', owner: 'testUser',
} as SurveyMeta; };
jest jest
.spyOn(surveyConfService, 'getSurveyConfBySurveyId') .spyOn(surveyConfService, 'getSurveyConfBySurveyId')
.mockResolvedValue({ .mockResolvedValue({} as any);
_id: new ObjectId(),
pageId: surveyId.toString(),
} as SurveyConf);
const request = {
user: { username: 'testUser', _id: new ObjectId() },
surveyMeta,
};
const result = await controller.getSurvey( const result = await controller.getSurvey(
{ surveyId: surveyId.toString() }, { surveyId: surveyId.toString() },
request, {
surveyMeta,
user: { username: 'testUser', _id: new ObjectId() },
},
); );
expect(result?.data?.surveyMetaRes).toBeDefined(); expect(result?.data?.surveyMetaRes).toBeDefined();
expect(result?.data?.surveyConfRes).toBeDefined(); expect(result?.data?.surveyConfRes).toBeDefined();
}); });
@ -273,28 +217,77 @@ describe('SurveyController', () => {
_id: surveyId, _id: surveyId,
surveyType: 'exam', surveyType: 'exam',
owner: 'testUser', owner: 'testUser',
} as SurveyMeta; isDeleted: false,
};
jest jest
.spyOn(surveyConfService, 'getSurveyConfBySurveyId') .spyOn(surveyConfService, 'getSurveyConfBySurveyId')
.mockResolvedValue({ .mockResolvedValue({
_id: new ObjectId(),
pageId: surveyId.toString(),
code: {}, code: {},
} as SurveyConf); } as any);
jest jest
.spyOn(surveyConfService, 'getSurveyContentByCode') .spyOn(surveyConfService, 'getSurveyContentByCode')
.mockResolvedValue({ text: '' }); .mockResolvedValue({ text: '' });
jest
.spyOn(surveyMetaService, 'publishSurveyMeta')
.mockResolvedValue(undefined);
const result = await controller.publishSurvey( const result = await controller.publishSurvey(
{ surveyId: surveyId.toString() }, { surveyId: surveyId.toString() },
{ { surveyMeta, user: { username: 'testUser', _id: new ObjectId() } },
user: { username: 'testUser', _id: new ObjectId() },
surveyMeta,
},
); );
expect(result.code).toBe(200); expect(result.code).toBe(200);
}); });
it('should throw an error if the survey is deleted', async () => {
const surveyId = new ObjectId();
const surveyMeta = { _id: surveyId, isDeleted: true };
await expect(
controller.publishSurvey(
{ surveyId: surveyId.toString() },
{ surveyMeta, user: { username: 'testUser' } },
),
).rejects.toThrow(HttpException);
});
});
// New tests for additional methods
describe('pausingSurvey', () => {
it('should pause the survey successfully', async () => {
const surveyMeta = { surveyPath: 'some/path' };
jest
.spyOn(surveyMetaService, 'pausingSurveyMeta')
.mockResolvedValue(undefined);
jest
.spyOn(responseSchemaService, 'pausingResponseSchema')
.mockResolvedValue(undefined);
const result = await controller.pausingSurvey({
surveyMeta,
user: { username: 'testUser' },
});
expect(result.code).toBe(200);
});
});
describe('getPreviewSchema', () => {
it('should get the preview schema successfully', async () => {
const surveyId = new ObjectId();
jest
.spyOn(surveyConfService, 'getSurveyConfBySurveyId')
.mockResolvedValue({} as any);
jest.spyOn(surveyMetaService, 'getSurveyById').mockResolvedValue({
title: 'Test Survey',
surveyPath: 'some/path',
} as any);
const result = await controller.getPreviewSchema({
surveyPath: surveyId.toString(),
});
expect(result.code).toBe(200);
});
}); });
}); });

View File

@ -121,9 +121,9 @@ describe('SurveyHistoryService', () => {
}, },
take: 100, take: 100,
order: { order: {
createDate: -1, createdAt: -1,
}, },
select: ['createDate', 'operator', 'type', '_id'], select: ['createdAt', 'operator', 'type', '_id'],
}); });
}); });
}); });

View File

@ -59,18 +59,25 @@ describe('SurveyMetaController', () => {
remark: '', remark: '',
}; };
const req = { const mockUser = {
user: {
username: 'test-user', username: 'test-user',
}, _id: new ObjectId(),
};
const req = {
user: mockUser,
surveyMeta: survey, surveyMeta: survey,
}; };
const result = await controller.updateMeta(reqBody, req); const result = await controller.updateMeta(reqBody, req);
expect(surveyMetaService.editSurveyMeta).toHaveBeenCalledWith({ expect(surveyMetaService.editSurveyMeta).toHaveBeenCalledWith({
operator: mockUser.username,
operatorId: mockUser._id.toString(),
survey: {
title: reqBody.title, title: reqBody.title,
remark: reqBody.remark, remark: reqBody.remark,
},
}); });
expect(result).toEqual({ code: 200 }); expect(result).toEqual({ code: 200 });
@ -116,8 +123,8 @@ describe('SurveyMetaController', () => {
data: [ data: [
{ {
_id: new ObjectId(), _id: new ObjectId(),
createDate: date, createdAt: date,
updateDate: date, updatedAt: date,
curStatus: { curStatus: {
date: date, date: date,
}, },
@ -138,7 +145,7 @@ describe('SurveyMetaController', () => {
count: 10, count: 10,
data: expect.arrayContaining([ data: expect.arrayContaining([
expect.objectContaining({ expect.objectContaining({
createDate: expect.stringMatching( createdAt: expect.stringMatching(
/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/, /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/,
), ),
curStatus: expect.objectContaining({ curStatus: expect.objectContaining({
@ -183,7 +190,7 @@ describe('SurveyMetaController', () => {
condition: [{ field: 'surveyType', value: 'normal' }], condition: [{ field: 'surveyType', value: 'normal' }],
}, },
]), ]),
order: JSON.stringify([{ field: 'createDate', value: -1 }]), order: JSON.stringify([{ field: 'createdAt', value: -1 }]),
}; };
const userId = new ObjectId().toString(); const userId = new ObjectId().toString();
const req = { const req = {
@ -203,7 +210,7 @@ describe('SurveyMetaController', () => {
surveyIdList: [], surveyIdList: [],
userId, userId,
filter: { surveyType: 'normal', title: { $regex: 'hahah' } }, filter: { surveyType: 'normal', title: { $regex: 'hahah' } },
order: { createDate: -1 }, order: { createdAt: -1 },
workspaceId: undefined, workspaceId: undefined,
}); });
}); });

View File

@ -2,12 +2,10 @@ import { Test, TestingModule } from '@nestjs/testing';
import { SurveyMetaService } from '../services/surveyMeta.service'; import { SurveyMetaService } from '../services/surveyMeta.service';
import { MongoRepository } from 'typeorm'; import { MongoRepository } from 'typeorm';
import { SurveyMeta } from 'src/models/surveyMeta.entity'; import { SurveyMeta } from 'src/models/surveyMeta.entity';
import { PluginManagerProvider } from 'src/securityPlugin/pluginManager.provider';
import { PluginManager } from 'src/securityPlugin/pluginManager'; import { PluginManager } from 'src/securityPlugin/pluginManager';
import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums';
import { getRepositoryToken } from '@nestjs/typeorm'; import { getRepositoryToken } from '@nestjs/typeorm';
import { HttpException } from 'src/exceptions/httpException'; import { HttpException } from 'src/exceptions/httpException';
import { SurveyUtilPlugin } from 'src/securityPlugin/surveyUtilPlugin'; import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums';
import { ObjectId } from 'mongodb'; import { ObjectId } from 'mongodb';
describe('SurveyMetaService', () => { describe('SurveyMetaService', () => {
@ -26,10 +24,11 @@ describe('SurveyMetaService', () => {
count: jest.fn(), count: jest.fn(),
create: jest.fn(), create: jest.fn(),
save: jest.fn(), save: jest.fn(),
updateOne: jest.fn(),
findAndCount: jest.fn(), findAndCount: jest.fn(),
}, },
}, },
PluginManagerProvider, PluginManager,
], ],
}).compile(); }).compile();
@ -38,18 +37,18 @@ describe('SurveyMetaService', () => {
getRepositoryToken(SurveyMeta), getRepositoryToken(SurveyMeta),
); );
pluginManager = module.get<PluginManager>(PluginManager); pluginManager = module.get<PluginManager>(PluginManager);
pluginManager.registerPlugin(new SurveyUtilPlugin());
}); });
describe('getNewSurveyPath', () => { describe('getNewSurveyPath', () => {
it('should generate a new survey path', async () => { it('should generate a new survey path', async () => {
jest.spyOn(surveyRepository, 'count').mockResolvedValueOnce(1); jest.spyOn(pluginManager, 'triggerHook').mockResolvedValueOnce('path1');
jest.spyOn(surveyRepository, 'count').mockResolvedValueOnce(0); jest.spyOn(surveyRepository, 'count').mockResolvedValueOnce(0);
const surveyPath = await service.getNewSurveyPath(); const surveyPath = await service.getNewSurveyPath();
expect(typeof surveyPath).toBe('string'); expect(surveyPath).toBe('path1');
expect(surveyRepository.count).toHaveBeenCalledTimes(2); expect(pluginManager.triggerHook).toHaveBeenCalledTimes(1);
expect(surveyRepository.count).toHaveBeenCalledTimes(1);
}); });
}); });
@ -63,14 +62,11 @@ describe('SurveyMetaService', () => {
userId: new ObjectId().toString(), userId: new ObjectId().toString(),
createMethod: '', createMethod: '',
createFrom: '', createFrom: '',
workspaceId: 'workspace1',
}; };
const newSurvey = new SurveyMeta(); const newSurvey = new SurveyMeta();
const mockedSurveyPath = 'mockedSurveyPath'; jest.spyOn(service, 'getNewSurveyPath').mockResolvedValue('path1');
jest
.spyOn(service, 'getNewSurveyPath')
.mockResolvedValue(mockedSurveyPath);
jest jest
.spyOn(surveyRepository, 'create') .spyOn(surveyRepository, 'create')
.mockImplementation(() => newSurvey); .mockImplementation(() => newSurvey);
@ -82,97 +78,118 @@ describe('SurveyMetaService', () => {
title: params.title, title: params.title,
remark: params.remark, remark: params.remark,
surveyType: params.surveyType, surveyType: params.surveyType,
surveyPath: mockedSurveyPath, surveyPath: 'path1',
creator: params.username, creator: params.username,
ownerId: params.userId, creatorId: params.userId,
owner: params.username, owner: params.username,
ownerId: params.userId,
createMethod: params.createMethod, createMethod: params.createMethod,
createFrom: params.createFrom, createFrom: params.createFrom,
workspaceId: params.workspaceId,
}); });
expect(surveyRepository.save).toHaveBeenCalledWith(newSurvey); expect(surveyRepository.save).toHaveBeenCalledWith(newSurvey);
expect(result).toEqual(newSurvey); expect(result).toEqual(newSurvey);
}); });
}); });
describe('editSurveyMeta', () => { describe('pausingSurveyMeta', () => {
it('should edit a survey meta and return it if in NEW or EDITING status', async () => { it('should throw an exception if survey is in NEW status', async () => {
const survey = new SurveyMeta();
survey.curStatus = { status: RECORD_STATUS.NEW, date: Date.now() };
await expect(service.pausingSurveyMeta(survey)).rejects.toThrow(
HttpException,
);
});
it('should pause a survey and update subStatus', async () => {
const survey = new SurveyMeta(); const survey = new SurveyMeta();
survey.curStatus = { status: RECORD_STATUS.PUBLISHED, date: Date.now() }; survey.curStatus = { status: RECORD_STATUS.PUBLISHED, date: Date.now() };
survey.subStatus = {
status: RECORD_SUB_STATUS.DEFAULT,
date: Date.now(),
};
survey.statusList = []; survey.statusList = [];
jest.spyOn(surveyRepository, 'save').mockResolvedValue(survey); jest.spyOn(surveyRepository, 'save').mockResolvedValue(survey);
const result = await service.editSurveyMeta(survey); const result = await service.pausingSurveyMeta(survey);
expect(survey.curStatus.status).toEqual(RECORD_STATUS.EDITING); expect(survey.subStatus.status).toBe(RECORD_SUB_STATUS.PAUSING);
expect(survey.statusList.length).toBe(1); expect(survey.statusList.length).toBe(1);
expect(survey.statusList[0].status).toEqual(RECORD_STATUS.EDITING); expect(survey.statusList[0].status).toBe(RECORD_SUB_STATUS.PAUSING);
expect(surveyRepository.save).toHaveBeenCalledWith(survey);
expect(result).toEqual(survey);
});
});
describe('editSurveyMeta', () => {
it('should edit a survey meta and return it', async () => {
const survey = new SurveyMeta();
survey.curStatus = { status: RECORD_STATUS.PUBLISHED, date: Date.now() };
survey.statusList = [];
const operator = 'editor';
const operatorId = 'editorId';
jest.spyOn(surveyRepository, 'save').mockResolvedValue(survey);
const result = await service.editSurveyMeta({
survey,
operator,
operatorId,
});
expect(survey.curStatus.status).toBe(RECORD_STATUS.EDITING);
expect(survey.statusList.length).toBe(1);
expect(survey.statusList[0].status).toBe(RECORD_STATUS.EDITING);
expect(survey.operator).toBe(operator);
expect(survey.operatorId).toBe(operatorId);
expect(surveyRepository.save).toHaveBeenCalledWith(survey); expect(surveyRepository.save).toHaveBeenCalledWith(survey);
expect(result).toEqual(survey); expect(result).toEqual(survey);
}); });
}); });
describe('deleteSurveyMeta', () => { describe('deleteSurveyMeta', () => {
it('should delete survey meta and update status', async () => { it('should mark a survey as deleted', async () => {
// 准备假的SurveyMeta对象 const surveyId = new ObjectId().toString();
const survey = new SurveyMeta(); const operator = 'deleter';
survey.curStatus = { status: RECORD_STATUS.NEW, date: Date.now() }; const operatorId = 'deleterId';
survey.subStatus = {
status: RECORD_SUB_STATUS.DEFAULT,
date: Date.now(),
};
survey.statusList = [];
// 模拟save方法 jest.spyOn(surveyRepository, 'updateOne').mockResolvedValue({
jest.spyOn(surveyRepository, 'save').mockResolvedValue(survey); matchedCount: 1,
modifiedCount: 1,
// 调用要测试的方法 acknowledged: true,
const result = await service.deleteSurveyMeta(survey);
// 验证结果
expect(result).toBe(survey);
expect(survey.subStatus.status).toBe(RECORD_STATUS.REMOVED);
expect(survey.statusList.length).toBe(1);
expect(survey.statusList[0].status).toBe(RECORD_STATUS.REMOVED);
expect(surveyRepository.save).toHaveBeenCalledTimes(1);
expect(surveyRepository.save).toHaveBeenCalledWith(survey);
}); });
it('should throw exception when survey is already removed', async () => { const result = await service.deleteSurveyMeta({
// 准备假的SurveyMeta对象其状态已设置为REMOVED surveyId,
const survey = new SurveyMeta(); operator,
survey.curStatus = { operatorId,
status: RECORD_STATUS.REMOVED, });
date: Date.now(),
};
// 调用要测试的方法并期待异常 expect(surveyRepository.updateOne).toHaveBeenCalledWith(
await expect(service.deleteSurveyMeta(survey)).rejects.toThrow( { _id: new ObjectId(surveyId) },
HttpException, {
$set: {
isDeleted: true,
operator,
operatorId,
deletedAt: expect.any(Date),
},
},
); );
expect(result.matchedCount).toBe(1);
// 验证save方法没有被调用
expect(surveyRepository.save).not.toHaveBeenCalled();
}); });
}); });
describe('getSurveyMetaList', () => { describe('getSurveyMetaList', () => {
it('should return a list of survey metadata', async () => { it('should return a list of survey metadata', async () => {
// 准备模拟数据
const mockData = [ const mockData = [
{ _id: 1, title: 'Survey 1' }, { _id: 1, title: 'Survey 1' },
{ _id: 2, title: 'Survey 2' },
] as unknown as Array<SurveyMeta>; ] as unknown as Array<SurveyMeta>;
const mockCount = 2; const mockCount = 1;
jest jest
.spyOn(surveyRepository, 'findAndCount') .spyOn(surveyRepository, 'findAndCount')
.mockResolvedValue([mockData, mockCount]); .mockResolvedValue([mockData, mockCount]);
// 调用方法并检查返回值
const condition = { const condition = {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
@ -181,44 +198,47 @@ describe('SurveyMetaService', () => {
filter: {}, filter: {},
order: {}, order: {},
}; };
const result = await service.getSurveyMetaList(condition); const result = await service.getSurveyMetaList(condition);
// 验证返回值
expect(result).toEqual({ data: mockData, count: mockCount }); expect(result).toEqual({ data: mockData, count: mockCount });
// 验证repository方法被正确调用
expect(surveyRepository.findAndCount).toHaveBeenCalledTimes(1); expect(surveyRepository.findAndCount).toHaveBeenCalledTimes(1);
}); });
}); });
describe('publishSurveyMeta', () => { describe('publishSurveyMeta', () => {
it('should publish a survey meta and add status to statusList', async () => { it('should publish a survey and update curStatus', async () => {
// 准备模拟数据 const surveyMeta = new SurveyMeta();
const surveyMeta = { surveyMeta.statusList = [];
id: 1,
title: 'Test Survey',
statusList: [],
} as unknown as SurveyMeta;
const savedSurveyMeta = {
...surveyMeta,
curStatus: {
status: RECORD_STATUS.PUBLISHED,
date: expect.any(Number),
},
subStatus: {
status: RECORD_SUB_STATUS.DEFAULT,
date: expect.any(Number),
},
} as unknown as SurveyMeta;
jest.spyOn(surveyRepository, 'save').mockResolvedValue(savedSurveyMeta); jest.spyOn(surveyRepository, 'save').mockResolvedValue(surveyMeta);
// 调用方法并检查返回值
const result = await service.publishSurveyMeta({ surveyMeta }); const result = await service.publishSurveyMeta({ surveyMeta });
// 验证返回值 expect(surveyMeta.curStatus.status).toBe(RECORD_STATUS.PUBLISHED);
expect(result).toEqual(savedSurveyMeta); expect(surveyMeta.statusList.length).toBe(1);
// 验证repository方法被正确调用 expect(surveyMeta.statusList[0].status).toBe(RECORD_STATUS.PUBLISHED);
expect(surveyRepository.save).toHaveBeenCalledWith(savedSurveyMeta); expect(surveyRepository.save).toHaveBeenCalledWith(surveyMeta);
expect(result).toEqual(surveyMeta);
});
});
describe('countSurveyMetaByWorkspaceId', () => {
it('should return the count of surveys in a workspace', async () => {
const workspaceId = 'workspace1';
const mockCount = 5;
jest.spyOn(surveyRepository, 'count').mockResolvedValue(mockCount);
const result = await service.countSurveyMetaByWorkspaceId({
workspaceId,
});
expect(result).toBe(mockCount);
expect(surveyRepository.count).toHaveBeenCalledWith({
workspaceId,
isDeleted: { $ne: true },
});
}); });
}); });
}); });

View File

@ -17,8 +17,8 @@ import { DOWNLOAD_TASK_STATUS } from 'src/enums/downloadTaskStatus';
@Injectable() @Injectable()
export class DownloadTaskService { export class DownloadTaskService {
private static taskList: Array<any> = []; static taskList: Array<any> = [];
private static isExecuting: boolean = false; static isExecuting: boolean = false;
constructor( constructor(
@InjectRepository(DownloadTask) @InjectRepository(DownloadTask)
@ -153,7 +153,7 @@ export class DownloadTaskService {
} }
} }
private async handleDownloadTask({ taskInfo }) { async handleDownloadTask({ taskInfo }) {
try { try {
// 更新任务状态为计算中 // 更新任务状态为计算中
const updateRes = await this.downloadTaskRepository.updateOne( const updateRes = await this.downloadTaskRepository.updateOne(

View File

@ -21,6 +21,7 @@ describe('ClientEncryptService', () => {
save: jest.fn(), save: jest.fn(),
findOne: jest.fn(), findOne: jest.fn(),
updateOne: jest.fn(), updateOne: jest.fn(),
deleteOne: jest.fn(),
}, },
}, },
], ],
@ -105,11 +106,13 @@ describe('ClientEncryptService', () => {
describe('deleteEncryptInfo', () => { describe('deleteEncryptInfo', () => {
it('should delete encrypt info by id', async () => { it('should delete encrypt info by id', async () => {
const id = new ObjectId().toHexString(); const id = new ObjectId().toHexString();
const updateResult = { matchedCount: 1, modifiedCount: 1 }; const deleteResult = { matchedCount: 1, modifiedCount: 1 };
jest.spyOn(repository, 'updateOne').mockResolvedValue(updateResult); jest
.spyOn(repository, 'deleteOne')
.mockResolvedValue(deleteResult as any);
const result = await service.deleteEncryptInfo(id); const result = await service.deleteEncryptInfo(id);
expect(result).toEqual(updateResult); expect(result).toEqual(deleteResult);
}); });
}); });
}); });

View File

@ -50,6 +50,7 @@ describe('CounterService', () => {
surveyPath: 'testPath', surveyPath: 'testPath',
type: 'testType', type: 'testType',
data, data,
updatedAt: expect.any(Date),
}, },
}, },
{ upsert: true }, { upsert: true },

View File

@ -18,8 +18,8 @@ export const mockResponseSchema: ResponseSchema = {
date: 1710399368439, date: 1710399368439,
}, },
], ],
createDate: 1710399368440, createdAt: 1710399368440,
updateDate: 1710399368440, updatedAt: 1710399368440,
title: '加密全流程', title: '加密全流程',
surveyPath: 'EBzdmnSp', surveyPath: 'EBzdmnSp',
code: { code: {

View File

@ -3,27 +3,28 @@ import { ResponseSchemaController } from '../controllers/responseSchema.controll
import { ResponseSchemaService } from '../services/responseScheme.service'; import { ResponseSchemaService } from '../services/responseScheme.service';
import { HttpException } from 'src/exceptions/httpException'; import { HttpException } from 'src/exceptions/httpException';
import { EXCEPTION_CODE } from 'src/enums/exceptionCode'; import { EXCEPTION_CODE } from 'src/enums/exceptionCode';
import { RECORD_STATUS, RECORD_SUB_STATUS } from 'src/enums'; import { RECORD_SUB_STATUS } from 'src/enums';
import { ResponseSchema } from 'src/models/responseSchema.entity'; import { ResponseSchema } from 'src/models/responseSchema.entity';
import { Logger } from 'src/logger'; import { Logger } from 'src/logger';
import { UserService } from 'src/modules/auth/services/user.service'; import { UserService } from 'src/modules/auth/services/user.service';
import { WorkspaceMemberService } from 'src/modules/workspace/services/workspaceMember.service'; import { WorkspaceMemberService } from 'src/modules/workspace/services/workspaceMember.service';
import { AuthService } from 'src/modules/auth/services/auth.service';
import { SurveyNotFoundException } from 'src/exceptions/surveyNotFoundException'; import { SurveyNotFoundException } from 'src/exceptions/surveyNotFoundException';
jest.mock('../services/responseScheme.service'); jest.mock('../services/responseScheme.service');
jest.mock('src/modules/auth/services/user.service');
jest.mock('src/modules/workspace/services/workspaceMember.service');
describe('ResponseSchemaController', () => { describe('ResponseSchemaController', () => {
let controller: ResponseSchemaController; let controller: ResponseSchemaController;
let responseSchemaService: ResponseSchemaService; let responseSchemaService: ResponseSchemaService;
let userService: UserService;
let workspaceMemberService: WorkspaceMemberService;
beforeEach(async () => { beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({ const module: TestingModule = await Test.createTestingModule({
controllers: [ResponseSchemaController], controllers: [ResponseSchemaController],
providers: [ providers: [
ResponseSchemaService, ResponseSchemaService,
AuthService,
{ {
provide: Logger, provide: Logger,
useValue: { useValue: {
@ -42,12 +43,6 @@ describe('ResponseSchemaController', () => {
findAllByUserId: jest.fn(), findAllByUserId: jest.fn(),
}, },
}, },
{
provide: AuthService,
useValue: {
create: jest.fn(),
},
},
{ {
provide: Logger, provide: Logger,
useValue: { useValue: {
@ -61,6 +56,10 @@ describe('ResponseSchemaController', () => {
responseSchemaService = module.get<ResponseSchemaService>( responseSchemaService = module.get<ResponseSchemaService>(
ResponseSchemaService, ResponseSchemaService,
); );
userService = module.get<UserService>(UserService);
workspaceMemberService = module.get<WorkspaceMemberService>(
WorkspaceMemberService,
);
}); });
describe('getSchema', () => { describe('getSchema', () => {
@ -68,13 +67,20 @@ describe('ResponseSchemaController', () => {
const mockQueryInfo = { surveyPath: 'validSurveyPath' }; const mockQueryInfo = { surveyPath: 'validSurveyPath' };
const mockResponseSchema = { const mockResponseSchema = {
surveyPath: 'testSurveyPath', surveyPath: 'testSurveyPath',
curStatus: { status: RECORD_STATUS.PUBLISHED, date: Date.now() }, curStatus: { status: 'published', date: Date.now() },
subStatus: { status: RECORD_SUB_STATUS.DEFAULT, date: Date.now() }, subStatus: { status: RECORD_SUB_STATUS.DEFAULT, date: Date.now() },
code: {
baseConf: {
passwordSwitch: false,
password: null,
whitelist: [],
},
},
} as ResponseSchema; } as ResponseSchema;
jest jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath') .spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue(Promise.resolve(mockResponseSchema)); .mockResolvedValue(mockResponseSchema);
const result = await controller.getSchema(mockQueryInfo); const result = await controller.getSchema(mockQueryInfo);
@ -98,168 +104,180 @@ describe('ResponseSchemaController', () => {
jest jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath') .spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue({ .mockResolvedValue({
subStatus: { status: RECORD_SUB_STATUS.REMOVED }, isDeleted: true,
} as ResponseSchema); } as ResponseSchema);
await expect(controller.getSchema(mockQueryInfo)).rejects.toThrow( await expect(controller.getSchema(mockQueryInfo)).rejects.toThrow(
new HttpException('问卷已删除', EXCEPTION_CODE.RESPONSE_SCHEMA_REMOVED), new HttpException(
'问卷不存在或已删除',
EXCEPTION_CODE.RESPONSE_SCHEMA_REMOVED,
),
); );
}); });
it('whitelistValidate should throw SurveyNotFoundException when survey is removed', async () => { it('should throw HttpException with RESPONSE_PAUSING code when survey is paused', async () => {
const surveyPath = ''; const mockQueryInfo = { surveyPath: 'pausedSurveyPath' };
jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue({
curStatus: { status: 'published' },
subStatus: { status: RECORD_SUB_STATUS.PAUSING },
} as ResponseSchema);
await expect(controller.getSchema(mockQueryInfo)).rejects.toThrow(
new HttpException('该问卷已暂停回收', EXCEPTION_CODE.RESPONSE_PAUSING),
);
});
});
describe('whitelistValidate', () => {
it('should throw HttpException when parameters are invalid', async () => {
const surveyPath = 'testSurveyPath';
const body = { password: 1 };
await expect(
controller.whitelistValidate(surveyPath, body),
).rejects.toThrow(HttpException);
});
it('should throw SurveyNotFoundException when survey is removed', async () => {
const surveyPath = 'removedSurveyPath';
jest jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath') .spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue(null); .mockResolvedValue(null);
await expect( await expect(
controller.whitelistValidate(surveyPath, { controller.whitelistValidate(surveyPath, { password: '123456' }),
password: '123456',
}),
).rejects.toThrow(new SurveyNotFoundException('该问卷不存在,无法提交')); ).rejects.toThrow(new SurveyNotFoundException('该问卷不存在,无法提交'));
}); });
it('whitelistValidate should throw WHITELIST_ERROR code when password is incorrect', async () => { it('should throw HttpException when password is incorrect', async () => {
const surveyPath = ''; const surveyPath = 'testSurveyPath';
jest const mockSchema = {
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue({
curStatus: {
status: 'published',
},
subStatus: {
status: '',
},
code: { code: {
baseConf: { baseConf: {
passwordSwitch: true, passwordSwitch: true,
password: '123456', password: '123456',
}, },
}, },
} as ResponseSchema); };
jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue(mockSchema as any);
await expect( await expect(
controller.whitelistValidate(surveyPath, { controller.whitelistValidate(surveyPath, { password: 'wrongPassword' }),
password: '123457',
}),
).rejects.toThrow( ).rejects.toThrow(
new HttpException('验证失败', EXCEPTION_CODE.WHITELIST_ERROR), new HttpException('密码验证失败', EXCEPTION_CODE.WHITELIST_ERROR),
); );
}); });
it('whitelistValidate should be successfully', async () => { it('should validate successfully when password is correct', async () => {
const surveyPath = 'test'; const surveyPath = 'testSurveyPath';
jest const mockSchema = {
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue({
curStatus: {
status: 'published',
},
subStatus: {
status: '',
},
code: {
baseConf: {
passwordSwitch: true,
password: '123456',
},
},
} as ResponseSchema);
await expect(
controller.whitelistValidate(surveyPath, {
password: '123456',
}),
).resolves.toEqual({ code: 200, data: null });
});
it('whitelistValidate should throw WHITELIST_ERROR code when mobile or email is incorrect', async () => {
const surveyPath = '';
jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue({
curStatus: {
status: 'published',
},
subStatus: {
status: '',
},
code: { code: {
baseConf: { baseConf: {
passwordSwitch: true, passwordSwitch: true,
password: '123456', password: '123456',
whitelistType: 'CUSTOM', whitelistType: 'CUSTOM',
memberType: 'MOBILE', whitelist: ['allowed@example.com'],
whitelist: ['13500000000'],
}, },
}, },
} as ResponseSchema); };
jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue(mockSchema as any);
const result = await controller.whitelistValidate(surveyPath, {
password: '123456',
whitelist: 'allowed@example.com',
});
expect(result).toEqual({ code: 200, data: null });
});
it('should throw HttpException when whitelist value is not in CUSTOM whitelist', async () => {
const surveyPath = 'testSurveyPath';
const mockSchema = {
code: {
baseConf: {
whitelistType: 'CUSTOM',
whitelist: ['allowed@example.com'],
},
},
};
jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue(mockSchema as any);
await expect( await expect(
controller.whitelistValidate(surveyPath, { controller.whitelistValidate(surveyPath, {
password: '123456', password: '123456',
whitelist: '13500000001', whitelist: 'notAllowed@example.com',
}), }),
).rejects.toThrow( ).rejects.toThrow(
new HttpException('验证失败', EXCEPTION_CODE.WHITELIST_ERROR), new HttpException('白名单验证失败', EXCEPTION_CODE.WHITELIST_ERROR),
); );
}); });
it('whitelistValidate should throw WHITELIST_ERROR code when member is incorrect', async () => { it('should throw HttpException when user is not found in MEMBER whitelist', async () => {
const surveyPath = ''; const surveyPath = 'testSurveyPath';
jest const mockSchema = {
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue({
curStatus: {
status: 'published',
},
subStatus: {
status: '',
},
code: { code: {
baseConf: { baseConf: {
passwordSwitch: true,
password: '123456',
whitelistType: 'MEMBER', whitelistType: 'MEMBER',
whitelist: ['Jack'], whitelist: [],
}, },
}, },
} as ResponseSchema); };
jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue(mockSchema as any);
jest.spyOn(userService, 'getUserByUsername').mockResolvedValue(null);
await expect( await expect(
controller.whitelistValidate(surveyPath, { controller.whitelistValidate(surveyPath, {
password: '123456', password: '123456',
whitelist: 'James', whitelist: 'nonExistentUser',
}),
).rejects.toThrow(
new HttpException('名单验证失败', EXCEPTION_CODE.WHITELIST_ERROR),
);
});
it('should throw HttpException when user is not a workspace member', async () => {
const surveyPath = 'testSurveyPath';
const mockSchema = {
code: {
baseConf: {
whitelistType: 'MEMBER',
whitelist: [],
},
},
};
jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue(mockSchema as any);
jest
.spyOn(userService, 'getUserByUsername')
.mockResolvedValue({ _id: new Object(), username: '' } as any);
jest
.spyOn(workspaceMemberService, 'findAllByUserId')
.mockResolvedValue([]);
await expect(
controller.whitelistValidate(surveyPath, {
password: '123456',
whitelist: 'testUser',
}), }),
).rejects.toThrow( ).rejects.toThrow(
new HttpException('验证失败', EXCEPTION_CODE.WHITELIST_ERROR), new HttpException('验证失败', EXCEPTION_CODE.WHITELIST_ERROR),
); );
}); });
}); });
it('whitelistValidate should return verifyId successfully', async () => {
const surveyPath = '';
jest
.spyOn(responseSchemaService, 'getResponseSchemaByPath')
.mockResolvedValue({
curStatus: {
status: 'published',
},
subStatus: {
status: '',
},
code: {
baseConf: {
passwordSwitch: true,
password: '123456',
whitelistType: 'CUSTOM',
memberType: 'MOBILE',
whitelist: ['13500000000'],
},
},
} as ResponseSchema);
await expect(
controller.whitelistValidate(surveyPath, {
password: '123456',
whitelist: '13500000000',
}),
).resolves.toEqual({ code: 200, data: null });
});
}); });

View File

@ -20,6 +20,7 @@ describe('ResponseSchemaService', () => {
findOne: jest.fn().mockResolvedValue(mockResponseSchema), findOne: jest.fn().mockResolvedValue(mockResponseSchema),
create: jest.fn(), create: jest.fn(),
save: jest.fn(), save: jest.fn(),
updateOne: jest.fn(),
}, },
}, },
], ],
@ -120,22 +121,24 @@ describe('ResponseSchemaService', () => {
describe('deleteResponseSchema', () => { describe('deleteResponseSchema', () => {
it('should delete response schema by survey path', async () => { it('should delete response schema by survey path', async () => {
jest jest
.spyOn(responseSchemaRepository, 'findOne') .spyOn(responseSchemaRepository, 'updateOne')
.mockResolvedValueOnce(cloneDeep(mockResponseSchema)); .mockResolvedValueOnce(cloneDeep(mockResponseSchema));
jest
.spyOn(responseSchemaRepository, 'save')
.mockResolvedValueOnce(undefined);
await service.deleteResponseSchema({ await service.deleteResponseSchema({
surveyPath: mockResponseSchema.surveyPath, surveyPath: mockResponseSchema.surveyPath,
}); });
expect(responseSchemaRepository.findOne).toHaveBeenCalledWith({ expect(responseSchemaRepository.updateOne).toHaveBeenCalledWith(
where: { {
surveyPath: mockResponseSchema.surveyPath, surveyPath: mockResponseSchema.surveyPath,
}, },
}); {
expect(responseSchemaRepository.save).toHaveBeenCalledTimes(1); $set: {
isDeleted: true,
updatedAt: new Date(),
},
},
);
}); });
}); });
}); });

View File

@ -71,8 +71,8 @@ const mockClientEncryptInfo = {
date: 1710399425273.0, date: 1710399425273.0,
}, },
], ],
createDate: 1710399425273.0, createdAt: 1710399425273.0,
updateDate: 1710399425273.0, updatedAt: 1710399425273.0,
}; };
describe('SurveyResponseController', () => { describe('SurveyResponseController', () => {
@ -178,7 +178,7 @@ describe('SurveyResponseController', () => {
.mockResolvedValueOnce({ .mockResolvedValueOnce({
_id: new ObjectId('65fc2dd77f4520858046e129'), _id: new ObjectId('65fc2dd77f4520858046e129'),
clientTime: 1711025112552, clientTime: 1711025112552,
createDate: 1711025113146, createdAt: 1711025113146,
curStatus: { curStatus: {
status: RECORD_STATUS.NEW, status: RECORD_STATUS.NEW,
date: 1711025113146, date: 1711025113146,
@ -212,7 +212,7 @@ describe('SurveyResponseController', () => {
], ],
surveyPath: 'EBzdmnSp', surveyPath: 'EBzdmnSp',
updateDate: 1711025113146, updatedAt: 1711025113146,
secretKeys: [], secretKeys: [],
} as unknown as SurveyResponse); } as unknown as SurveyResponse);
jest jest

View File

@ -18,6 +18,7 @@ describe('SurveyResponseService', () => {
create: jest.fn(), create: jest.fn(),
save: jest.fn(), save: jest.fn(),
count: jest.fn(), count: jest.fn(),
find: jest.fn(),
}, },
}, },
], ],
@ -69,16 +70,12 @@ describe('SurveyResponseService', () => {
it('should get the total survey response count by path', async () => { it('should get the total survey response count by path', async () => {
const surveyPath = 'testPath'; const surveyPath = 'testPath';
const count = 10; const count = 10;
jest.spyOn(surveyResponseRepository, 'count').mockResolvedValue(count); jest
.spyOn(surveyResponseRepository, 'find')
.mockResolvedValue(new Array(10));
const result = await service.getSurveyResponseTotalByPath(surveyPath); const result = await service.getSurveyResponseTotalByPath(surveyPath);
expect(result).toEqual(count); expect(result).toEqual(count);
expect(surveyResponseRepository.count).toHaveBeenCalledWith({
where: {
surveyPath,
'subStatus.status': { $ne: 'removed' },
},
});
}); });
}); });

View File

@ -12,6 +12,7 @@ import { UserService } from 'src/modules/auth/services/user.service';
import { SurveyMetaService } from 'src/modules/survey/services/surveyMeta.service'; import { SurveyMetaService } from 'src/modules/survey/services/surveyMeta.service';
import { Logger } from 'src/logger'; import { Logger } from 'src/logger';
import { User } from 'src/models/user.entity'; import { User } from 'src/models/user.entity';
import { GetWorkspaceListDto } from '../dto/getWorkspaceList.dto';
jest.mock('src/guards/authentication.guard'); jest.mock('src/guards/authentication.guard');
jest.mock('src/guards/survey.guard'); jest.mock('src/guards/survey.guard');
@ -22,6 +23,7 @@ describe('WorkspaceController', () => {
let workspaceService: WorkspaceService; let workspaceService: WorkspaceService;
let workspaceMemberService: WorkspaceMemberService; let workspaceMemberService: WorkspaceMemberService;
let userService: UserService; let userService: UserService;
let logger: Logger;
beforeEach(async () => { beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({ const module: TestingModule = await Test.createTestingModule({
@ -31,7 +33,6 @@ describe('WorkspaceController', () => {
provide: WorkspaceService, provide: WorkspaceService,
useValue: { useValue: {
create: jest.fn(), create: jest.fn(),
findAllById: jest.fn(),
findAllByIdWithPagination: jest.fn(), findAllByIdWithPagination: jest.fn(),
update: jest.fn(), update: jest.fn(),
delete: jest.fn(), delete: jest.fn(),
@ -47,7 +48,6 @@ describe('WorkspaceController', () => {
batchUpdate: jest.fn(), batchUpdate: jest.fn(),
batchDelete: jest.fn(), batchDelete: jest.fn(),
countByWorkspaceId: jest.fn(), countByWorkspaceId: jest.fn(),
batchSearchByWorkspace: jest.fn(),
}, },
}, },
{ {
@ -80,24 +80,26 @@ describe('WorkspaceController', () => {
WorkspaceMemberService, WorkspaceMemberService,
); );
userService = module.get<UserService>(UserService); userService = module.get<UserService>(UserService);
logger = module.get<Logger>(Logger);
}); });
describe('create', () => { describe('create', () => {
it('should create a workspace and return workspaceId', async () => { it('should create a workspace and return workspaceId', async () => {
const mockUserId = new ObjectId(),
mockUsername = 'username';
const createWorkspaceDto: CreateWorkspaceDto = { const createWorkspaceDto: CreateWorkspaceDto = {
name: 'Test Workspace', name: 'Test Workspace',
description: 'Test Description', description: 'Test Description',
members: [{ userId: 'userId1', role: WORKSPACE_ROLE.USER }], members: [{ userId: mockUserId.toString(), role: WORKSPACE_ROLE.USER }],
}; };
const req = { user: { _id: new ObjectId() } }; const req = { user: { _id: new ObjectId(), username: 'testuser' } };
const createdWorkspace = { _id: new ObjectId() }; const createdWorkspace = { _id: new ObjectId() };
jest.spyOn(userService, 'getUserListByIds').mockResolvedValue([ jest
{ .spyOn(userService, 'getUserListByIds')
_id: 'userId1', .mockResolvedValue([
}, { _id: mockUserId, username: mockUsername },
] as unknown as Array<User>); ] as unknown as Array<User>);
jest jest
.spyOn(workspaceService, 'create') .spyOn(workspaceService, 'create')
.mockResolvedValue(createdWorkspace as Workspace); .mockResolvedValue(createdWorkspace as Workspace);
@ -113,6 +115,7 @@ describe('WorkspaceController', () => {
expect(workspaceService.create).toHaveBeenCalledWith({ expect(workspaceService.create).toHaveBeenCalledWith({
name: createWorkspaceDto.name, name: createWorkspaceDto.name,
description: createWorkspaceDto.description, description: createWorkspaceDto.description,
owner: req.user.username,
ownerId: req.user._id.toString(), ownerId: req.user._id.toString(),
}); });
expect(workspaceMemberService.create).toHaveBeenCalledWith({ expect(workspaceMemberService.create).toHaveBeenCalledWith({
@ -123,31 +126,31 @@ describe('WorkspaceController', () => {
expect(workspaceMemberService.batchCreate).toHaveBeenCalledWith({ expect(workspaceMemberService.batchCreate).toHaveBeenCalledWith({
workspaceId: createdWorkspace._id.toString(), workspaceId: createdWorkspace._id.toString(),
members: createWorkspaceDto.members, members: createWorkspaceDto.members,
creator: req.user.username,
creatorId: req.user._id.toString(),
}); });
}); });
it('should throw an exception if validation fails', async () => { it('should throw an exception if validation fails', async () => {
const createWorkspaceDto: CreateWorkspaceDto = { const createWorkspaceDto = { name: '', members: [] };
name: '',
members: [],
};
const req = { user: { _id: new ObjectId() } }; const req = { user: { _id: new ObjectId() } };
await expect(controller.create(createWorkspaceDto, req)).rejects.toThrow( await expect(controller.create(createWorkspaceDto, req)).rejects.toThrow(
HttpException, HttpException,
); );
expect(logger.error).toHaveBeenCalledTimes(1);
}); });
}); });
describe('findAll', () => { describe('findAll', () => {
it('should return a list of workspaces for the user', async () => { it('should return a list of workspaces for the user', async () => {
const req = { user: { _id: new ObjectId() } }; const req = { user: { _id: new ObjectId() } };
const queryInfo: GetWorkspaceListDto = { curPage: 1, pageSize: 10 };
const memberList = [{ workspaceId: new ObjectId().toString() }]; const memberList = [{ workspaceId: new ObjectId().toString() }];
const workspaces = [{ _id: new ObjectId(), name: 'Test Workspace' }]; const workspaces = [{ _id: new ObjectId(), name: 'Test Workspace' }];
jest jest
.spyOn(workspaceMemberService, 'findAllByUserId') .spyOn(workspaceMemberService, 'findAllByUserId')
.mockResolvedValue(memberList as unknown as Array<WorkspaceMember>); .mockResolvedValue(memberList as Array<WorkspaceMember>);
jest jest
.spyOn(workspaceService, 'findAllByIdWithPagination') .spyOn(workspaceService, 'findAllByIdWithPagination')
@ -156,12 +159,11 @@ describe('WorkspaceController', () => {
count: workspaces.length, count: workspaces.length,
}); });
jest.spyOn(userService, 'getUserListByIds').mockResolvedValue([]); jest
.spyOn(userService, 'getUserListByIds')
.mockResolvedValue([{ _id: new ObjectId() }] as unknown as Array<User>);
const result = await controller.findAll(req, { const result = await controller.findAll(req, queryInfo);
curPage: 1,
pageSize: 10,
});
expect(result.code).toEqual(200); expect(result.code).toEqual(200);
expect(workspaceMemberService.findAllByUserId).toHaveBeenCalledWith({ expect(workspaceMemberService.findAllByUserId).toHaveBeenCalledWith({
@ -174,6 +176,18 @@ describe('WorkspaceController', () => {
name: undefined, name: undefined,
}); });
}); });
it('should throw an exception if validation fails', async () => {
const req = { user: { _id: new ObjectId() } };
const queryInfo: GetWorkspaceListDto = {
curPage: 'not_a_number',
pageSize: 10,
} as any;
await expect(controller.findAll(req, queryInfo)).rejects.toThrow(
HttpException,
);
});
}); });
describe('update', () => { describe('update', () => {
@ -185,11 +199,9 @@ describe('WorkspaceController', () => {
adminMembers: [], adminMembers: [],
userMembers: [], userMembers: [],
}; };
jest.spyOn(userService, 'getUserListByIds').mockResolvedValue([ jest
{ .spyOn(userService, 'getUserListByIds')
_id: userId, .mockResolvedValue([{ _id: userId }] as Array<User>);
},
] as Array<User>);
const updateDto = { const updateDto = {
name: 'Updated Workspace', name: 'Updated Workspace',
members: [ members: [
@ -203,76 +215,41 @@ describe('WorkspaceController', () => {
jest.spyOn(workspaceService, 'update').mockResolvedValue(updateResult); jest.spyOn(workspaceService, 'update').mockResolvedValue(updateResult);
jest.spyOn(workspaceMemberService, 'batchCreate').mockResolvedValue(null); jest.spyOn(workspaceMemberService, 'batchCreate').mockResolvedValue(null);
jest.spyOn(workspaceMemberService, 'batchUpdate').mockResolvedValue(null); jest.spyOn(workspaceMemberService, 'batchUpdate').mockResolvedValue(null);
jest.spyOn(workspaceMemberService, 'batchDelete').mockResolvedValue(null);
const result = await controller.update(id, updateDto); const result = await controller.update(id, updateDto, {
user: { username: 'testuser', _id: new ObjectId() },
expect(result).toEqual({
code: 200,
}); });
expect(workspaceService.update).toHaveBeenCalledWith(id, {
name: updateDto.name, expect(result).toEqual({ code: 200 });
expect(workspaceService.update).toHaveBeenCalledWith({
id,
workspace: { name: updateDto.name },
operator: 'testuser',
operatorId: expect.any(String),
}); });
expect(workspaceMemberService.batchCreate).toHaveBeenCalledWith({ expect(workspaceMemberService.batchCreate).toHaveBeenCalledWith({
workspaceId: id, workspaceId: id,
members: members.newMembers, members: members.newMembers,
creator: 'testuser',
creatorId: expect.any(String),
}); });
expect(workspaceMemberService.batchUpdate).toHaveBeenCalledWith({ expect(workspaceMemberService.batchUpdate).toHaveBeenCalledWith({
idList: members.adminMembers, idList: members.adminMembers,
role: WORKSPACE_ROLE.ADMIN, role: WORKSPACE_ROLE.ADMIN,
operator: 'testuser',
operatorId: expect.any(String),
}); });
expect(workspaceMemberService.batchUpdate).toHaveBeenCalledWith({ expect(workspaceMemberService.batchUpdate).toHaveBeenCalledWith({
idList: members.userMembers, idList: members.userMembers,
role: WORKSPACE_ROLE.USER, role: WORKSPACE_ROLE.USER,
operator: 'testuser',
operatorId: expect.any(String),
});
expect(workspaceMemberService.batchDelete).toHaveBeenCalledWith({
idList: [],
neIdList: [],
}); });
}); });
}); });
describe('delete', () => {
it('should delete a workspace', async () => {
const id = 'workspaceId';
jest.spyOn(workspaceService, 'delete').mockResolvedValue(null);
const result = await controller.delete(id);
expect(result).toEqual({ code: 200 });
expect(workspaceService.delete).toHaveBeenCalledWith(id);
});
});
describe('getWorkspaceAndMember', () => {
it('should return a list of workspaces and members for the user', async () => {
const userId = new ObjectId();
jest.spyOn(userService, 'getUserListByIds').mockResolvedValue([
{
_id: userId,
},
] as Array<User>);
const req = { user: { _id: userId } };
const workspaceId = new ObjectId();
const memberList = [{ workspaceId, userId }];
const workspaces = [{ _id: workspaceId, name: 'Test Workspace' }];
const userList = [{ _id: userId, username: 'Test User' }];
jest
.spyOn(workspaceService, 'findAllByUserId')
.mockResolvedValue(workspaces as Array<Workspace>);
jest
.spyOn(workspaceMemberService, 'batchSearchByWorkspace')
.mockResolvedValue(memberList as unknown as Array<WorkspaceMember>);
jest
.spyOn(userService, 'getUserListByIds')
.mockResolvedValue(userList as User[]);
const result = await controller.getWorkspaceAndMember(req);
expect(result.code).toEqual(200);
expect(workspaceService.findAllByUserId).toHaveBeenCalledWith(
req.user._id.toString(),
);
expect(
workspaceMemberService.batchSearchByWorkspace,
).toHaveBeenCalledWith(workspaces.map((item) => item._id.toString()));
});
});
}); });

View File

@ -45,6 +45,7 @@ describe('WorkspaceService', () => {
const workspace = { const workspace = {
name: 'Test Workspace', name: 'Test Workspace',
description: 'Description', description: 'Description',
owner: 'Test Owner', // 添加 owner 属性
ownerId: 'ownerId', ownerId: 'ownerId',
}; };
const createdWorkspace = { ...workspace, _id: new ObjectId() }; const createdWorkspace = { ...workspace, _id: new ObjectId() };
@ -59,7 +60,11 @@ describe('WorkspaceService', () => {
const result = await service.create(workspace); const result = await service.create(workspace);
expect(result).toEqual(createdWorkspace); expect(result).toEqual(createdWorkspace);
expect(workspaceRepository.create).toHaveBeenCalledWith(workspace); expect(workspaceRepository.create).toHaveBeenCalledWith({
...workspace,
creator: workspace.owner,
creatorId: workspace.ownerId,
});
expect(workspaceRepository.save).toHaveBeenCalledWith(createdWorkspace); expect(workspaceRepository.save).toHaveBeenCalledWith(createdWorkspace);
}); });
}); });
@ -90,24 +95,35 @@ describe('WorkspaceService', () => {
it('should update a workspace', async () => { it('should update a workspace', async () => {
const workspaceId = 'workspaceId'; const workspaceId = 'workspaceId';
const updateData = { name: 'Updated Workspace' }; const updateData = { name: 'Updated Workspace' };
const operator = 'Test Operator';
const operatorId = 'operatorId';
jest jest
.spyOn(workspaceRepository, 'update') .spyOn(workspaceRepository, 'update')
.mockResolvedValue({ affected: 1 } as any); .mockResolvedValue({ affected: 1 } as any);
const result = await service.update(workspaceId, updateData); const result = await service.update({
id: workspaceId,
workspace: updateData,
operator,
operatorId,
});
expect(result).toEqual({ affected: 1 }); expect(result).toEqual({ affected: 1 });
expect(workspaceRepository.update).toHaveBeenCalledWith( expect(workspaceRepository.update).toHaveBeenCalledWith(workspaceId, {
workspaceId, ...updateData,
updateData, updatedAt: expect.any(Date),
); operator,
operatorId,
});
}); });
}); });
describe('delete', () => { describe('delete', () => {
it('should delete a workspace and update related surveyMeta', async () => { it('should delete a workspace and update related surveyMeta', async () => {
const workspaceId = new ObjectId().toString(); const workspaceId = new ObjectId().toString();
const operator = 'Test Operator';
const operatorId = 'operatorId';
jest jest
.spyOn(workspaceRepository, 'updateOne') .spyOn(workspaceRepository, 'updateOne')
@ -116,11 +132,17 @@ describe('WorkspaceService', () => {
.spyOn(surveyMetaRepository, 'updateMany') .spyOn(surveyMetaRepository, 'updateMany')
.mockResolvedValue({ modifiedCount: 1 } as any); .mockResolvedValue({ modifiedCount: 1 } as any);
await service.delete(workspaceId); const result = await service.delete(workspaceId, {
operator,
operatorId,
});
expect(workspaceRepository.updateOne).toHaveBeenCalledTimes(1); expect(workspaceRepository.updateOne).toHaveBeenCalledTimes(1);
expect(surveyMetaRepository.updateMany).toHaveBeenCalledTimes(1); expect(surveyMetaRepository.updateMany).toHaveBeenCalledTimes(1);
expect(result).toEqual({
workspaceRes: { modifiedCount: 1 },
surveyRes: { modifiedCount: 1 },
});
}); });
}); });
@ -139,9 +161,43 @@ describe('WorkspaceService', () => {
.spyOn(workspaceRepository, 'find') .spyOn(workspaceRepository, 'find')
.mockResolvedValue(workspaces as any); .mockResolvedValue(workspaces as any);
const result = await service.findAllByUserId(''); const result = await service.findAllByUserId('userId');
expect(result).toEqual(workspaces); expect(result).toEqual(workspaces);
expect(workspaceRepository.find).toHaveBeenCalledTimes(1); expect(workspaceRepository.find).toHaveBeenCalledTimes(1);
}); });
}); });
describe('findAllByIdWithPagination', () => {
it('should return paginated workspaces', async () => {
const workspaceIdList = [
new ObjectId().toString(),
new ObjectId().toString(),
];
const page = 1;
const limit = 10;
const workspaces = [
{ _id: workspaceIdList[0], name: 'Workspace 1' },
{ _id: workspaceIdList[1], name: 'Workspace 2' },
];
jest
.spyOn(workspaceRepository, 'findAndCount')
.mockResolvedValue([workspaces, workspaces.length] as any);
const result = await service.findAllByIdWithPagination({
workspaceIdList,
page,
limit,
});
expect(result).toEqual({ list: workspaces, count: workspaces.length });
expect(workspaceRepository.findAndCount).toHaveBeenCalledWith({
where: expect.any(Object),
skip: 0,
take: limit,
order: { createdAt: -1 },
});
});
});
}); });

View File

@ -115,11 +115,16 @@ describe('WorkspaceMemberController', () => {
}; };
const updateResult = { modifiedCount: 1 }; const updateResult = { modifiedCount: 1 };
// Mock request object
const req = {
user: { username: 'admin', _id: 'operatorId' },
};
jest jest
.spyOn(workspaceMemberService, 'updateRole') .spyOn(workspaceMemberService, 'updateRole')
.mockResolvedValue(updateResult); .mockResolvedValue(updateResult);
const result = await controller.updateRole(updateDto); const result = await controller.updateRole(updateDto, req);
expect(result).toEqual({ expect(result).toEqual({
code: 200, code: 200,
@ -128,9 +133,11 @@ describe('WorkspaceMemberController', () => {
}, },
}); });
expect(workspaceMemberService.updateRole).toHaveBeenCalledWith({ expect(workspaceMemberService.updateRole).toHaveBeenCalledWith({
role: updateDto.role,
workspaceId: updateDto.workspaceId, workspaceId: updateDto.workspaceId,
userId: updateDto.userId, userId: updateDto.userId,
role: updateDto.role, operator: req.user.username,
operatorId: req.user._id.toString(),
}); });
}); });
@ -140,8 +147,11 @@ describe('WorkspaceMemberController', () => {
userId: '', userId: '',
role: '', role: '',
}; };
const req = {
user: { username: 'admin', _id: 'operatorId' },
};
await expect(controller.updateRole(updateDto)).rejects.toThrow( await expect(controller.updateRole(updateDto, req)).rejects.toThrow(
HttpException, HttpException,
); );
}); });

View File

@ -58,23 +58,53 @@ describe('WorkspaceMemberService', () => {
{ userId: 'userId1', role: 'admin' }, { userId: 'userId1', role: 'admin' },
{ userId: 'userId2', role: 'user' }, { userId: 'userId2', role: 'user' },
]; ];
const dataToInsert = members.map((item) => ({ ...item, workspaceId })); const creator = 'creatorName';
const creatorId = 'creatorId';
const now = new Date();
const dataToInsert = members.map((item) => ({
...item,
workspaceId,
createdAt: now,
updatedAt: now,
creator,
creatorId,
}));
jest jest.spyOn(repository, 'insertMany').mockResolvedValueOnce({
.spyOn(repository, 'insertMany') insertedCount: members.length,
.mockResolvedValueOnce({ insertedCount: members.length } as any); } as any);
const result = await service.batchCreate({ workspaceId, members }); const result = await service.batchCreate({
workspaceId,
members,
creator,
creatorId,
});
expect(result).toEqual({ insertedCount: members.length }); expect(result).toEqual({ insertedCount: members.length });
expect(repository.insertMany).toHaveBeenCalledWith(dataToInsert); expect(repository.insertMany).toHaveBeenCalledWith(
dataToInsert.map((item) => {
return {
...item,
createdAt: expect.any(Date),
updatedAt: expect.any(Date),
};
}),
);
}); });
it('should return insertedCount 0 if no members to insert', async () => { it('should return insertedCount 0 if no members to insert', async () => {
const workspaceId = new ObjectId().toString(); const workspaceId = new ObjectId().toString();
const members = []; const members = [];
const creator = 'creatorName';
const creatorId = 'creatorId';
const result = await service.batchCreate({ workspaceId, members }); const result = await service.batchCreate({
workspaceId,
members,
creator,
creatorId,
});
expect(result).toEqual({ insertedCount: 0 }); expect(result).toEqual({ insertedCount: 0 });
}); });
@ -84,12 +114,19 @@ describe('WorkspaceMemberService', () => {
it('should batch update workspace members roles', async () => { it('should batch update workspace members roles', async () => {
const idList = [new ObjectId().toString(), new ObjectId().toString()]; const idList = [new ObjectId().toString(), new ObjectId().toString()];
const role = 'user'; const role = 'user';
const operator = 'operatorName';
const operatorId = 'operatorId';
jest jest
.spyOn(repository, 'updateMany') .spyOn(repository, 'updateMany')
.mockResolvedValue({ modifiedCount: idList.length } as any); .mockResolvedValue({ modifiedCount: idList.length } as any);
const result = await service.batchUpdate({ idList, role }); const result = await service.batchUpdate({
idList,
role,
operator,
operatorId,
});
expect(result).toEqual({ modifiedCount: idList.length }); expect(result).toEqual({ modifiedCount: idList.length });
}); });
@ -97,8 +134,15 @@ describe('WorkspaceMemberService', () => {
it('should return modifiedCount 0 if no ids to update', async () => { it('should return modifiedCount 0 if no ids to update', async () => {
const idList = []; const idList = [];
const role = 'user'; const role = 'user';
const operator = 'operatorName';
const operatorId = 'operatorId';
const result = await service.batchUpdate({ idList, role }); const result = await service.batchUpdate({
idList,
role,
operator,
operatorId,
});
expect(result).toEqual({ modifiedCount: 0 }); expect(result).toEqual({ modifiedCount: 0 });
}); });
@ -160,17 +204,25 @@ describe('WorkspaceMemberService', () => {
const workspaceId = 'workspaceId'; const workspaceId = 'workspaceId';
const userId = 'userId'; const userId = 'userId';
const role = 'admin'; const role = 'admin';
const operator = 'operatorName';
const operatorId = 'operatorId';
jest jest
.spyOn(repository, 'updateOne') .spyOn(repository, 'updateOne')
.mockResolvedValue({ modifiedCount: 1 } as any); .mockResolvedValue({ modifiedCount: 1 } as any);
const result = await service.updateRole({ workspaceId, userId, role }); const result = await service.updateRole({
workspaceId,
userId,
role,
operator,
operatorId,
});
expect(result).toEqual({ modifiedCount: 1 }); expect(result).toEqual({ modifiedCount: 1 });
expect(repository.updateOne).toHaveBeenCalledWith( expect(repository.updateOne).toHaveBeenCalledWith(
{ workspaceId, userId }, { workspaceId, userId },
{ $set: { role } }, { $set: { role, operator, operatorId, updatedAt: expect.any(Date) } },
); );
}); });
}); });

View File

@ -1,5 +1,5 @@
import { ObjectId } from 'mongodb'; import { ObjectId } from 'mongodb';
import { getPushingData } from './messagePushing'; import { getPushingData } from '../messagePushing';
import { RECORD_STATUS } from 'src/enums'; import { RECORD_STATUS } from 'src/enums';
describe('getPushingData', () => { describe('getPushingData', () => {

View File

@ -44,7 +44,7 @@
background background
layout="prev, pager, next" layout="prev, pager, next"
:total="total" :total="total"
small size="small"
:page-size="pageSize" :page-size="pageSize"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
> >

View File

@ -17,7 +17,9 @@ export default function usePageEdit(
updateTime: () => void updateTime: () => void
) { ) {
const pageConf = computed(() => schema.pageConf) const pageConf = computed(() => schema.pageConf)
const pageEditOne = computed(() => schema.pageEditOne) const pageEditOne = computed(() => {
return schema.pageEditOne
})
const isFinallyPage = computed(() => { const isFinallyPage = computed(() => {
return pageEditOne.value === pageConf.value.length return pageEditOne.value === pageConf.value.length
}) })

View File

@ -64,7 +64,6 @@ export default defineComponent({
const onRadioClick = (item, $event) => { const onRadioClick = (item, $event) => {
$event && $event.stopPropagation() $event && $event.stopPropagation()
$event && $event.preventDefault() $event && $event.preventDefault()
if (!isChecked(item)) { if (!isChecked(item)) {
emit('change', item.hash) emit('change', item.hash)
} }

View File

@ -91,10 +91,8 @@ const questionConfig = computed(() => {
const updateFormData = (value) => { const updateFormData = (value) => {
const key = props.moduleConfig.field const key = props.moduleConfig.field
const formData = cloneDeep(formValues.value) const formData = cloneDeep(formValues.value)
if (key in formData) {
formData[key] = value formData[key] = value
} console.log(formData)
return formData return formData
} }

View File

@ -161,9 +161,7 @@ export const useSurveyStore = defineStore('survey', () => {
// 用户输入或者选择后,更新表单数据 // 用户输入或者选择后,更新表单数据
const changeData = (data) => { const changeData = (data) => {
let { key, value } = data let { key, value } = data
if (key in formValues.value) {
formValues.value[key] = value formValues.value[key] = value
}
questionStore.setChangeField(key) questionStore.setChangeField(key)
} }