@planning-inspectorate/data-model 2.13.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/nsip-document.md +9 -5
- package/package.json +1 -1
- package/pins_data_model/models/model_appeal_document.py +1 -1
- package/pins_data_model/models/model_appeal_event.py +1 -1
- package/pins_data_model/models/model_appeal_event_estimate.py +1 -1
- package/pins_data_model/models/model_appeal_has.py +1 -1
- package/pins_data_model/models/model_appeal_representation.py +1 -1
- package/pins_data_model/models/model_appeal_s78.py +1 -1
- package/pins_data_model/models/model_dart_response.py +1 -1
- package/pins_data_model/models/model_entraid.py +1 -1
- package/pins_data_model/models/model_folder.py +1 -1
- package/pins_data_model/models/model_gettimesheets_response.py +1 -1
- package/pins_data_model/models/model_listed_building.py +1 -1
- package/pins_data_model/models/model_listed_buildings.py +1 -1
- package/pins_data_model/models/model_nsip_document.py +5 -1
- package/pins_data_model/models/model_nsip_exam_timetable.py +1 -1
- package/pins_data_model/models/model_nsip_invoice.py +1 -1
- package/pins_data_model/models/model_nsip_meeting.py +1 -1
- package/pins_data_model/models/model_nsip_project.py +1 -1
- package/pins_data_model/models/model_nsip_project_update.py +1 -1
- package/pins_data_model/models/model_nsip_representation.py +1 -1
- package/pins_data_model/models/model_nsip_subscription.py +1 -1
- package/pins_data_model/models/model_pins_inspector.py +1 -1
- package/pins_data_model/models/model_pins_lpa.py +1 -1
- package/pins_data_model/models/model_s51_advice.py +1 -1
- package/pins_data_model/models/model_service_user.py +1 -1
- package/schemas/commands/appellant-submission.schema.json +8 -0
- package/schemas/commands/lpa-questionnaire.schema.json +2 -2
- package/schemas/nsip-document.schema.json +9 -1
- package/src/enums.cjs +4 -0
- package/src/enums.d.ts +4 -0
- package/src/enums.js +4 -0
- package/src/index.cjs +4 -0
- package/src/schemas.d.ts +14 -3
- package/tests/appeals/commands/enforcement-listed-questionnaire.test.js +109 -0
- package/tests/appeals/commands/enforcement-listed-submission.test.js +187 -0
package/docs/nsip-document.md
CHANGED
|
@@ -516,11 +516,15 @@ The location of the published document. Only applicable to documents which are p
|
|
|
516
516
|
|
|
517
517
|
**enum**: the value of this property must be equal to one of the following values:
|
|
518
518
|
|
|
519
|
-
| Value
|
|
520
|
-
|
|
|
521
|
-
| `"not_redacted"`
|
|
522
|
-
| `"redacted"`
|
|
523
|
-
| `
|
|
519
|
+
| Value | Explanation |
|
|
520
|
+
| :------------------------------- | :---------- |
|
|
521
|
+
| `"not_redacted"` | |
|
|
522
|
+
| `"redacted"` | |
|
|
523
|
+
| `"awaiting_ai_redaction"` | |
|
|
524
|
+
| `"ai_redaction_review_required"` | |
|
|
525
|
+
| `"ai_redaction_failed"` | |
|
|
526
|
+
| `"no_redaction_required"` | |
|
|
527
|
+
| `null` | |
|
|
524
528
|
|
|
525
529
|
## publishedStatus
|
|
526
530
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# generated by datamodel-codegen:
|
|
2
2
|
# filename: nsip-document.schema.json
|
|
3
|
-
# timestamp: 2026-
|
|
3
|
+
# timestamp: 2026-02-05T10:08:01+00:00
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
@@ -25,6 +25,10 @@ class CaseType(Enum):
|
|
|
25
25
|
class RedactedStatus(Enum):
|
|
26
26
|
not_redacted = "not_redacted"
|
|
27
27
|
redacted = "redacted"
|
|
28
|
+
awaiting_ai_redaction = "awaiting_ai_redaction"
|
|
29
|
+
ai_redaction_review_required = "ai_redaction_review_required"
|
|
30
|
+
ai_redaction_failed = "ai_redaction_failed"
|
|
31
|
+
no_redaction_required = "no_redaction_required"
|
|
28
32
|
NoneType_None = None
|
|
29
33
|
|
|
30
34
|
|
|
@@ -73,6 +73,14 @@
|
|
|
73
73
|
{ "$ref": "appeals-components/appellant-procedure-preference.schema.json" },
|
|
74
74
|
{ "$ref": "appeals-components/appeal-ldc.submission.schema.json" }
|
|
75
75
|
]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"$comment": "Enforcement listed building",
|
|
79
|
+
"allOf": [
|
|
80
|
+
{ "properties": { "caseType": { "enum": ["F"] } } },
|
|
81
|
+
{ "$ref": "appeals-components/appeal-enforcement-submission.schema.json" },
|
|
82
|
+
{ "$ref": "appeals-components/appellant-procedure-preference.schema.json" }
|
|
83
|
+
]
|
|
76
84
|
}
|
|
77
85
|
]
|
|
78
86
|
},
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
]
|
|
72
72
|
},
|
|
73
73
|
{
|
|
74
|
-
"$comment": "Enforcement",
|
|
74
|
+
"$comment": "Enforcement + Enforcement listed building",
|
|
75
75
|
"allOf": [
|
|
76
|
-
{ "properties": { "caseType": { "enum": ["C"] } } },
|
|
76
|
+
{ "properties": { "caseType": { "enum": ["C", "F"] } } },
|
|
77
77
|
{ "$ref": "appeals-components/lpa-questionnaire-common.schema.json" },
|
|
78
78
|
{ "$ref": "appeals-components/lpa-questionnaire-has.schema.json" },
|
|
79
79
|
{ "$ref": "appeals-components/lpa-procedure-preference.schema.json" },
|
|
@@ -129,7 +129,15 @@
|
|
|
129
129
|
},
|
|
130
130
|
"redactedStatus": {
|
|
131
131
|
"type": ["string", "null"],
|
|
132
|
-
"enum": [
|
|
132
|
+
"enum": [
|
|
133
|
+
"not_redacted",
|
|
134
|
+
"redacted",
|
|
135
|
+
"awaiting_ai_redaction",
|
|
136
|
+
"ai_redaction_review_required",
|
|
137
|
+
"ai_redaction_failed",
|
|
138
|
+
"no_redaction_required",
|
|
139
|
+
null
|
|
140
|
+
]
|
|
133
141
|
},
|
|
134
142
|
"publishedStatus": {
|
|
135
143
|
"type": ["string", "null"],
|
package/src/enums.cjs
CHANGED
|
@@ -590,6 +590,10 @@ const NSIP_RECOMMENDATION = Object.freeze({
|
|
|
590
590
|
});
|
|
591
591
|
|
|
592
592
|
const NSIP_REDACTED_STATUS = Object.freeze({
|
|
593
|
+
AI_REDACTION_FAILED: 'ai_redaction_failed',
|
|
594
|
+
AI_REDACTION_REVIEW_REQUIRED: 'ai_redaction_review_required',
|
|
595
|
+
AWAITING_AI_REDACTION: 'awaiting_ai_redaction',
|
|
596
|
+
NO_REDACTION_REQUIRED: 'no_redaction_required',
|
|
593
597
|
NOT_REDACTED: 'not_redacted',
|
|
594
598
|
REDACTED: 'redacted',
|
|
595
599
|
});
|
package/src/enums.d.ts
CHANGED
|
@@ -588,6 +588,10 @@ export const NSIP_RECOMMENDATION = {
|
|
|
588
588
|
} as const;
|
|
589
589
|
|
|
590
590
|
export const NSIP_REDACTED_STATUS = {
|
|
591
|
+
AI_REDACTION_FAILED: 'ai_redaction_failed',
|
|
592
|
+
AI_REDACTION_REVIEW_REQUIRED: 'ai_redaction_review_required',
|
|
593
|
+
AWAITING_AI_REDACTION: 'awaiting_ai_redaction',
|
|
594
|
+
NO_REDACTION_REQUIRED: 'no_redaction_required',
|
|
591
595
|
NOT_REDACTED: 'not_redacted',
|
|
592
596
|
REDACTED: 'redacted',
|
|
593
597
|
} as const;
|
package/src/enums.js
CHANGED
|
@@ -588,6 +588,10 @@ export const NSIP_RECOMMENDATION = Object.freeze({
|
|
|
588
588
|
});
|
|
589
589
|
|
|
590
590
|
export const NSIP_REDACTED_STATUS = Object.freeze({
|
|
591
|
+
AI_REDACTION_FAILED: 'ai_redaction_failed',
|
|
592
|
+
AI_REDACTION_REVIEW_REQUIRED: 'ai_redaction_review_required',
|
|
593
|
+
AWAITING_AI_REDACTION: 'awaiting_ai_redaction',
|
|
594
|
+
NO_REDACTION_REQUIRED: 'no_redaction_required',
|
|
591
595
|
NOT_REDACTED: 'not_redacted',
|
|
592
596
|
REDACTED: 'redacted',
|
|
593
597
|
});
|
package/src/index.cjs
CHANGED
|
@@ -671,6 +671,10 @@ const NSIP_RECOMMENDATION = Object.freeze({
|
|
|
671
671
|
});
|
|
672
672
|
|
|
673
673
|
const NSIP_REDACTED_STATUS = Object.freeze({
|
|
674
|
+
AI_REDACTION_FAILED: 'ai_redaction_failed',
|
|
675
|
+
AI_REDACTION_REVIEW_REQUIRED: 'ai_redaction_review_required',
|
|
676
|
+
AWAITING_AI_REDACTION: 'awaiting_ai_redaction',
|
|
677
|
+
NO_REDACTION_REQUIRED: 'no_redaction_required',
|
|
674
678
|
NOT_REDACTED: 'not_redacted',
|
|
675
679
|
REDACTED: 'redacted',
|
|
676
680
|
});
|
package/src/schemas.d.ts
CHANGED
|
@@ -2115,7 +2115,14 @@ export interface NSIPDocument {
|
|
|
2115
2115
|
dateCreated: string;
|
|
2116
2116
|
lastModified: string | null;
|
|
2117
2117
|
caseType: 'nsip' | 'has' | null;
|
|
2118
|
-
redactedStatus:
|
|
2118
|
+
redactedStatus:
|
|
2119
|
+
| 'not_redacted'
|
|
2120
|
+
| 'redacted'
|
|
2121
|
+
| 'awaiting_ai_redaction'
|
|
2122
|
+
| 'ai_redaction_review_required'
|
|
2123
|
+
| 'ai_redaction_failed'
|
|
2124
|
+
| 'no_redaction_required'
|
|
2125
|
+
| null;
|
|
2119
2126
|
publishedStatus:
|
|
2120
2127
|
| 'not_checked'
|
|
2121
2128
|
| 'checked'
|
|
@@ -3986,7 +3993,11 @@ export interface AppellantSubmissionCommand {
|
|
|
3986
3993
|
} & AppellantCommonSubmissionProperties &
|
|
3987
3994
|
AppellantCommonPlanningProperties &
|
|
3988
3995
|
AppellantProcedurePreferenceProperties &
|
|
3989
|
-
LDCSpecificProperties)
|
|
3996
|
+
LDCSpecificProperties)
|
|
3997
|
+
| ({
|
|
3998
|
+
caseType?: 'F';
|
|
3999
|
+
} & AppellantEnforcementSubmissionProperties &
|
|
4000
|
+
AppellantProcedurePreferenceProperties);
|
|
3990
4001
|
documents: {
|
|
3991
4002
|
/**
|
|
3992
4003
|
* The unique identifier for the document
|
|
@@ -4590,7 +4601,7 @@ export interface LPAQuestionnaireCommand {
|
|
|
4590
4601
|
LPAProcedurePreferenceProperties &
|
|
4591
4602
|
ChangedListedBuildingNumbersProperties)
|
|
4592
4603
|
| ({
|
|
4593
|
-
caseType?: 'C';
|
|
4604
|
+
caseType?: 'C' | 'F';
|
|
4594
4605
|
} & LPAQCommonSubmissionProperties &
|
|
4595
4606
|
LPAQHASSubmissionProperties &
|
|
4596
4607
|
LPAProcedurePreferenceProperties &
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import Ajv from 'ajv';
|
|
4
|
+
import addFormats from 'ajv-formats';
|
|
5
|
+
import { loadAllSchemasSync } from '../../../src/index.js';
|
|
6
|
+
|
|
7
|
+
const schema = 'lpa-questionnaire.schema.json';
|
|
8
|
+
|
|
9
|
+
const document = {
|
|
10
|
+
documentId: 'deserunt sint aliqua adipisicing dolore',
|
|
11
|
+
filename: 'ut dolore',
|
|
12
|
+
originalFilename: 'Lorem amet fugiat adipisicing Excepteur',
|
|
13
|
+
size: -90476934,
|
|
14
|
+
mime: 'magna labore exercitation ut',
|
|
15
|
+
documentURI: 'ut reprehenderit',
|
|
16
|
+
dateCreated: '1933-04-03T03:24:38.0Z',
|
|
17
|
+
documentType: 'plansDrawings'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const exampleEnforcementListedQuestionnaireSchema = {
|
|
21
|
+
casedata: {
|
|
22
|
+
caseType: 'F',
|
|
23
|
+
caseReference: 'est ea elit in nulla',
|
|
24
|
+
lpaQuestionnaireSubmittedDate: null,
|
|
25
|
+
siteAccessDetails: ['velit adipisicing fugiat dolor ullamco'],
|
|
26
|
+
siteSafetyDetails: ['ut', 'dolore ut sint Duis', 'magna consequat quis laboris officia'],
|
|
27
|
+
nearbyCaseReferences: ['nulla', 'incididunt eu nostrud eiusmod', 'exercitation', 'Ut nostrud', 'eiusmod cillum eu'],
|
|
28
|
+
neighbouringSiteAddresses: null,
|
|
29
|
+
isCorrectAppealType: true,
|
|
30
|
+
affectedListedBuildingNumbers: null,
|
|
31
|
+
isGreenBelt: null,
|
|
32
|
+
inConservationArea: null,
|
|
33
|
+
newConditionDetails: null,
|
|
34
|
+
notificationMethod: ['irure', 'cillum tempor incididunt labore in'],
|
|
35
|
+
lpaCostsAppliedFor: true,
|
|
36
|
+
lpaStatement: 'ex laborum cupidatat',
|
|
37
|
+
changedListedBuildingNumbers: null,
|
|
38
|
+
affectsScheduledMonument: true,
|
|
39
|
+
hasProtectedSpecies: false,
|
|
40
|
+
isAonbNationalLandscape: true,
|
|
41
|
+
designatedSitesNames: ['quis nulla eu officia exercitation'],
|
|
42
|
+
hasTreePreservationOrder: null,
|
|
43
|
+
isGypsyOrTravellerSite: true,
|
|
44
|
+
isPublicRightOfWay: null,
|
|
45
|
+
eiaEnvironmentalImpactSchedule: 'schedule-2',
|
|
46
|
+
eiaDevelopmentDescription: 'production-processing-of-metals',
|
|
47
|
+
eiaSensitiveAreaDetails: null,
|
|
48
|
+
eiaColumnTwoThreshold: false,
|
|
49
|
+
eiaScreeningOpinion: false,
|
|
50
|
+
eiaRequiresEnvironmentalStatement: null,
|
|
51
|
+
eiaCompletedEnvironmentalStatement: true,
|
|
52
|
+
hasStatutoryConsultees: true,
|
|
53
|
+
consultedBodiesDetails: 'in in labore irure nostrud',
|
|
54
|
+
hasConsultationResponses: null,
|
|
55
|
+
hasEmergingPlan: null,
|
|
56
|
+
hasSupplementaryPlanningDocs: null,
|
|
57
|
+
hasInfrastructureLevy: true,
|
|
58
|
+
isInfrastructureLevyFormallyAdopted: false,
|
|
59
|
+
infrastructureLevyAdoptedDate: '1913-06-14T10:40:33.0Z',
|
|
60
|
+
infrastructureLevyExpectedDate: '1912-06-14T10:40:33.0Z',
|
|
61
|
+
lpaProcedurePreference: null,
|
|
62
|
+
lpaProcedurePreferenceDetails: 'in reprehenderit',
|
|
63
|
+
lpaProcedurePreferenceDuration: -34480053.16630782,
|
|
64
|
+
noticeRelatesToBuildingEngineeringMiningOther: null,
|
|
65
|
+
siteAreaSquareMetres: null,
|
|
66
|
+
hasAllegedBreachArea: null,
|
|
67
|
+
doesAllegedBreachCreateFloorSpace: null,
|
|
68
|
+
changeOfUseRefuseOrWaste: null,
|
|
69
|
+
changeOfUseMineralExtraction: null,
|
|
70
|
+
changeOfUseMineralStorage: null,
|
|
71
|
+
relatesToErectionOfBuildingOrBuildings: null,
|
|
72
|
+
relatesToBuildingWithAgriculturalPurpose: null,
|
|
73
|
+
relatesToBuildingSingleDwellingHouse: null,
|
|
74
|
+
affectedTrunkRoadName: null,
|
|
75
|
+
isSiteOnCrownLand: null,
|
|
76
|
+
article4AffectedDevelopmentRights: null
|
|
77
|
+
},
|
|
78
|
+
documents: [document]
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
describe('Enforcement listed building questionnaire command schema', () => {
|
|
82
|
+
const schemas = loadAllSchemasSync();
|
|
83
|
+
const flatSchemas = Object.values(schemas).reduce((a, c) => ({ ...a, ...c }), {});
|
|
84
|
+
const ajv = new Ajv({ schemas: flatSchemas, allErrors: true });
|
|
85
|
+
addFormats(ajv);
|
|
86
|
+
|
|
87
|
+
it('should allow valid schema for Enforcement listed building', () => {
|
|
88
|
+
const validationResult = ajv.validate(schema, exampleEnforcementListedQuestionnaireSchema);
|
|
89
|
+
assert.strictEqual(validationResult, true);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should reject missing caseReference', () => {
|
|
93
|
+
const test = structuredClone(exampleEnforcementListedQuestionnaireSchema);
|
|
94
|
+
delete test.casedata.caseReference;
|
|
95
|
+
const validationResult = ajv.validate(schema, test);
|
|
96
|
+
assert.strictEqual(validationResult, false);
|
|
97
|
+
assert.strictEqual(
|
|
98
|
+
ajv.errors.some((x) => x.message === "must have required property 'caseReference'"),
|
|
99
|
+
true
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should allow additional props', () => {
|
|
104
|
+
const test = structuredClone(exampleEnforcementListedQuestionnaireSchema);
|
|
105
|
+
test.test = 1;
|
|
106
|
+
const validationResult = ajv.validate(schema, test);
|
|
107
|
+
assert.strictEqual(validationResult, true);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import Ajv from 'ajv';
|
|
4
|
+
import addFormats from 'ajv-formats';
|
|
5
|
+
import { loadAllSchemasSync } from '../../../src/index.js';
|
|
6
|
+
|
|
7
|
+
const schema = 'appellant-submission.schema.json';
|
|
8
|
+
|
|
9
|
+
const user = {
|
|
10
|
+
salutation: 'nisi aute tempor Ut',
|
|
11
|
+
firstName: null,
|
|
12
|
+
lastName: null,
|
|
13
|
+
emailAddress: null,
|
|
14
|
+
telephoneNumber: 'irure',
|
|
15
|
+
organisation: null,
|
|
16
|
+
serviceUserType: 'Appellant'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const document = {
|
|
20
|
+
documentId: 'Lorem',
|
|
21
|
+
filename: 'sunt',
|
|
22
|
+
originalFilename: 'dolore fugiat',
|
|
23
|
+
size: 663667,
|
|
24
|
+
mime: 'consequat veniam ipsum ullamco sint',
|
|
25
|
+
documentURI: 'reprehenderit',
|
|
26
|
+
dateCreated: '1904-04-10T14:53:32.0Z',
|
|
27
|
+
documentType: 'priorCorrespondenceWithPINS'
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const exampleEnforcementListedSubmissionSchema = {
|
|
31
|
+
casedata: {
|
|
32
|
+
caseType: 'F',
|
|
33
|
+
submissionId: '4b78fc58-fcb0-70d6-5dea-b9b774f802d6',
|
|
34
|
+
caseProcedure: 'written',
|
|
35
|
+
lpaCode: 'cupidatat',
|
|
36
|
+
caseSubmittedDate: '1890-12-28T22:49:47.0Z',
|
|
37
|
+
enforcementNotice: true,
|
|
38
|
+
enforcementReference: '12345',
|
|
39
|
+
enforcementIssueDate: '1890-12-28T22:49:47.0Z',
|
|
40
|
+
enforcementEffectiveDate: '1890-12-28T22:49:47.0Z',
|
|
41
|
+
contactPlanningInspectorateDate: null,
|
|
42
|
+
interestInLand: 'owner',
|
|
43
|
+
writtenOrVerbalPermission: null,
|
|
44
|
+
descriptionOfAllegedBreach: 'a new chimney',
|
|
45
|
+
applicationMadeAndFeePaid: true,
|
|
46
|
+
applicationDevelopmentAllOrPart: 'all-of-the-development',
|
|
47
|
+
originalDevelopmentDescription: 'in amet',
|
|
48
|
+
changedDevelopmentDescription: true,
|
|
49
|
+
applicationReference: '43010/APP/1/290572',
|
|
50
|
+
applicationDate: '1890-12-28T22:49:47.0Z',
|
|
51
|
+
applicationDecision: 'granted',
|
|
52
|
+
applicationDecisionAppealed: false,
|
|
53
|
+
applicationDecisionDate: '1890-12-28T22:49:47.0Z',
|
|
54
|
+
appealDecisionDate: null,
|
|
55
|
+
caseSubmissionDueDate: null,
|
|
56
|
+
siteAddressLine1: 'occaecat aliquip non pariatur consequat',
|
|
57
|
+
siteAddressLine2: null,
|
|
58
|
+
siteAddressTown: 'et',
|
|
59
|
+
siteAddressCounty: 'velit',
|
|
60
|
+
siteAddressPostcode: 'nisi minim laboris sed',
|
|
61
|
+
siteGridReferenceEasting: '357144',
|
|
62
|
+
siteGridReferenceNorthing: '400534',
|
|
63
|
+
contactAddressLine1: null,
|
|
64
|
+
contactAddressLine2: null,
|
|
65
|
+
contactAddressTown: null,
|
|
66
|
+
contactAddressCounty: null,
|
|
67
|
+
contactAddressPostcode: null,
|
|
68
|
+
contactGridReferenceEasting: null,
|
|
69
|
+
contactGridReferenceNorthing: null,
|
|
70
|
+
siteAccessDetails: ['laborum', 'aute velit quis', 'dolor'],
|
|
71
|
+
siteSafetyDetails: ['velit aliqua', 'qui', 'tempor Duis ut dolore', 'anim Ut in ea', 'eiusmod laborum'],
|
|
72
|
+
appellantCostsAppliedFor: false,
|
|
73
|
+
appellantProcedurePreference: null,
|
|
74
|
+
appellantProcedurePreferenceDetails: 'eiusmod ex exercitation',
|
|
75
|
+
appellantProcedurePreferenceDuration: 10816414.941069126,
|
|
76
|
+
appellantProcedurePreferenceWitnessCount: -91300569.36444478,
|
|
77
|
+
statusPlanningObligation: 'proident aute',
|
|
78
|
+
nearbyCaseReferences: ['incididunt'],
|
|
79
|
+
namedIndividuals: [
|
|
80
|
+
{
|
|
81
|
+
firstName: 'Bob',
|
|
82
|
+
lastName: 'Bobberson',
|
|
83
|
+
interestInLand: 'owner',
|
|
84
|
+
writtenOrVerbalPermission: 'yes'
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
appealGrounds: [
|
|
88
|
+
{
|
|
89
|
+
groundRef: 'a',
|
|
90
|
+
factsForGround: 'I like Christmas'
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
documents: [document],
|
|
95
|
+
users: [user]
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
describe(' listed building submission command schema', () => {
|
|
99
|
+
const schemas = loadAllSchemasSync();
|
|
100
|
+
const flatSchemas = Object.values(schemas).reduce((a, c) => ({ ...a, ...c }), {});
|
|
101
|
+
const ajv = new Ajv({ schemas: flatSchemas, allErrors: true });
|
|
102
|
+
addFormats(ajv);
|
|
103
|
+
|
|
104
|
+
it('should allow valid schema for enforcement listed building', () => {
|
|
105
|
+
const validationResult = ajv.validate(schema, exampleEnforcementListedSubmissionSchema);
|
|
106
|
+
assert.strictEqual(validationResult, true);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should enforce eastings-northings pattern', () => {
|
|
110
|
+
const invalidPatterns = [
|
|
111
|
+
{ easting: 'abc123', northing: '400534', description: 'easting with letters' },
|
|
112
|
+
{ easting: '1234567*', northing: '400534', description: 'easting too long' },
|
|
113
|
+
{ easting: '12345', northing: '400534', description: 'easting too short' },
|
|
114
|
+
{ easting: '357144', northing: 'xyz123', description: 'northing with letters' },
|
|
115
|
+
{ easting: '357144', northing: '12345678', description: 'northing too long' },
|
|
116
|
+
{ easting: '357144', northing: '12345', description: 'northing too short' },
|
|
117
|
+
{ easting: '', northing: '400534', description: 'empty easting' },
|
|
118
|
+
{ easting: '357144', northing: '', description: 'empty northing' }
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
for (const pattern of invalidPatterns) {
|
|
122
|
+
const test = structuredClone(exampleEnforcementListedSubmissionSchema);
|
|
123
|
+
test.casedata.siteGridReferenceEasting = pattern.easting;
|
|
124
|
+
test.casedata.siteGridReferenceNorthing = pattern.northing;
|
|
125
|
+
|
|
126
|
+
const validationResult = ajv.validate(schema, test);
|
|
127
|
+
assert.strictEqual(validationResult, false, `Expected validation to fail for ${pattern.description}`);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should allow only eastings-northings', () => {
|
|
132
|
+
const test = structuredClone(exampleEnforcementListedSubmissionSchema);
|
|
133
|
+
test.casedata.siteAddressPostcode = undefined;
|
|
134
|
+
test.casedata.siteAddressLine1 = null;
|
|
135
|
+
test.casedata.siteAddressTown = null;
|
|
136
|
+
const validationResult = ajv.validate(schema, test);
|
|
137
|
+
assert.strictEqual(validationResult, true);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should allow only site address', () => {
|
|
141
|
+
const test = structuredClone(exampleEnforcementListedSubmissionSchema);
|
|
142
|
+
test.casedata.siteGridReferenceEasting = undefined;
|
|
143
|
+
test.casedata.siteGridReferenceNorthing = null;
|
|
144
|
+
const validationResult = ajv.validate(schema, test);
|
|
145
|
+
assert.strictEqual(validationResult, true);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should enforce either site address or easting-northing', () => {
|
|
149
|
+
const test = structuredClone(exampleEnforcementListedSubmissionSchema);
|
|
150
|
+
test.casedata.siteAddressPostcode = undefined;
|
|
151
|
+
test.casedata.siteAddressLine1 = null;
|
|
152
|
+
test.casedata.siteAddressTown = null;
|
|
153
|
+
test.casedata.siteGridReferenceEasting = undefined;
|
|
154
|
+
test.casedata.siteGridReferenceNorthing = null;
|
|
155
|
+
const validationResult = ajv.validate(schema, test);
|
|
156
|
+
assert.strictEqual(validationResult, false);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should reject missing root property', () => {
|
|
160
|
+
const test = structuredClone(exampleEnforcementListedSubmissionSchema);
|
|
161
|
+
delete test.casedata.caseType;
|
|
162
|
+
const validationResult = ajv.validate(schema, test);
|
|
163
|
+
assert.strictEqual(validationResult, false);
|
|
164
|
+
assert.strictEqual(
|
|
165
|
+
ajv.errors.some((x) => x.message === "must have required property 'caseType'"),
|
|
166
|
+
true
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('should reject missing nested property', () => {
|
|
171
|
+
const test = structuredClone(exampleEnforcementListedSubmissionSchema);
|
|
172
|
+
delete test.casedata.caseProcedure;
|
|
173
|
+
const validationResult = ajv.validate(schema, test);
|
|
174
|
+
assert.strictEqual(validationResult, false);
|
|
175
|
+
assert.strictEqual(
|
|
176
|
+
ajv.errors.some((x) => x.message === "must have required property 'caseProcedure'"),
|
|
177
|
+
true
|
|
178
|
+
);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should allow additional props', () => {
|
|
182
|
+
const test = structuredClone(exampleEnforcementListedSubmissionSchema);
|
|
183
|
+
test.test = 1;
|
|
184
|
+
const validationResult = ajv.validate(schema, test);
|
|
185
|
+
assert.strictEqual(validationResult, true);
|
|
186
|
+
});
|
|
187
|
+
});
|