Skip to content

Commit

Permalink
CB2-14764: Update Test Result Service for recalls (#428)
Browse files Browse the repository at this point in the history
* feat(cb2-14764): bumped types def and updated joi validation

* feat(cb2-14764): linter

* feat(cb2-14764): allow empty string for manufacturer
  • Loading branch information
cb-cs authored Nov 25, 2024
1 parent 81b115a commit 886b721
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 5 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
"@aws-sdk/lib-dynamodb": "^3.632.0",
"@aws-sdk/smithy-client": "^3.374.0",
"@dvsa/cvs-microservice-common": "^1.2.4",
"@dvsa/cvs-type-definitions": "^7.6.1",
"@dvsa/cvs-type-definitions": "^7.7.1",
"@smithy/smithy-client": "^2.5.1",
"@smithy/util-utf8": "^2.3.0",
"aws-lambda": "^1.0.7",
Expand Down
6 changes: 6 additions & 0 deletions src/models/validators/TestResultsSchemaHGVCancelled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,10 @@ export const hgvCancelled = testResultsCommonSchema.keys({
.required(),
testTypes: Joi.array().items(testTypesSchema).required(),
regnDate: Joi.string().allow('', null),
recalls: Joi.object()
.keys({
hasRecall: Joi.boolean().required(),
manufacturer: Joi.string().required().allow('', null),
})
.optional(),
});
6 changes: 6 additions & 0 deletions src/models/validators/TestResultsSchemaHGVSubmitted.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,10 @@ export const hgvSubmitted = testResultsCommonSchema.keys({
.required(),
testTypes: Joi.array().items(testTypesSchema).required(),
regnDate: Joi.string().allow('', null),
recalls: Joi.object()
.keys({
hasRecall: Joi.boolean().required(),
manufacturer: Joi.string().required().allow('', null),
})
.optional(),
});
6 changes: 6 additions & 0 deletions src/models/validators/TestResultsSchemaPSVCancelled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,10 @@ export const psvCancelled = testResultsCommonSchema.keys({
countryOfRegistration: Joi.string().required().allow('', null),
vehicleSize: Joi.string().valid('small', 'large').required(),
testTypes: Joi.array().items(testTypesSchema).required(),
recalls: Joi.object()
.keys({
hasRecall: Joi.boolean().required(),
manufacturer: Joi.string().required().allow('', null),
})
.optional(),
});
6 changes: 6 additions & 0 deletions src/models/validators/TestResultsSchemaPSVSubmitted.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,10 @@ export const psvSubmitted = testResultsCommonSchema.keys({
vehicleSize: Joi.string().valid('small', 'large').required(),
reasonForCancellation: Joi.string().max(500).required().allow('', null),
testTypes: Joi.array().items(testTypesSchema).required(),
recalls: Joi.object()
.keys({
hasRecall: Joi.boolean().required(),
manufacturer: Joi.string().required().allow('', null),
})
.optional(),
});
6 changes: 6 additions & 0 deletions src/models/validators/TestResultsSchemaTRLCancelled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,10 @@ export const trlCancelled = testResultsCommonSchema.keys({
trailerId: Joi.string().required(),
testTypes: Joi.array().items(testTypesSchema).required(),
firstUseDate: Joi.string().allow('', null),
recalls: Joi.object()
.keys({
hasRecall: Joi.boolean().required(),
manufacturer: Joi.string().required().allow('', null),
})
.optional(),
});
6 changes: 6 additions & 0 deletions src/models/validators/TestResultsSchemaTRLSubmitted.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,10 @@ export const trlSubmitted = testResultsCommonSchema.keys({
trailerId: Joi.string().required(),
testTypes: Joi.array().items(testTypesSchema).required(),
firstUseDate: Joi.string().allow('', null),
recalls: Joi.object()
.keys({
hasRecall: Joi.boolean().required(),
manufacturer: Joi.string().required().allow('', null),
})
.optional(),
});
179 changes: 179 additions & 0 deletions tests/unit/insertTestResult.unitTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
TestTypeSchema,
} from '@dvsa/cvs-type-definitions/types/v1/test-result';
import { TestResults } from '@dvsa/cvs-type-definitions/types/v1/enums/testResult.enum';
import { RecallsSchema } from '@dvsa/cvs-type-definitions/types/v1/recalls';
import { TestStatus } from '@dvsa/cvs-type-definitions/types/v1/enums/testStatus.enum';
import {
ERRORS,
MESSAGES,
Expand Down Expand Up @@ -4252,4 +4254,181 @@ describe('insertTestResult', () => {
},
);
});

