import { createSystemInstruction, updateSystemInstruction, deleteSystemInstruction, deactivateSystemInstruction, activateSystemInstruction, } from "../instructions.setters"; import { getSystemInstructionById } from "../instructions.getters"; import { MIS_SystemInstruction, MIS_TOOLS, QUERY_TYPES, } from "../instructions.types"; import { ObjectId } from "mongodb"; describe("System Instructions Setter Tests", () => { const testCity = "Ashdod"; describe("createSystemInstruction", () => { it("given valid data when created then save document with timestamps", async () => { // Given const instructionData: Omit< MIS_SystemInstruction, "_id" | "createdAt" | "updatedAt" > = { cityName: testCity, instruction: "Test Instruction", isActive: true, tool: MIS_TOOLS.findSubject, queryType: QUERY_TYPES.any, tags: ["test", "unit"], }; // When const id = await createSystemInstruction(instructionData); // Then const saved = await getSystemInstructionById(id.toString()); expect(saved).toBeDefined(); expect(saved?._id).toBeDefined(); expect(saved).toMatchObject(instructionData); expect(saved?.createdAt).toBeInstanceOf(Date); expect(saved?.updatedAt).toBeInstanceOf(Date); }); it("given data without tags when created then save document with default isActive true and no tags", async () => { // Given const instructionData: Omit< MIS_SystemInstruction, "_id" | "createdAt" | "updatedAt" > = { cityName: testCity, instruction: "No Tags Instruction", isActive: true, tool: MIS_TOOLS.findStreet, queryType: QUERY_TYPES.exactlyOne, }; // When const id = await createSystemInstruction(instructionData); // Then const saved = await getSystemInstructionById(id.toString()); expect(saved).toBeDefined(); expect(saved?.tags).toBeUndefined(); expect(saved?.isActive).toBe(true); }); it("should throw error when creating with invalid tool", async () => { const invalidData = { cityName: testCity, instruction: "Invalid Tool Test", isActive: true, tool: "invalidTool" as any, queryType: QUERY_TYPES.any, }; await expect(createSystemInstruction(invalidData)).rejects.toThrow( `Invalid tool value: invalidTool. Allowed values are: ${Object.values(MIS_TOOLS).join(", ")}`, ); }); it("should throw error when creating with invalid queryType", async () => { const invalidData = { cityName: testCity, instruction: "Invalid QueryType Test", isActive: true, tool: MIS_TOOLS.findSubject, queryType: "invalidType" as any, }; await expect(createSystemInstruction(invalidData)).rejects.toThrow( `Invalid queryType value: invalidType. Allowed values are: ${Object.values(QUERY_TYPES).join(", ")}`, ); }); }); describe("updateSystemInstruction", () => { let instructionId: string; //Given before each test beforeEach(async () => { const id = await createSystemInstruction({ cityName: testCity, instruction: "Find Me", isActive: true, tool: MIS_TOOLS.findSubject, queryType: QUERY_TYPES.any, }); instructionId = id.toString(); await createSystemInstruction({ cityName: testCity, instruction: "Inactive One", isActive: false, tool: MIS_TOOLS.findSubject, queryType: QUERY_TYPES.any, }); }); it("given existing doc when updated then change values and refresh updatedAt", async () => { const originalDoc = await getSystemInstructionById( instructionId.toString(), ); // Wait a bit to ensure timestamp difference await new Promise((resolve) => setTimeout(resolve, 10)); // When await updateSystemInstruction(instructionId.toString(), { instruction: "New Text", }); // Then const updatedDoc = await getSystemInstructionById( instructionId.toString(), ); expect(updatedDoc?.instruction).toBe("New Text"); expect(updatedDoc?.updatedAt.getTime()).toBeGreaterThan( originalDoc!.updatedAt.getTime(), ); }); it("given multiple fields when updated then change all provided values", async () => { // When await updateSystemInstruction(instructionId, { isActive: false, tool: MIS_TOOLS.findStreet, tags: ["new-tag"], }); // Then const updatedDoc = await getSystemInstructionById(instructionId); expect(updatedDoc?.isActive).toBe(false); expect(updatedDoc?.tool).toBe(MIS_TOOLS.findStreet); expect(updatedDoc?.tags).toEqual(["new-tag"]); }); it("should throw error when updating with invalid tool", async () => { const invalidUpdate = { tool: "invalidTool" as any }; await expect( updateSystemInstruction(instructionId, invalidUpdate), ).rejects.toThrow( `Invalid tool value: invalidTool. Allowed values are: ${Object.values(MIS_TOOLS).join(", ")}`, ); }); it("should throw error when updating with invalid queryType", async () => { const invalidUpdate = { queryType: "invalidType" as any }; await expect( updateSystemInstruction(instructionId, invalidUpdate), ).rejects.toThrow( `Invalid queryType value: invalidType. Allowed values are: ${Object.values(QUERY_TYPES).join(", ")}`, ); }); it("given system instructions, when deactivating it then its status updated to active", async () => { //When const success = await deactivateSystemInstruction( instructionId.toString(), ); const updatedDoc = await getSystemInstructionById( instructionId.toString(), ); //Then expect(success).toBe(true); expect(updatedDoc?.isActive).toBe(false); }); it("given invalidId when deactivating it then return false", async () => { //When const success = await deactivateSystemInstruction( new ObjectId().toHexString(), ); //Then expect(success).toBe(false); }); it("given already inactive instruction when deactivating then still return true and remain inactive", async () => { // Given await deactivateSystemInstruction(instructionId); // When const success = await deactivateSystemInstruction(instructionId); // Then expect(success).toBe(true); const doc = await getSystemInstructionById(instructionId); expect(doc?.isActive).toBe(false); }); }); describe("activateSystemInstruction", () => { let instructionId: string; beforeEach(async () => { const id = await createSystemInstruction({ cityName: testCity, instruction: "Inactive Instruction", isActive: false, tool: MIS_TOOLS.findSubject, queryType: QUERY_TYPES.any, }); instructionId = id.toString(); }); it("given inactive doc when activating then set isActive to true", async () => { // When const success = await activateSystemInstruction(instructionId); // Then expect(success).toBe(true); const updatedDoc = await getSystemInstructionById(instructionId); expect(updatedDoc?.isActive).toBe(true); }); it("given invalidId when activating then return false", async () => { // When const success = await activateSystemInstruction( new ObjectId().toHexString(), ); // Then expect(success).toBe(false); }); }); describe("deleteSystemInstruction", () => { it("given existing id when deleted then remove document from DB", async () => { const id = await createSystemInstruction({ cityName: testCity, instruction: "To be deleted", isActive: true, tool: MIS_TOOLS.findSubject, queryType: QUERY_TYPES.any, }); const deleteResult = await deleteSystemInstruction(id.toString()); expect(deleteResult).toBe(true); const findResult = await getSystemInstructionById(id.toString()); expect(findResult).toBeNull(); }); it("given non-existent id when deleting then return false", async () => { // When const result = await deleteSystemInstruction( new ObjectId().toHexString(), ); // Then expect(result).toBe(false); }); }); });