forked from makeopensource/devU-api
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Submission score entity (makeopensource#44)
Add submissionScore entity to the API. This entity stores a score and feedback attached to a single submission
- Loading branch information
Showing
17 changed files
with
471 additions
and
16 deletions.
There are no files selected for viewing
4 changes: 2 additions & 2 deletions
4
src/controller/codeAssignments.controller.ts → src/controller/codeAssignment.controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { Request, Response, NextFunction } from 'express' | ||
import submissionScoreService from '../services/submissionScore.service' | ||
|
||
import SubmissionScoreService from '../services/submissionScore.service' | ||
|
||
import { GenericResponse, NotFound, Updated } from '../utils/apiResponse.utils' | ||
|
||
import { serialize } from '../utils/serializer/submissionScore.serializer' | ||
|
||
export async function get(req: Request, res: Response, next: NextFunction) { | ||
try { | ||
const submissionScores = await SubmissionScoreService.list() | ||
const response = submissionScores.map(serialize) | ||
|
||
res.status(200).json(response) | ||
} catch (err) { | ||
next(err) | ||
} | ||
} | ||
|
||
export async function detail(req: Request, res: Response, next: NextFunction) { | ||
try { | ||
const id = parseInt(req.params.id) | ||
const submissionScore = await submissionScoreService.retrieve(id) | ||
|
||
if (!submissionScore) return res.status(404).json(NotFound) | ||
|
||
const response = serialize(submissionScore) | ||
|
||
res.status(200).json(response) | ||
} catch (err) { | ||
next(err) | ||
} | ||
} | ||
|
||
export async function post(req: Request, res: Response, next: NextFunction) { | ||
try { | ||
const submissionScore = await SubmissionScoreService.create(req.body) | ||
const response = serialize(submissionScore) | ||
|
||
res.status(201).json(response) | ||
} catch (err) { | ||
res.status(400).json(new GenericResponse(err.message)) | ||
} | ||
} | ||
|
||
export async function put(req: Request, res: Response, next: NextFunction) { | ||
try { | ||
req.body.id = parseInt(req.params.id) | ||
const results = await SubmissionScoreService.update(req.body) | ||
|
||
if (!results.affected) return res.status(404).json(NotFound) | ||
|
||
res.status(200).json(Updated) | ||
} catch (err) { | ||
next(err) | ||
} | ||
} | ||
|
||
export async function _delete(req: Request, res: Response, next: NextFunction) { | ||
try { | ||
const id = parseInt(req.params.id) | ||
const results = await SubmissionScoreService._delete(id) | ||
|
||
if (!results.affected) return res.status(404).json(NotFound) | ||
|
||
res.status(204).send() | ||
} catch (err) { | ||
next(err) | ||
} | ||
} | ||
|
||
export default { get, detail, post, put, _delete } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
208 changes: 208 additions & 0 deletions
208
src/controller/tests/submissionScore.controller.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
import { UpdateResult } from 'typeorm' | ||
|
||
import { SubmissionScore } from 'devu-shared-modules' | ||
|
||
import controller from '../submissionScore.controller' | ||
|
||
import SubmissionScoreModel from '../../model/submissionScore.model' | ||
|
||
import SubmissionScoreService from '../../services/submissionScore.service' | ||
|
||
import { serialize } from '../../utils/serializer/submissionScore.serializer' | ||
|
||
import Testing from '../../utils/testing.utils' | ||
import { GenericResponse, NotFound, Updated } from '../../utils/apiResponse.utils' | ||
|
||
// Testing Globals | ||
let req: any | ||
let res: any | ||
let next: any | ||
|
||
let mockedSubmissionScores: SubmissionScoreModel[] | ||
let mockedSubmissionScore: SubmissionScoreModel | ||
let expectedResults: SubmissionScore[] | ||
let expectedResult: SubmissionScore | ||
let expectedError: Error | ||
|
||
let expectedDbResult: UpdateResult | ||
|
||
describe('SubmissionScoreController', () => { | ||
beforeEach(() => { | ||
req = Testing.fakeRequest() | ||
res = Testing.fakeResponse() | ||
next = Testing.fakeNext() | ||
|
||
mockedSubmissionScores = Testing.generateTypeOrmArray(SubmissionScoreModel, 3) | ||
mockedSubmissionScore = Testing.generateTypeOrm(SubmissionScoreModel) | ||
|
||
expectedResults = mockedSubmissionScores.map(serialize) | ||
expectedResult = serialize(mockedSubmissionScore) | ||
expectedError = new Error('Expected Error') | ||
|
||
expectedDbResult = {} as UpdateResult | ||
}) | ||
|
||
describe('GET - /submission-score', () => { | ||
describe('200 - Ok', () => { | ||
beforeEach(async () => { | ||
SubmissionScoreService.list = jest.fn().mockImplementation(() => Promise.resolve(mockedSubmissionScores)) | ||
await controller.get(req, res, next) // what we're testing | ||
}) | ||
|
||
test('Returns list of submissionScores', () => expect(res.json).toBeCalledWith(expectedResults)) | ||
test('Status code is 200', () => expect(res.status).toBeCalledWith(200)) | ||
}) | ||
|
||
describe('400 - Bad request', () => { | ||
test('Next called with expected error', async () => { | ||
SubmissionScoreService.list = jest.fn().mockImplementation(() => Promise.reject(expectedError)) | ||
|
||
try { | ||
await controller.get(req, res, next) | ||
|
||
fail('Expected test to throw') | ||
} catch { | ||
expect(next).toBeCalledWith(expectedError) | ||
} | ||
}) | ||
}) | ||
}) | ||
|
||
describe('GET - /submission-score/:id', () => { | ||
describe('200 - Ok', () => { | ||
beforeEach(async () => { | ||
SubmissionScoreService.retrieve = jest.fn().mockImplementation(() => Promise.resolve(mockedSubmissionScore)) | ||
await controller.detail(req, res, next) | ||
}) | ||
|
||
test('Returns expected submissionScore', () => expect(res.json).toBeCalledWith(expectedResult)) | ||
test('Status code is 200', () => expect(res.status).toBeCalledWith(200)) | ||
}) | ||
|
||
describe('404 - Not Found', () => { | ||
beforeEach(async () => { | ||
SubmissionScoreService.retrieve = jest.fn().mockImplementation(() => Promise.resolve()) // No results | ||
await controller.detail(req, res, next) | ||
}) | ||
|
||
test('Status code is 404 on missing submissionScore', () => expect(res.status).toBeCalledWith(404)) | ||
test('Responds with NotFound on missing submissionScore', () => expect(res.json).toBeCalledWith(NotFound)) | ||
test('Next not called on missing submissionScore', () => expect(next).toBeCalledTimes(0)) | ||
}) | ||
|
||
describe('400 - Bad Request', () => { | ||
test('Next called with expected error', async () => { | ||
SubmissionScoreService.retrieve = jest.fn().mockImplementation(() => Promise.reject(expectedError)) | ||
|
||
try { | ||
await controller.detail(req, res, next) | ||
|
||
fail('Expected test to throw') | ||
} catch { | ||
expect(next).toBeCalledWith(expectedError) | ||
} | ||
}) | ||
}) | ||
}) | ||
|
||
describe('POST - /submission-score/', () => { | ||
describe('201 - Created', () => { | ||
beforeEach(async () => { | ||
SubmissionScoreService.create = jest.fn().mockImplementation(() => Promise.resolve(mockedSubmissionScore)) | ||
await controller.post(req, res, next) | ||
}) | ||
|
||
test('Returns expected submissionScore', () => expect(res.json).toBeCalledWith(expectedResult)) | ||
test('Status code is 201', () => expect(res.status).toBeCalledWith(201)) | ||
}) | ||
|
||
describe('400 - Bad Request', () => { | ||
beforeEach(async () => { | ||
SubmissionScoreService.create = jest.fn().mockImplementation(() => Promise.reject(expectedError)) | ||
|
||
try { | ||
await controller.post(req, res, next) | ||
|
||
fail('Expected test to throw') | ||
} catch { | ||
// continue to tests | ||
} | ||
}) | ||
|
||
test('Status code is 400', () => expect(res.status).toBeCalledWith(400)) | ||
test('Responds with generic error', () => | ||
expect(res.json).toBeCalledWith(new GenericResponse(expectedError.message))) | ||
test('Next not called', () => expect(next).toBeCalledTimes(0)) | ||
}) | ||
}) | ||
|
||
describe('PUT - /submission-score/:id', () => { | ||
describe('200 - Ok', () => { | ||
beforeEach(async () => { | ||
expectedDbResult.affected = 1 // mocking service return shape | ||
SubmissionScoreService.update = jest.fn().mockImplementation(() => Promise.resolve(expectedDbResult)) | ||
await controller.put(req, res, next) | ||
}) | ||
|
||
test('Status code is 200', () => expect(res.status).toBeCalledWith(200)) | ||
test('Returns Updated message', () => expect(res.json).toBeCalledWith(Updated)) | ||
test('Next is not called', () => expect(next).toHaveBeenCalledTimes(0)) | ||
}) | ||
|
||
describe('404 - Not Found', () => { | ||
beforeEach(async () => { | ||
expectedDbResult.affected = 0 // No records affected in db | ||
SubmissionScoreService.update = jest.fn().mockImplementation(() => Promise.resolve(expectedDbResult)) | ||
await controller.put(req, res, next) | ||
}) | ||
|
||
test('Status code is 404', () => expect(res.status).toBeCalledWith(404)) | ||
test('Returns Not found message', () => expect(res.json).toBeCalledWith(NotFound)) | ||
test('Next is not called', () => expect(next).toHaveBeenCalledTimes(0)) | ||
}) | ||
|
||
describe('400 - Bad Request', () => { | ||
beforeEach(async () => { | ||
SubmissionScoreService.update = jest.fn().mockImplementation(() => Promise.reject(expectedError)) | ||
await controller.put(req, res, next) | ||
}) | ||
|
||
test('Next is called with error', () => expect(next).toBeCalledWith(expectedError)) | ||
}) | ||
}) | ||
|
||
describe('DELETE - /submission-score/:id', () => { | ||
describe('204 - No Content', () => { | ||
beforeEach(async () => { | ||
expectedDbResult.affected = 1 | ||
SubmissionScoreService._delete = jest.fn().mockImplementation(() => Promise.resolve(expectedDbResult)) | ||
await controller._delete(req, res, next) | ||
}) | ||
|
||
test('Status code is 204', () => expect(res.status).toBeCalledWith(204)) | ||
test('Response to have no content', () => expect(res.send).toBeCalledWith()) | ||
test('Next not called', () => expect(next).toBeCalledTimes(0)) | ||
}) | ||
|
||
describe('404 - Not Found', () => { | ||
beforeEach(async () => { | ||
expectedDbResult.affected = 0 | ||
SubmissionScoreService._delete = jest.fn().mockImplementation(() => Promise.resolve(expectedDbResult)) | ||
await controller._delete(req, res, next) | ||
}) | ||
|
||
test('Status code is 404', () => expect(res.status).toBeCalledWith(404)) | ||
test('Response to have no content', () => expect(res.json).toBeCalledWith(NotFound)) | ||
test('Next not called', () => expect(next).toBeCalledTimes(0)) | ||
}) | ||
|
||
describe('400 - Bad Request', () => { | ||
beforeEach(async () => { | ||
SubmissionScoreService._delete = jest.fn().mockImplementation(() => Promise.reject(expectedError)) | ||
await controller._delete(req, res, next) | ||
}) | ||
|
||
test('Next called with expected error', () => expect(next).toBeCalledWith(expectedError)) | ||
}) | ||
}) | ||
}) |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { check } from 'express-validator' | ||
|
||
import validate from './generic.validator' | ||
|
||
const submissionId = check('submissionId').isNumeric() | ||
const score = check('score').isNumeric().optional({ nullable: true }) | ||
const feedback = check('feedback').isString().trim().optional({ nullable: true }) | ||
const releasedAt = check('releasedAt').trim().isISO8601().toDate() | ||
|
||
const validator = [submissionId, score, feedback, releasedAt, validate] | ||
|
||
export default validator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
src/router/codeAssignments.router.ts → src/router/codeAssignment.router.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.