describe('Vehicle Recalls', () => {
let testResult: TestResultSchema;
let recallsMock: RecallsSchema;

describe('validateInsertTestResultPayload', () => {
describe('when inserting a test result with valid vehicle recalls present', () => {
context('and the status is submitted', () => {
beforeEach(() => {
testResult = { ...testResultsPostMock[0] } as TestResultSchema;
recallsMock = {
hasRecall: true,
manufacturer: 'manufacturer',
};
});

it('should create the record successfully when hasRecalls and manufacturer are present', () => {
testResult.recalls = recallsMock;
const validationResult =
ValidationUtil.validateInsertTestResultPayload(testResult);
expect(validationResult).toBe(true);
});

it('should create the record successfully when hasRecalls is present and manufacturer is null', () => {
recallsMock.manufacturer = null;
testResult.recalls = recallsMock;
const validationResult =
ValidationUtil.validateInsertTestResultPayload(testResult);
expect(validationResult).toBe(true);
});

it('should create the record successfully when hasRecalls is present and manufacturer is empty string', () => {
recallsMock.manufacturer = '';
testResult.recalls = recallsMock;
const validationResult =
ValidationUtil.validateInsertTestResultPayload(testResult);
expect(validationResult).toBe(true);
});

it('should create the record successfully when recalls object is not on payload', () => {
const validationResult =
ValidationUtil.validateInsertTestResultPayload(testResult);
expect(validationResult).toBe(true);
});
});
context('and the status is cancelled', () => {
beforeEach(() => {
testResult = { ...testResultsPostMock[0] } as TestResultSchema;
testResult.testStatus = 'cancelled' as TestStatus;
recallsMock = {
hasRecall: true,
manufacturer: 'manufacturer',
};
});

it('should create the record successfully when hasRecalls and manufacturer are present', () => {
testResult.recalls = recallsMock;
const validationResult =
ValidationUtil.validateInsertTestResultPayload(testResult);
expect(validationResult).toBe(true);
});

it('should create the record successfully when hasRecalls is present and manufacturer is null', () => {
recallsMock.manufacturer = null;
testResult.recalls = recallsMock;
const validationResult =
ValidationUtil.validateInsertTestResultPayload(testResult);
expect(validationResult).toBe(true);
});

it('should create the record successfully when hasRecalls is present and manufacturer is empty string', () => {
recallsMock.manufacturer = '';
testResult.recalls = recallsMock;
const validationResult =
ValidationUtil.validateInsertTestResultPayload(testResult);
expect(validationResult).toBe(true);
});

it('should create the record successfully when recalls object is not on payload', () => {
const validationResult =
ValidationUtil.validateInsertTestResultPayload(testResult);
expect(validationResult).toBe(true);
});
});
});
describe('when inserting a test result', () => {
beforeEach(() => {
testResult = { ...testResultsPostMock[0] } as TestResultSchema;
recallsMock = {
hasRecall: true,
manufacturer: 'manufacturer',
};
});

context('with an invalid recalls object value present', () => {
it('should throw validation error', () => {
testResult.recalls = true as any;
try {
ValidationUtil.validateInsertTestResultPayload(testResult);
} catch (error) {
expect(error).toBeInstanceOf(HTTPError);
expect(error.statusCode).toBe(400);
expect(error.body).toEqual({
errors: ['"recalls" must be of type object'],
});
}
});
});
context(
'with an invalid hasRecall value in recalls object present',
() => {
it('should throw validation error', () => {
recallsMock.hasRecall = 'dummy value' as any;
testResult.recalls = recallsMock;
try {
ValidationUtil.validateInsertTestResultPayload(testResult);
} catch (error) {
expect(error).toBeInstanceOf(HTTPError);
expect(error.statusCode).toBe(400);
expect(error.body).toEqual({
errors: ['"recalls.hasRecall" must be a boolean'],
});
}
});
},
);
context('with hasRecall missing from recalls object', () => {
it('should throw validation error', () => {
recallsMock.hasRecall = undefined as any;
testResult.recalls = recallsMock;
try {
ValidationUtil.validateInsertTestResultPayload(testResult);
} catch (error) {
expect(error).toBeInstanceOf(HTTPError);
expect(error.statusCode).toBe(400);
expect(error.body).toEqual({
errors: ['"recalls.hasRecall" is required'],
});
}
});
});
context(
'with an invalid manufacture value in recalls object present',
() => {
it('should throw validation error', () => {
recallsMock.manufacturer = 123 as any;
testResult.recalls = recallsMock;
try {
ValidationUtil.validateInsertTestResultPayload(testResult);
} catch (error) {
expect(error).toBeInstanceOf(HTTPError);
expect(error.statusCode).toBe(400);
expect(error.body).toEqual({
errors: ['"recalls.manufacturer" must be a string'],
});
}
});
},
);
context('with manufacturer missing from recalls object', () => {
it('should throw validation error', () => {
recallsMock.manufacturer = undefined as any;
testResult.recalls = recallsMock;
try {
ValidationUtil.validateInsertTestResultPayload(testResult);
} catch (error) {
expect(error).toBeInstanceOf(HTTPError);
expect(error.statusCode).toBe(400);
expect(error.body).toEqual({
errors: ['"recalls.manufacturer" is required'],
});
}
});
});
});
});
});
});

0 comments on commit 886b721

Please sign in to comment.