Skip to content

Commit

Permalink
feat(cb2-13154): Provide a '‘centralDocs'' object for VTx (#410)
Browse files Browse the repository at this point in the history
* feat(cb2-13154): added centralDoc object and validators + linting

* feat(cb2-13154): use differernt test result in int test

* feat(cb2-13154): linting

* feat(cb2-13154): comments

* feat(cb2-13154): Added validation when central docs is present on wrong test type

* feat(cb2-13154): utilise common repo helper function and id

* feat(cb2-13154): remove central doc from base test result

* feat(cb2-13154): made reason for issue mandatory

* feat(cb2-13154): replace .every with for each

* feat(cb2-13154): replace central docs with test type id

* feat(cb2-13154): change error message when invalid test type and central doc present
  • Loading branch information
Daniel-Searle authored Jul 26, 2024
1 parent c916a85 commit 6f2c245
Show file tree
Hide file tree
Showing 19 changed files with 519 additions and 21 deletions.
22 changes: 18 additions & 4 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"joi": "^17.12.1",
"js-yaml": "^3.14.1",
"lodash": "^4.17.21",
"@dvsa/cvs-microservice-common": "1.2.0",
"moment": "^2.29.4",
"moment-timezone": "^0.5.40",
"node-yaml": "^4.0.1",
Expand Down
7 changes: 7 additions & 0 deletions src/models/ITestResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ export interface TestType {
modificationTypeUsed?: string | null;
particulateTrapFitted?: string | null;
fuelType?: string | null;
centralDocs?: CentralDocs;
}

export interface CentralDocs {
issueRequired: boolean;
notes?: string;
reasonsForIssue: string[];
}

export interface Defect {
Expand Down
8 changes: 8 additions & 0 deletions src/models/validators/SpecialistTestsCommonSchemaCancelled.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as Joi from 'joi';
import { string } from 'joi';
import {
defectsCommonSchema,
testResultsCommonSchema,
Expand Down Expand Up @@ -45,6 +46,13 @@ export const testTypesCommonSchemaSpecialistTestsCancelled =
.items(requiredStandardsSchema.required())
.optional(),
reapplicationDate: Joi.date().optional().allow(null, ''),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string().optional()).required(),
})
.optional(),
});

export const testResultsCommonSchemaSpecialistTestsCancelled =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as Joi from 'joi';
import Joi, { string } from 'joi';
import {
defectsCommonSchema,
requiredStandardsSchema,
Expand Down Expand Up @@ -62,6 +62,13 @@ export const testTypesCommonSchemaSpecialistTestsSubmitted =
.required(),
requiredStandards: Joi.array().items(requiredStandardsSchema).optional(),
reapplicationDate: Joi.date().optional().allow(null, ''),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string().optional()).required(),
})
.optional(),
});

export const testResultsCommonSchemaSpecialistTestsSubmitted =
Expand Down
9 changes: 8 additions & 1 deletion src/models/validators/TestResultsSchemaHGVCancelled.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Joi from 'joi';
import { array } from 'joi';
import { array, string } from 'joi';
import {
defectsCommonSchema,
testTypesCommonSchema,
Expand Down Expand Up @@ -42,6 +42,13 @@ const testTypesSchema = testTypesCommonSchema.keys({
.items(requiredStandardsSchema.required())
.optional(),
reapplicationDate: Joi.date().optional().allow(null, ''),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string().optional()).required(),
})
.optional(),
});

export const hgvCancelled = testResultsCommonSchema.keys({
Expand Down
9 changes: 8 additions & 1 deletion src/models/validators/TestResultsSchemaHGVSubmitted.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Joi from 'joi';
import { array } from 'joi';
import { array, string } from 'joi';
import {
defectsCommonSchema,
testTypesCommonSchema,
Expand Down Expand Up @@ -42,6 +42,13 @@ const testTypesSchema = testTypesCommonSchema.keys({
.items(requiredStandardsSchema.required())
.optional(),
reapplicationDate: Joi.date().optional().allow(null, ''),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string().optional()).required(),
})
.optional(),
});

