diff --git a/backend/src/__tests__/importJob.test.ts b/backend/src/__tests__/importJob.test.ts new file mode 100644 index 0000000..aa34653 --- /dev/null +++ b/backend/src/__tests__/importJob.test.ts @@ -0,0 +1,283 @@ +import request from "supertest"; +import app from "../server"; +import {ImportJobsList, ImportJob} from "../interfaces"; +import {PROCESSING_TIME_IMPORT_ANY} from "../config"; + +describe ("App import jobs endpoint with invalid body", () => { + it("should return array with errors if body is empty and request should not be saved", async () => { + const postResult = await request(app).post("/import").send({}); + const getResult = await request(app).get("/import"); + + const memoryContents:ImportJobsList = { + pending: [], + finished: [] + }; + + const expectedErrorsArray = [ + {"location": "body", "msg": "bookId field should be a string", "param": "bookId"}, + {"location": "body", "msg": "bookId field is required", "param": "bookId"}, + {"location": "body", "msg": "type field should be a string", "param": "type"}, + {"location": "body", "msg": "type field is required", "param": "type"}, + {"location": "body", "msg": "type is not valid", "param": "type"}, + {"location": "body", "msg": "url field should be a string", "param": "url"}, + {"location": "body", "msg": "url field is required", "param": "url"}, + ]; + + expect(getResult.status).toEqual(200); + expect(postResult.body).toEqual(expectedErrorsArray); + expect(getResult.body).toEqual(memoryContents); + }); + + it("should return array with errors if body is missing bookId field and request should not be saved", async () => { + const postResult = await request(app).post("/import").send({type:"pdf", url: "https://dummy.com"}); + const getResult = await request(app).get("/import"); + + const memoryContents:ImportJobsList = { + pending: [], + finished: [] + }; + + const expectedErrorsArray = [ + {"location": "body", "msg": "bookId field should be a string", "param": "bookId"}, + {"location": "body", "msg": "bookId field is required", "param": "bookId"}, + ]; + + expect(getResult.status).toEqual(200); + expect(postResult.body).toEqual(expectedErrorsArray); + expect(getResult.body).toEqual(memoryContents); + }); + + it("should return array with errors if bookId field is not a string and request should not be saved", async () => { + const postResult = await request(app).post("/import").send({bookId:0, type:"pdf", url: "https://dummy.com"}); + const getResult = await request(app).get("/import"); + + const memoryContents:ImportJobsList = { + pending: [], + finished: [] + }; + + const expectedErrorsArray = [ + {"location": "body", "msg": "bookId field should be a string", "param": "bookId", "value": 0} + ]; + + expect(getResult.status).toEqual(200); + expect(postResult.body).toEqual(expectedErrorsArray); + expect(getResult.body).toEqual(memoryContents); + }); + + it("should return array with errors if body is missing type field and request should not be saved", async () => { + const postResult = await request(app).post("/import").send({bookId:"1111", url:"https://dummy.com"}); + const getResult = await request(app).get("/import"); + + const memoryContents:ImportJobsList = { + pending: [], + finished: [] + }; + + const expectedErrorsArray = [ + {"location": "body", "msg": "type field should be a string", "param": "type"}, + {"location": "body", "msg": "type field is required", "param": "type"}, + {"location": "body", "msg": "type is not valid", "param": "type"} + ]; + + expect(postResult.body).toEqual(expectedErrorsArray); + expect(getResult.status).toEqual(200); + expect(getResult.body).toEqual(memoryContents); + }); + + it("should return array with errors if type field is not a string and request should not be saved", async () => { + const postResult = await request(app).post("/import").send({bookId:"111", type:0, url: "https://dummy.com"}); + const getResult = await request(app).get("/import"); + + const memoryContents:ImportJobsList = { + pending: [], + finished: [] + }; + + const expectedErrorsArray = [ + {"location": "body", "msg": "type field should be a string", "param": "type", "value": 0}, + {"location": "body", "msg": "type is not valid", "param": "type", "value": 0} + ]; + + expect(getResult.status).toEqual(200); + expect(postResult.body).toEqual(expectedErrorsArray); + expect(getResult.body).toEqual(memoryContents); + }); + + it("should return array with errors if type field has invalid value and request should not be saved", async () => { + const postResult = await request(app).post("/import").send({bookId:"111", type:"invalid_type", url:"https://dummy.com"}); + const getResult = await request(app).get("/import"); + + const memoryContents:ImportJobsList = { + pending: [], + finished: [] + }; + + const expectedErrorsArray = [ + {"location": "body", "msg": "type is not valid", "param": "type", "value": "invalid_type"} + ]; + + expect(getResult.status).toEqual(200); + expect(postResult.body).toEqual(expectedErrorsArray); + expect(getResult.body).toEqual(memoryContents); + }); + + it("should return array with errors if body is missing url field and request should not be saved", async () => { + const postResult = await request(app).post("/import").send({bookId:"11122", type:"pdf"}); + const getResult = await request(app).get("/import"); + + const memoryContents:ImportJobsList = { + pending: [], + finished: [] + }; + + const expectedErrorsArray = [ + {"location": "body", "msg": "url field should be a string", "param": "url"}, + {"location": "body", "msg": "url field is required", "param": "url"}, + ]; + + expect(getResult.status).toEqual(200); + expect(postResult.body).toEqual(expectedErrorsArray); + expect(getResult.body).toEqual(memoryContents); + }); + + it("should return array with errors if url field is not a string and request should not be saved", async () => { + const postResult = await request(app).post("/import").send({bookId:"123", type:"pdf", url: 1}); + const getResult = await request(app).get("/import"); + + const memoryContents:ImportJobsList = { + pending: [], + finished: [] + }; + + const expectedErrorsArray = [ + {"location": "body", "msg": "url field should be a string", "param": "url", "value": 1} + ]; + + expect(getResult.status).toEqual(200); + expect(postResult.body).toEqual(expectedErrorsArray); + expect(getResult.body).toEqual(memoryContents); + }); + +}); + +describe ("App export jobs endpoint with valid body", () => { + it("should return ImportJobsList object with empty pending and finished arrays", async () => { + const result = await request(app).get("/import"); + const initialMemoryContents:ImportJobsList = { + pending:[], + finished:[] + }; + + expect(result.status).toEqual(200); + expect(result.body).toEqual(initialMemoryContents); + }); + + it("should return ImportJobsList object containing pending pdf item", async () => { + const dummyImportJob:ImportJob = { + bookId: "12345", + type: "pdf", + url: "https://dummy.com", + state: "pending", // this will be ignored + created_at: new Date(), // this will be ignored + updated_at: new Date() // this will be ignored + }; + const postResult = await request(app).post("/import").send(dummyImportJob); + const getResult = await request(app).get("/import"); + + const newJob = postResult.body; + const pendingJobs = getResult.body.pending; + + expect(getResult.status).toEqual(200); + expect(pendingJobs).toContainEqual(expect.objectContaining(newJob)); + }); + + it("should return ImportJobsList object containing pending word item", async () => { + const dummyImportJob:ImportJob = { + bookId: "990", + type: "word", + url: "https://dummy.com", + state: "pending", // this will be ignored + created_at: new Date(), // this will be ignored + updated_at: new Date() // this will be ignored + }; + const postResult = await request(app).post("/import").send(dummyImportJob); + const getResult = await request(app).get("/import"); + + const newJob = postResult.body; + const pendingJobs = getResult.body.pending; + + expect(getResult.status).toEqual(200); + expect(pendingJobs).toContainEqual(expect.objectContaining(newJob)); + }); + + it("should return ImportJobsList object containing pending evernote item", async () => { + const dummyImportJob:ImportJob = { + bookId: "990", + type: "evernote", + url: "https://dummy.com", + state: "pending", // this will be ignored + created_at: new Date(), // this will be ignored + updated_at: new Date() // this will be ignored + }; + const postResult = await request(app).post("/import").send(dummyImportJob); + const getResult = await request(app).get("/import"); + + const newJob = postResult.body; + const pendingJobs = getResult.body.pending; + + expect(getResult.status).toEqual(200); + expect(pendingJobs).toContainEqual(expect.objectContaining(newJob)); + }); + + it("should return ImportJobsList object containing pending wattpad item", async () => { + const dummyImportJob:ImportJob = { + bookId: "990", + type: "wattpad", + url: "https://dummy.com", + state: "pending", // this will be ignored + created_at: new Date(), // this will be ignored + updated_at: new Date() // this will be ignored + }; + const postResult = await request(app).post("/import").send(dummyImportJob); + const getResult = await request(app).get("/import"); + + const newJob = postResult.body; + const pendingJobs = getResult.body.pending; + + expect(getResult.status).toEqual(200); + expect(pendingJobs).toContainEqual(expect.objectContaining(newJob)); + }); + + it("should return ImportJobsList object with specific pdf-type item in finished array", async () => { + const dummyImportJob:ImportJob = { + bookId: "12345", + type: "pdf", + url: "https://dummy.com", + state: "finished", // this will be ignored + created_at: new Date(), // this will be ignored + updated_at: new Date() // this will be ignored + }; + const postResult = await request(app).post("/import").send(dummyImportJob); + + const exportJob:ImportJob = postResult.body; + const updatedAtUTC = new Date(exportJob.created_at); + const timeToAdd = PROCESSING_TIME_IMPORT_ANY; + updatedAtUTC.setSeconds(updatedAtUTC.getSeconds() + timeToAdd); + updatedAtUTC.setMilliseconds(0); + exportJob.updated_at = updatedAtUTC; + exportJob.state = "finished"; + await new Promise(resolve => setTimeout(resolve, timeToAdd*1000)); + + const getResult = await request(app).get("/import"); + const finishedJobs:ImportJob[] = getResult.body.finished; + + finishedJobs.forEach((finishedJob) => { + finishedJob.updated_at = new Date(finishedJob.updated_at); + finishedJob.updated_at.setMilliseconds(0); + }); + + expect(getResult.status).toEqual(200); + expect(finishedJobs).toContainEqual(expect.objectContaining(exportJob)); + }); +});