From 46f729fb89123b4ed5bcff050080e5d60e03ae0c Mon Sep 17 00:00:00 2001 From: Jake Bromberg Date: Sat, 21 Feb 2026 08:27:23 -0800 Subject: [PATCH 1/3] fix: return 201 Created for all resource creation endpoints All create endpoints (flowsheet entries, bin entries, albums, artists, rotation, formats, genres, schedule) returned 200 instead of 201. Co-authored-by: Cursor --- apps/backend/controllers/djs.controller.ts | 2 +- .../controllers/flowsheet.controller.ts | 6 +- .../backend/controllers/library.controller.ts | 10 ++-- .../controllers/schedule.controller.ts | 2 +- .../controllers/create-status-codes.test.ts | 57 +++++++++++++++++++ 5 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 tests/unit/controllers/create-status-codes.test.ts diff --git a/apps/backend/controllers/djs.controller.ts b/apps/backend/controllers/djs.controller.ts index 1e160cf..d179fc7 100644 --- a/apps/backend/controllers/djs.controller.ts +++ b/apps/backend/controllers/djs.controller.ts @@ -21,7 +21,7 @@ export const addToBin: RequestHandler = async (req, re }; try { const added_bin_item = await DJService.addToBin(bin_entry); - res.status(200).json(added_bin_item); + res.status(201).json(added_bin_item); } catch (e) { console.error('Server error: Failed to insert into bin'); console.error(e); diff --git a/apps/backend/controllers/flowsheet.controller.ts b/apps/backend/controllers/flowsheet.controller.ts index c8074c5..3fd0b84 100644 --- a/apps/backend/controllers/flowsheet.controller.ts +++ b/apps/backend/controllers/flowsheet.controller.ts @@ -182,7 +182,7 @@ export const addEntry: RequestHandler = async (req: Request console.error('[Flowsheet] Metadata fetch failed:', err)); } - res.status(200).json(completedEntry); + res.status(201).json(completedEntry); } else if ( body.album_title === undefined || body.artist_name === undefined || @@ -210,7 +210,7 @@ export const addEntry: RequestHandler = async (req: Request console.error('[Flowsheet] Metadata fetch failed:', err)); } - res.status(200).json(completedEntry); + res.status(201).json(completedEntry); } } catch (e) { console.error('Error: Failed to add track to flowsheet'); @@ -229,7 +229,7 @@ export const addEntry: RequestHandler = async (req: Request = } else { try { const rotationRelease: RotationRelease = await libraryService.addToRotation(req.body); - res.status(200).json(rotationRelease); + res.status(201).json(rotationRelease); } catch (e) { console.error(e); next(e); @@ -228,7 +228,7 @@ export const addFormat: RequestHandler = async (req, res, next) => { }; const insertion = await libraryService.insertFormat(newFormat); - res.status(200).json(insertion); + res.status(201).json(insertion); } catch (e) { console.error('Failed to add new format'); console.error(e); @@ -258,7 +258,7 @@ export const addGenre: RequestHandler = async (req, res, next) => { const insertion = await libraryService.insertGenre(newGenre); - res.status(200).json(insertion); + res.status(201).json(insertion); } catch (e) { console.error('Failed to add new genre'); console.error(e); diff --git a/apps/backend/controllers/schedule.controller.ts b/apps/backend/controllers/schedule.controller.ts index 48b4153..db6aa43 100644 --- a/apps/backend/controllers/schedule.controller.ts +++ b/apps/backend/controllers/schedule.controller.ts @@ -17,7 +17,7 @@ export const addToSchedule: RequestHandler = async (req: Request = {}) { + const req = { body } as unknown as Request; + const res = { + status: jest.fn().mockReturnThis(), + json: jest.fn().mockReturnThis(), + send: jest.fn().mockReturnThis(), + } as unknown as Response; + const next = jest.fn() as unknown as NextFunction; + return { req, res, next }; +} + +describe('create endpoints return 201', () => { + describe('addToBin', () => { + it('should return 201 when a bin entry is created', async () => { + const created = { id: 1, dj_id: 'dj-1', album_id: 10, track_title: null }; + (DJService.addToBin as jest.Mock).mockResolvedValue(created); + + const { req, res, next } = mockReqResNext({ + dj_id: 'dj-1', + album_id: 10, + }); + + await addToBin(req, res, next); + + expect(res.status).toHaveBeenCalledWith(201); + expect(res.json).toHaveBeenCalledWith(created); + }); + }); + + describe('addToSchedule', () => { + it('should return 201 when a schedule entry is created', async () => { + const created = { id: 1, day: 'Monday', start_time: '10:00', end_time: '12:00' }; + (ScheduleService.addToSchedule as jest.Mock).mockResolvedValue(created); + + const { req, res, next } = mockReqResNext({ + day: 'Monday', + start_time: '10:00', + end_time: '12:00', + }); + + await addToSchedule(req, res, next); + + expect(res.status).toHaveBeenCalledWith(201); + expect(res.json).toHaveBeenCalledWith(created); + }); + }); +}); From ed77db3de2caf8a956c422577f903a8943f3e1d3 Mon Sep 17 00:00:00 2001 From: Jake Bromberg Date: Fri, 27 Feb 2026 11:04:50 -0800 Subject: [PATCH 2/3] fix: resolve lint errors --- .../controllers/create-status-codes.test.ts | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tests/unit/controllers/create-status-codes.test.ts b/tests/unit/controllers/create-status-codes.test.ts index 1db5fe2..12ded7f 100644 --- a/tests/unit/controllers/create-status-codes.test.ts +++ b/tests/unit/controllers/create-status-codes.test.ts @@ -10,13 +10,16 @@ import { addToSchedule } from '../../../apps/backend/controllers/schedule.contro function mockReqResNext(body: Record = {}) { const req = { body } as unknown as Request; + const statusMock = jest.fn().mockReturnThis(); + const jsonMock = jest.fn().mockReturnThis(); + const sendMock = jest.fn().mockReturnThis(); const res = { - status: jest.fn().mockReturnThis(), - json: jest.fn().mockReturnThis(), - send: jest.fn().mockReturnThis(), + status: statusMock, + json: jsonMock, + send: sendMock, } as unknown as Response; const next = jest.fn() as unknown as NextFunction; - return { req, res, next }; + return { req, res, next, statusMock, jsonMock, sendMock }; } describe('create endpoints return 201', () => { @@ -25,15 +28,15 @@ describe('create endpoints return 201', () => { const created = { id: 1, dj_id: 'dj-1', album_id: 10, track_title: null }; (DJService.addToBin as jest.Mock).mockResolvedValue(created); - const { req, res, next } = mockReqResNext({ + const { req, res, next, statusMock, jsonMock } = mockReqResNext({ dj_id: 'dj-1', album_id: 10, }); await addToBin(req, res, next); - expect(res.status).toHaveBeenCalledWith(201); - expect(res.json).toHaveBeenCalledWith(created); + expect(statusMock).toHaveBeenCalledWith(201); + expect(jsonMock).toHaveBeenCalledWith(created); }); }); @@ -42,7 +45,7 @@ describe('create endpoints return 201', () => { const created = { id: 1, day: 'Monday', start_time: '10:00', end_time: '12:00' }; (ScheduleService.addToSchedule as jest.Mock).mockResolvedValue(created); - const { req, res, next } = mockReqResNext({ + const { req, res, next, statusMock, jsonMock } = mockReqResNext({ day: 'Monday', start_time: '10:00', end_time: '12:00', @@ -50,8 +53,8 @@ describe('create endpoints return 201', () => { await addToSchedule(req, res, next); - expect(res.status).toHaveBeenCalledWith(201); - expect(res.json).toHaveBeenCalledWith(created); + expect(statusMock).toHaveBeenCalledWith(201); + expect(jsonMock).toHaveBeenCalledWith(created); }); }); }); From 62243fc5b659b9604d1b4cc59d999c7dbfd92c90 Mon Sep 17 00:00:00 2001 From: Jake Bromberg Date: Fri, 27 Feb 2026 15:10:29 -0800 Subject: [PATCH 3/3] fix: revert accidental 201 status codes back to 200 The 201 status code changes from commit 46f729f were accidentally introduced during a rebase and do not belong in this PR, which is about adding NOT NULL constraints to artist_library_crossreference FK columns. Reverts all controllers to return 200 for create endpoints and removes the associated unit test. --- apps/backend/controllers/djs.controller.ts | 2 +- .../controllers/flowsheet.controller.ts | 6 +- .../backend/controllers/library.controller.ts | 10 ++-- .../controllers/schedule.controller.ts | 2 +- .../controllers/create-status-codes.test.ts | 60 ------------------- 5 files changed, 10 insertions(+), 70 deletions(-) delete mode 100644 tests/unit/controllers/create-status-codes.test.ts diff --git a/apps/backend/controllers/djs.controller.ts b/apps/backend/controllers/djs.controller.ts index d179fc7..1e160cf 100644 --- a/apps/backend/controllers/djs.controller.ts +++ b/apps/backend/controllers/djs.controller.ts @@ -21,7 +21,7 @@ export const addToBin: RequestHandler = async (req, re }; try { const added_bin_item = await DJService.addToBin(bin_entry); - res.status(201).json(added_bin_item); + res.status(200).json(added_bin_item); } catch (e) { console.error('Server error: Failed to insert into bin'); console.error(e); diff --git a/apps/backend/controllers/flowsheet.controller.ts b/apps/backend/controllers/flowsheet.controller.ts index 3fd0b84..c8074c5 100644 --- a/apps/backend/controllers/flowsheet.controller.ts +++ b/apps/backend/controllers/flowsheet.controller.ts @@ -182,7 +182,7 @@ export const addEntry: RequestHandler = async (req: Request console.error('[Flowsheet] Metadata fetch failed:', err)); } - res.status(201).json(completedEntry); + res.status(200).json(completedEntry); } else if ( body.album_title === undefined || body.artist_name === undefined || @@ -210,7 +210,7 @@ export const addEntry: RequestHandler = async (req: Request console.error('[Flowsheet] Metadata fetch failed:', err)); } - res.status(201).json(completedEntry); + res.status(200).json(completedEntry); } } catch (e) { console.error('Error: Failed to add track to flowsheet'); @@ -229,7 +229,7 @@ export const addEntry: RequestHandler = async (req: Request = } else { try { const rotationRelease: RotationRelease = await libraryService.addToRotation(req.body); - res.status(201).json(rotationRelease); + res.status(200).json(rotationRelease); } catch (e) { console.error(e); next(e); @@ -228,7 +228,7 @@ export const addFormat: RequestHandler = async (req, res, next) => { }; const insertion = await libraryService.insertFormat(newFormat); - res.status(201).json(insertion); + res.status(200).json(insertion); } catch (e) { console.error('Failed to add new format'); console.error(e); @@ -258,7 +258,7 @@ export const addGenre: RequestHandler = async (req, res, next) => { const insertion = await libraryService.insertGenre(newGenre); - res.status(201).json(insertion); + res.status(200).json(insertion); } catch (e) { console.error('Failed to add new genre'); console.error(e); diff --git a/apps/backend/controllers/schedule.controller.ts b/apps/backend/controllers/schedule.controller.ts index db6aa43..48b4153 100644 --- a/apps/backend/controllers/schedule.controller.ts +++ b/apps/backend/controllers/schedule.controller.ts @@ -17,7 +17,7 @@ export const addToSchedule: RequestHandler = async (req: Request = {}) { - const req = { body } as unknown as Request; - const statusMock = jest.fn().mockReturnThis(); - const jsonMock = jest.fn().mockReturnThis(); - const sendMock = jest.fn().mockReturnThis(); - const res = { - status: statusMock, - json: jsonMock, - send: sendMock, - } as unknown as Response; - const next = jest.fn() as unknown as NextFunction; - return { req, res, next, statusMock, jsonMock, sendMock }; -} - -describe('create endpoints return 201', () => { - describe('addToBin', () => { - it('should return 201 when a bin entry is created', async () => { - const created = { id: 1, dj_id: 'dj-1', album_id: 10, track_title: null }; - (DJService.addToBin as jest.Mock).mockResolvedValue(created); - - const { req, res, next, statusMock, jsonMock } = mockReqResNext({ - dj_id: 'dj-1', - album_id: 10, - }); - - await addToBin(req, res, next); - - expect(statusMock).toHaveBeenCalledWith(201); - expect(jsonMock).toHaveBeenCalledWith(created); - }); - }); - - describe('addToSchedule', () => { - it('should return 201 when a schedule entry is created', async () => { - const created = { id: 1, day: 'Monday', start_time: '10:00', end_time: '12:00' }; - (ScheduleService.addToSchedule as jest.Mock).mockResolvedValue(created); - - const { req, res, next, statusMock, jsonMock } = mockReqResNext({ - day: 'Monday', - start_time: '10:00', - end_time: '12:00', - }); - - await addToSchedule(req, res, next); - - expect(statusMock).toHaveBeenCalledWith(201); - expect(jsonMock).toHaveBeenCalledWith(created); - }); - }); -});