export const hgvSubmitted = testResultsCommonSchema.keys({
Expand Down
9 changes: 8 additions & 1 deletion src/models/validators/TestResultsSchemaPSVCancelled.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Joi from 'joi';
import { array } from 'joi';
import { array, string } from 'joi';
import {
defectsCommonSchema,
testTypesCommonSchema,
Expand Down Expand Up @@ -57,6 +57,13 @@ const testTypesSchema = testTypesCommonSchema.keys({
modificationTypeUsed: Joi.string().max(100).allow(null),
particulateTrapFitted: Joi.string().max(100).allow(null),
reapplicationDate: Joi.date().optional().allow(null, ''),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string().optional()).required(),
})
.optional(),
});

export const psvCancelled = testResultsCommonSchema.keys({
Expand Down
9 changes: 8 additions & 1 deletion src/models/validators/TestResultsSchemaPSVSubmitted.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Joi from 'joi';
import { array } from 'joi';
import { array, string } from 'joi';
import {
defectsCommonSchema,
testTypesCommonSchema,
Expand Down Expand Up @@ -57,6 +57,13 @@ const testTypesSchema = testTypesCommonSchema.keys({
modificationTypeUsed: Joi.string().max(100).allow(null),
particulateTrapFitted: Joi.string().max(100).allow(null),
reapplicationDate: Joi.date().optional().allow(null, ''),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string().optional()).required(),
})
.optional(),
});

export const psvSubmitted = testResultsCommonSchema.keys({
Expand Down
9 changes: 8 additions & 1 deletion src/models/validators/TestResultsSchemaTRLCancelled.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Joi from 'joi';
import { array } from 'joi';
import { array, string } from 'joi';
import {
defectsCommonSchema,
testTypesCommonSchema,
Expand Down Expand Up @@ -42,6 +42,13 @@ const testTypesSchema = testTypesCommonSchema.keys({
.items(requiredStandardsSchema.required())
.optional(),
reapplicationDate: Joi.date().optional().allow(null, ''),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string().optional()).required(),
})
.optional(),
});

export const trlCancelled = testResultsCommonSchema.keys({
Expand Down
9 changes: 8 additions & 1 deletion src/models/validators/TestResultsSchemaTRLSubmitted.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Joi from 'joi';
import { array } from 'joi';
import { array, string } from 'joi';
import {
defectsCommonSchema,
testTypesCommonSchema,
Expand Down Expand Up @@ -43,6 +43,13 @@ const testTypesSchema = testTypesCommonSchema.keys({
.items(requiredStandardsSchema.required())
.optional(),
reapplicationDate: Joi.date().optional().allow(null, ''),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string().optional()).required(),
})
.optional(),
});

export const trlSubmitted = testResultsCommonSchema.keys({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as Joi from 'joi';
import { string } from 'joi';
import { requiredStandardsSchema } from '../CommonSchema';

export const testTypesCommonSchemaDeskBasedTests = Joi.object().keys({
Expand All @@ -20,6 +21,13 @@ export const testTypesCommonSchemaDeskBasedTests = Joi.object().keys({
.items(requiredStandardsSchema.required())
.optional(),
customDefects: Joi.array().max(0).allow(null),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string()).optional(),
})
.optional(),
});

export const testTypesDeskBasedGroup1 =
Expand Down
8 changes: 8 additions & 0 deletions src/models/validators/test-types/testTypesSchemaPut.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as Joi from 'joi';
import { string } from 'joi';
import { defectsCommonSchema, requiredStandardsSchema } from '../CommonSchema';

const additionalInformationSchema = Joi.object().keys({
Expand Down Expand Up @@ -64,6 +65,13 @@ export const testTypesCommonSchema = Joi.object()
certificateLink: Joi.string().optional().allow(null),
testTypeClassification: Joi.string().required(),
deletionFlag: Joi.boolean().optional(),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string()).optional(),
})
.optional(),
})
.required();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as Joi from 'joi';
import { string } from 'joi';
import { defectsCommonSchemaSpecialistTestsSubmitted } from '../SpecialistTestsCommonSchemaSubmitted';
import { requiredStandardsSchema } from '../CommonSchema';

