From ee984cd0f5d9a9741061b3ca8cb783f85c1e51d1 Mon Sep 17 00:00:00 2001 From: Federico Hurtado <fed_home@Federicos-Mac-mini.local> Date: Wed, 23 Oct 2024 11:41:29 -0400 Subject: [PATCH] Able to create people and store all of their information except involvements. Began unit testing repository classes. --- backend/repository/addressRepository.js | 6 +- backend/repository/contactRepository.js | 11 +- backend/repository/degreeRepository.js | 8 +- backend/routes/peopleRoutes.js | 6 +- backend/service/peopleService.js | 6 + .../test/repository/addressRepository.test.js | 114 ++++++++++++++++++ .../test/repository/contactRepository.test.js | 56 +++++++++ .../test/repository/degreeRepository.test.js | 108 +++++++++++++++++ .../test/repository/peopleRepository.test.js | 29 ++--- 9 files changed, 317 insertions(+), 27 deletions(-) create mode 100644 backend/test/repository/addressRepository.test.js create mode 100644 backend/test/repository/contactRepository.test.js create mode 100644 backend/test/repository/degreeRepository.test.js diff --git a/backend/repository/addressRepository.js b/backend/repository/addressRepository.js index d2deaef..06da1ce 100644 --- a/backend/repository/addressRepository.js +++ b/backend/repository/addressRepository.js @@ -1,5 +1,8 @@ const { pool } = require("../config/database/database.config"); +/* +Add address info into address table and peopleXaddress table +*/ async function addAddress(address, peopleId) { // get all the parts of the address let { address1, address2, city, state, country, zipCode, preferredAddress } = @@ -43,7 +46,6 @@ async function addAddress(address, peopleId) { INSERT INTO peopleXAddress (peopleId, addressId, preferredAddress) VALUES (?, ?, ?) `; - const [peopleAddressResult] = await pool.query(peopleAddressQuery, [ peopleId, addressId, @@ -54,7 +56,9 @@ async function addAddress(address, peopleId) { return peopleAddressResult; } catch (error) { + // return null if error console.error(error); + return null; } } diff --git a/backend/repository/contactRepository.js b/backend/repository/contactRepository.js index b096cb2..0a091e9 100644 --- a/backend/repository/contactRepository.js +++ b/backend/repository/contactRepository.js @@ -1,11 +1,9 @@ const { pool } = require("../config/database/database.config"); -// contacts: [ -// { -// contactNumber: string --> i guess this can be a phone nunber, email, etc. -// contactType: string --> need to define list: phone, email, .... -// preferredContact: boolean -// }, +/* +Function to add a row into the peopleContact +table with the contact info given +*/ async function addContact(contact, peopleId) { // extract the parts of the contact let { contactNumber, contactType, preferredContact } = contact; @@ -30,6 +28,7 @@ async function addContact(contact, peopleId) { return results; } catch (error) { console.log(error); + return null; } } diff --git a/backend/repository/degreeRepository.js b/backend/repository/degreeRepository.js index 9955b1d..9e7835f 100644 --- a/backend/repository/degreeRepository.js +++ b/backend/repository/degreeRepository.js @@ -1,5 +1,8 @@ const { pool } = require("../config/database/database.config"); +/* +Add degree information into the database. +*/ async function addDegree(degree, peopleId) { // get all the parts of the degree let { @@ -16,6 +19,7 @@ async function addDegree(degree, peopleId) { // Use the helper function to determine the degreeTypeId let degreeTypeId = await _lookupDegreeTypeId(degreeType); + // query to insert degree info const query = ` INSERT INTO peopleDegree (peopleId, degreeTypeId, degreeDepartment, degreeCollege, degreeYear, degreeDescription) VALUES (?,?,?,?,?,?) @@ -33,7 +37,9 @@ async function addDegree(degree, peopleId) { return results; } catch (error) { + // return null if there is an error console.error(error); + return null; } } @@ -61,4 +67,4 @@ async function _lookupDegreeTypeId(degreeType) { } } -module.exports = { addDegree }; +module.exports = { addDegree, _lookupDegreeTypeId }; diff --git a/backend/routes/peopleRoutes.js b/backend/routes/peopleRoutes.js index 3e707a6..fe7ff6b 100644 --- a/backend/routes/peopleRoutes.js +++ b/backend/routes/peopleRoutes.js @@ -122,13 +122,13 @@ peopleRouter.post("/create", validateCreatePerson, async (req, res) => { const person = await createPerson(req.body); console.log("In people routes after add: ", person); - return res.status(201).json({ message: "person added successfully" }); + return res + .status(201) + .json({ message: "person added successfully", personId: person }); } catch (error) { console.log("error"); return res.status(500).json({ message: error }); } - // no logic for now, return 200 - return res.status(200).json({ message: "No errors" }); }); module.exports = peopleRouter; diff --git a/backend/service/peopleService.js b/backend/service/peopleService.js index 0c610db..e196f5c 100644 --- a/backend/service/peopleService.js +++ b/backend/service/peopleService.js @@ -1,4 +1,5 @@ const { addAddress } = require("../repository/addressRepository"); +const { addContact } = require("../repository/contactRepository"); const { addDegree } = require("../repository/degreeRepository"); const { addPerson } = require("../repository/peopleRepository"); @@ -25,12 +26,17 @@ async function createPerson(person) { // insert the contact information into the database for (const contact of contacts) { + const addedContact = await addContact(contact, newPersonID); + console.log("added contact: ", contact); } // insert the involvment information into the database for (const involvment of involvements) { + console.log("not adding involvements yet."); } + // TODO: log database change here + return newPersonID; } diff --git a/backend/test/repository/addressRepository.test.js b/backend/test/repository/addressRepository.test.js new file mode 100644 index 0000000..835e7a8 --- /dev/null +++ b/backend/test/repository/addressRepository.test.js @@ -0,0 +1,114 @@ +// Mock the database's pool and query function +jest.mock("../../config/database/database.config", () => { + const queryMock = jest.fn(); // Mock query function + return { pool: { query: queryMock } }; // Return the mocked pool directly +}); + +const { pool } = require("../../config/database/database.config"); +const { addAddress } = require("../../repository/addressRepository"); + +/* +Test methods for addressRepository +*/ +describe("Testing addressRepository.js", () => { + const mockAddress1 = { + address1: "123 Main St", + address2: "Apt 4", + city: "Springfield", + state: "VA", + country: "United States", + zipCode: "22150", + preferredAddress: true, + }; + + const mockAddress2 = { + address1: "12 Center St", + address2: "Apt 14", + city: "Centerville", + state: "VA", + country: "United States", + zipCode: "23456", + preferredAddress: true, + }; + + const mockPeopleId = 1; + + describe("addAddress tests", () => { + it("Insert 1 address with no errors", async () => { + const mockAddressId = 2; + const mockPeopleXAddressResult = { affectedRows: 1 }; + + // Mock database query for inserting address and peopleXAddress + pool.query + .mockResolvedValueOnce([{ insertId: mockAddressId }]) // First query for address insertion + .mockResolvedValueOnce([mockPeopleXAddressResult]); // Second query for peopleXAddress insertion + + const result = await addAddress(mockAddress1, mockPeopleId); + + // Verify first query was called for address table + expect(pool.query).toHaveBeenCalledWith(expect.any(String), [ + "123 Main St", + "Apt 4", + "Springfield", + 1, // Hardcoded for now + 1, // Hardcoded fow now + "22150", + ]); + + // Verify second query was called for peopleXAddress table + expect(pool.query).toHaveBeenCalledWith(expect.any(String), [ + mockPeopleId, + mockAddressId, // ensure the correct addressID was used + true, + ]); + + // Expect the function to return the result of the second query + expect(result).toBe(mockPeopleXAddressResult); + }); + + it("should handle errors during address insertion", async () => { + // Mock database query to throw an error during address insertion + const mockError = new Error("Database query failed"); + pool.query.mockRejectedValueOnce(mockError); + + // Call addAddress and expect it to handle the error + const result = await addAddress(mockAddress1, mockPeopleId); + + expect(result).toBe(null); + }); + + it("Insert 1 address with no errors", async () => { + const mockAddressId = 2; + const mockPeopleXAddressResult = { affectedRows: 1 }; + + // Mock database query for inserting address and peopleXAddress + pool.query.mockResolvedValueOnce([{ insertId: mockAddressId }]); // First query for address insertion + + // Mock second query to throw an error during peopleXAddress insertion + const mockError = new Error("Failed to insert into peopleXAddress"); + pool.query.mockRejectedValueOnce(mockError); + + const result = await addAddress(mockAddress1, mockPeopleId); + + // Verify first query was called for address table + expect(pool.query).toHaveBeenCalledWith(expect.any(String), [ + "123 Main St", + "Apt 4", + "Springfield", + 1, // Hardcoded for now + 1, // Hardcoded fow now + "22150", + ]); + + // Verify second query was called for peopleXAddress table + expect(pool.query).toHaveBeenCalledWith(expect.any(String), [ + mockPeopleId, + mockAddressId, // ensure the correct addressID was used + true, + ]); + + // expect a null return after the call + expect(result).toBe(null); + }); + }); +}); diff --git a/backend/test/repository/contactRepository.test.js b/backend/test/repository/contactRepository.test.js new file mode 100644 index 0000000..1dfadfb --- /dev/null +++ b/backend/test/repository/contactRepository.test.js @@ -0,0 +1,56 @@ +// Mock the database's pool and query function +jest.mock("../../config/database/database.config", () => { + const queryMock = jest.fn(); // Mock query function + return { pool: { query: queryMock } }; // Return the mocked pool directly +}); + +const { pool } = require("../../config/database/database.config"); +const { addContact } = require("../../repository/contactRepository"); + +/* +Test methods for peopleRepository +*/ +describe("Testing peopleRepository.js", () => { + // mock contact value to use while testing + const mockContact = { + contactNumber: "1234567890", + contactType: "mobile", + preferredContact: true, + }; + const mockPeopleId = 1; + + /* + Tests for the addContact method + */ + describe("addContact Tests", () => { + it("insert a contact with no errors", async () => { + // Mock the database to return a success response + const mockResults = { affectedRows: 1 }; + pool.query.mockResolvedValueOnce([mockResults]); + + // Call addContact + const result = await addContact(mockContact, mockPeopleId); + + // Verify the SQL query and parameters + expect(pool.query).toHaveBeenCalledWith(expect.any(String), [ + 1, + "1234567890", + "mobile", + true, + ]); + + // Expect function to return the database result + expect(result).toBe(mockResults); + }); + + it("handle errors if the query fails", async () => { + // Mock the database to throw an error + const mockError = new Error("Database query failed"); + pool.query.mockRejectedValueOnce(mockError); + + // Call addContact and expect it to handle the error + const result = await addContact(mockContact, mockPeopleId); + expect(result).toBe(null); + }); + }); +}); diff --git a/backend/test/repository/degreeRepository.test.js b/backend/test/repository/degreeRepository.test.js new file mode 100644 index 0000000..c0ee99f --- /dev/null +++ b/backend/test/repository/degreeRepository.test.js @@ -0,0 +1,108 @@ +// Mock the database's pool and query function +jest.mock("../../config/database/database.config", () => { + const queryMock = jest.fn(); // Mock query function + return { pool: { query: queryMock } }; // Return the mocked pool directly +}); + +const { pool } = require("../../config/database/database.config.js"); +const { addDegree } = require("../../repository/degreeRepository.js"); + +/* +Test methods for degreeRepository +*/ +describe("Testing degreeRepository.js", () => { + const mockDegree = { + degreeType: "BS", + degreeDepartment: "Computer Science", + degreeCollege: "Engineering", + degreeYear: "2024", + degreeDescription: "Bachelor of Science in Computer Science", + }; + + const mockPeopleId = 1; + + /* + Tests for the addDegree method + */ + describe("addDegree tests", () => { + it("Insert a degree with no errors", async () => { + const mockDegreeTypeId = 1; + const mockResult = { affectedRows: 1 }; + + // Mock the helper function _lookupDegreeTypeId to return 1 + const lookupDegreeTypeIdSpy = jest + .spyOn( + require("../../repository/degreeRepository"), + "_lookupDegreeTypeId" + ) + .mockResolvedValueOnce(mockDegreeTypeId); + + // Mock the database query for inserting the degree + pool.query.mockResolvedValueOnce([mockResult]); + + // Call addDegree + const result = await addDegree(mockDegree, mockPeopleId); + + // Verify the SQL query for inserting the degree + expect(pool.query).toHaveBeenCalledWith(expect.any(String), [ + mockPeopleId, + null, // null for now + "Computer Science", + "Engineering", + "2024", + "Bachelor of Science in Computer Science", + ]); + + // Expect the function to return the result from the database + expect(result).toBe(mockResult); + + // Clean up spy + lookupDegreeTypeIdSpy.mockRestore(); + }); + + it("error thrown during degree insertion", async () => { + const mockError = new Error("Database query failed"); + + // Mock the helper function _lookupDegreeTypeId to return 1 + const lookupDegreeTypeIdSpy = jest + .spyOn( + require("../../repository/degreeRepository"), + "_lookupDegreeTypeId" + ) + .mockResolvedValueOnce(1); + + // Mock the database query to throw an error during degree insertion + pool.query.mockRejectedValueOnce(mockError); + + // Call addDegree and expect it to handle the error + const result = await addDegree(mockDegree, mockPeopleId); + + // Expect the function to return null on error + expect(result).toBeNull(); + + // Clean up the spy + lookupDegreeTypeIdSpy.mockRestore(); + }); + + it("handle errors during degree type lookup", async () => { + const mockError = new Error("Degree type lookup failed"); + + // Mock the helper function _lookupDegreeTypeId to throw an error + const lookupDegreeTypeIdSpy = jest + .spyOn( + require("../../repository/degreeRepository"), + "_lookupDegreeTypeId" + ) + .mockRejectedValueOnce(mockError); + + // Call addDegree and expect it to handle the error + const result = await addDegree(mockDegree, mockPeopleId); + + // Expect the function to return null on error + expect(result).toBeNull(); + + // Clean up the spy + lookupDegreeTypeIdSpy.mockRestore(); + }); + }); +}); diff --git a/backend/test/repository/peopleRepository.test.js b/backend/test/repository/peopleRepository.test.js index c29c280..1408825 100644 --- a/backend/test/repository/peopleRepository.test.js +++ b/backend/test/repository/peopleRepository.test.js @@ -39,22 +39,19 @@ describe("Testing peopleRepository.js", () => { const result = await addPerson(mockPerson); // Verify the SQL query and parameters - expect(pool.query).toHaveBeenCalledWith( - expect.any(String), // SQL query string, can be further detailed if needed - [ - "John", - "Doe", - "A", - null, - null, - "Johnny", - 2, // hardcoded for now - "2024", - "2024", - "spring", - "male", - ] - ); + expect(pool.query).toHaveBeenCalledWith(expect.any(String), [ + "John", + "Doe", + "A", + null, + null, + "Johnny", + 2, // hardcoded for now + "2024", + "2024", + "spring", + "male", + ]); // expect function to return the new insert id expect(result).toBe(mockInsertId); -- GitLab