Expand Down Expand Up @@ -35,6 +36,13 @@ export const testTypesCommonSchemaSpecialistTests = Joi.object()
lastUpdatedAt: Joi.string().optional(),
certificateLink: Joi.string().optional(),
testTypeClassification: Joi.string().required(),
centralDocs: Joi.object()
.keys({
issueRequired: Joi.boolean().required(),
notes: Joi.string().optional(),
reasonsForIssue: Joi.array().items(string()).optional(),
})
.optional(),
})
.required();

Expand Down
43 changes: 41 additions & 2 deletions src/utils/validationUtil.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { ValidationResult, any, string } from 'joi';
import { any, string, ValidationResult } from 'joi';
import { isDate } from 'lodash';
import { TestTypeHelper } from '@dvsa/cvs-microservice-common/classes/testTypes/testTypeHelper';
import { CENTRAL_DOCS_TEST } from '@dvsa/cvs-microservice-common/classes/testTypes/Constants';
import * as enums from '../assets/Enums';
import * as models from '../models';
import { TestType } from '../models';
import * as validators from '../models/validators';
import { MappingUtil } from './mappingUtil';
import { TestType } from '../models';

export class ValidationUtil {
// #region [rgba(52, 152, 219, 0.15)] Public Functions
Expand Down Expand Up @@ -49,6 +51,8 @@ export class ValidationUtil {
// this.ivaFailedHasRequiredFields(payload.testTypes);
// }

this.validateCentralDocs(payload.testTypes);

const validation: ValidationResult<any> | any | null = validationSchema
? validationSchema.validate(payload)
: null;
Expand Down Expand Up @@ -569,4 +573,39 @@ export class ValidationUtil {
// throw new models.HTTPError(400, 'Failed IVA tests must have IVA Defects');
// }
}

/**
* Validates central docs for an array of test types
* @param testTypes TestType[]
* @throws HTTPError with status 400 if validation fails
*/
public static validateCentralDocs(testTypes: TestType[]): void {
testTypes.forEach((testType) => {
if (
TestTypeHelper.validateTestTypeIdInList(
CENTRAL_DOCS_TEST,
testType.testTypeId,
) &&
!testType?.centralDocs
) {
throw new models.HTTPError(
400,
`Central docs required for test type ${testType.testTypeId}`,
);
}
if (
!TestTypeHelper.validateTestTypeIdInList(
CENTRAL_DOCS_TEST,
testType.testTypeId,
) &&
testType?.centralDocs
) {
throw new models.HTTPError(
400,
`Central documents can not be issued for test type ${testType.testTypeId}`,
);
}
return true;
});
}
}
37 changes: 37 additions & 0 deletions tests/integration/postTestResults.intTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import supertest from 'supertest';
import { CENTRAL_DOCS_TEST } from '@dvsa/cvs-microservice-common/classes/testTypes/Constants';
import { ITestResultPayload } from '../../src/models';
import testResultsPostMock from '../resources/test-results-post.json';

const url = 'http://localhost:3006/';
const request = supertest(url);

describe('postTestResults', () => {
context('when submitting a test result with central docs', () => {
it('should return 400 when central docs are required but missing', async () => {
const testResult =
testResultsPostMock[15] as unknown as ITestResultPayload;

testResult.testTypes[0].testTypeId = CENTRAL_DOCS_TEST.IDS[3];
delete testResult.testTypes[0].centralDocs;

const res = await request.post('test-results').send(testResult);

expect(res.status).toBe(400);
expect(res.body).toBe('Central docs required for test type 47');
});
});

context('when submitting an invalid test result', () => {
it('should return 400 for missing required fields', async () => {
const testResult =
testResultsPostMock[10] as unknown as ITestResultPayload;
delete testResult.testResultId;
const res = await request.post('test-results').send(testResult);

console.log(res);
expect(res.status).toBe(400);
expect(res.body.errors).toContain('"testResultId" is required');
});
});
});
Loading

0 comments on commit 6f2c245

Please sign in to comment.