@pdtf/schemas 3.6.0-30 → 3.6.0-32
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/sef25-extensions-ui-spec.md +274 -5
- package/index.js +9 -0
- package/package.json +1 -1
- package/src/schemas/v3/combined.json +419 -69
- package/src/schemas/v3/compactSkeleton.txt +24 -5
- package/src/schemas/v3/overlays/extensions/as.json +4 -2
- package/src/schemas/v3/overlays/extensions/dk.json +32 -0
- package/src/schemas/v3/overlays/extensions/dr.json +4 -2
- package/src/schemas/v3/overlays/extensions/er.json +4 -2
- package/src/schemas/v3/overlays/extensions/fd.json +6 -3
- package/src/schemas/v3/overlays/extensions/hi.json +6 -3
- package/src/schemas/v3/overlays/extensions/hs.json +4 -2
- package/src/schemas/v3/overlays/extensions/ic.json +56 -0
- package/src/schemas/v3/overlays/extensions/jk.json +4 -2
- package/src/schemas/v3/overlays/extensions/la.json +4 -2
- package/src/schemas/v3/overlays/extensions/lc.json +86 -0
- package/src/schemas/v3/overlays/extensions/ma.json +6 -3
- package/src/schemas/v3/overlays/extensions/mc.json +4 -2
- package/src/schemas/v3/overlays/extensions/mi.json +52 -0
- package/src/schemas/v3/overlays/extensions/nd.json +43 -0
- package/src/schemas/v3/overlays/extensions/oa.json +4 -2
- package/src/schemas/v3/overlays/extensions/oc.json +4 -2
- package/src/schemas/v3/overlays/extensions/pc.json +2 -1
- package/src/schemas/v3/overlays/extensions/rw.json +68 -0
- package/src/schemas/v3/overlays/extensions/sb.json +4 -2
- package/src/schemas/v3/overlays/extensions/sc.json +82 -14
- package/src/schemas/v3/overlays/extensions/sd.json +63 -0
- package/src/schemas/v3/overlays/extensions/sf.json +4 -2
- package/src/schemas/v3/overlays/extensions/sl.json +4 -2
- package/src/schemas/v3/overlays/extensions/tf.json +6 -3
- package/src/schemas/v3/overlays/extensions/tr.json +73 -0
- package/src/schemas/v3/overlays/extensions/wg.json +209 -0
- package/src/schemas/v3/overlays/ta6ed6.json +37 -18
- package/src/schemas/v3/pdtf-transaction.json +477 -51
- package/src/schemas/v3/skeleton.json +33 -10
- package/src/tests/v3/extensionOverlays.test.js +410 -4
- package/src/tests/v3/ta6ed6.test.js +1 -48
- package/src/utils/extractExtensionOverlays.js +121 -0
|
@@ -166,7 +166,13 @@
|
|
|
166
166
|
},
|
|
167
167
|
"yearOfBuild": "integer",
|
|
168
168
|
"isNewBuild": {
|
|
169
|
-
"yesNo": "
|
|
169
|
+
"yesNo": "variant",
|
|
170
|
+
"newBuildDetails": {
|
|
171
|
+
"snaggingCompletion": "string",
|
|
172
|
+
"adoptionStatus": "string",
|
|
173
|
+
"conversionConsent": "boolean",
|
|
174
|
+
"conversionQuality": "string"
|
|
175
|
+
}
|
|
170
176
|
},
|
|
171
177
|
"isHMO": "string",
|
|
172
178
|
"isStudentAccommodation": "string",
|
|
@@ -289,6 +295,10 @@
|
|
|
289
295
|
"details": "string",
|
|
290
296
|
"amount": "number"
|
|
291
297
|
},
|
|
298
|
+
"titleRestrictions": {
|
|
299
|
+
"yesNo": "variant",
|
|
300
|
+
"details": "string"
|
|
301
|
+
},
|
|
292
302
|
"wholeFreeholdForSale": {
|
|
293
303
|
"yesNo": "variant",
|
|
294
304
|
"details": "string"
|
|
@@ -1229,6 +1239,9 @@
|
|
|
1229
1239
|
"yesNo": "variant",
|
|
1230
1240
|
"details": "string"
|
|
1231
1241
|
},
|
|
1242
|
+
"droppedKerbAccess": {
|
|
1243
|
+
"yesNo": "string"
|
|
1244
|
+
},
|
|
1232
1245
|
"electricVehicleChargingPoint": {
|
|
1233
1246
|
"yesNo": "variant",
|
|
1234
1247
|
"chargerDetails": "string",
|
|
@@ -2386,7 +2399,12 @@
|
|
|
2386
2399
|
"panelsOwnedOutright": {
|
|
2387
2400
|
"yesNo": "variant",
|
|
2388
2401
|
"details": "string",
|
|
2389
|
-
"attachments": "string"
|
|
2402
|
+
"attachments": "string",
|
|
2403
|
+
"associatedCost": {
|
|
2404
|
+
"hasCost": "variant",
|
|
2405
|
+
"amount": "number",
|
|
2406
|
+
"frequency": "string"
|
|
2407
|
+
}
|
|
2390
2408
|
},
|
|
2391
2409
|
"panelProviderLease": {
|
|
2392
2410
|
"yesNo": "variant",
|
|
@@ -2449,6 +2467,7 @@
|
|
|
2449
2467
|
"yesNo": "variant",
|
|
2450
2468
|
"details": "string",
|
|
2451
2469
|
"associatedCost": {
|
|
2470
|
+
"hasCost": "variant",
|
|
2452
2471
|
"amount": "number",
|
|
2453
2472
|
"frequency": "string"
|
|
2454
2473
|
},
|
|
@@ -2511,17 +2530,19 @@
|
|
|
2511
2530
|
},
|
|
2512
2531
|
"dischargeCompliesWithGBR": "string"
|
|
2513
2532
|
},
|
|
2533
|
+
"dateDischargeCommenced": {},
|
|
2534
|
+
"dateInstalled": "string",
|
|
2514
2535
|
"dateReplaced": "string",
|
|
2515
2536
|
"dateLastEmptied": "string",
|
|
2516
2537
|
"supplier": "string",
|
|
2517
2538
|
"makeModel": "string",
|
|
2518
2539
|
"serviceProviderName": "string",
|
|
2519
|
-
"dateInstalled": "string",
|
|
2520
2540
|
"dateLastServiced": "string",
|
|
2521
2541
|
"attachments": "string",
|
|
2522
2542
|
"details": "string"
|
|
2523
2543
|
},
|
|
2524
2544
|
"associatedCost": {
|
|
2545
|
+
"hasCost": "variant",
|
|
2525
2546
|
"amount": "number",
|
|
2526
2547
|
"frequency": "string"
|
|
2527
2548
|
}
|
|
@@ -2735,6 +2756,10 @@
|
|
|
2735
2756
|
"details": "string",
|
|
2736
2757
|
"attachments": "string"
|
|
2737
2758
|
},
|
|
2759
|
+
"privateRightOfWay": {
|
|
2760
|
+
"yesNo": "variant",
|
|
2761
|
+
"details": "string"
|
|
2762
|
+
},
|
|
2738
2763
|
"rightsOfLight": {
|
|
2739
2764
|
"yesNo": "variant",
|
|
2740
2765
|
"details": "string"
|
|
@@ -2814,6 +2839,10 @@
|
|
|
2814
2839
|
"details": "string"
|
|
2815
2840
|
}
|
|
2816
2841
|
},
|
|
2842
|
+
"stormFireFloodDamage": {
|
|
2843
|
+
"yesNo": "variant",
|
|
2844
|
+
"details": "string"
|
|
2845
|
+
},
|
|
2817
2846
|
"radon": {
|
|
2818
2847
|
"radonRisk": {
|
|
2819
2848
|
"riskIndicator": "string",
|
|
@@ -3340,13 +3369,7 @@
|
|
|
3340
3369
|
},
|
|
3341
3370
|
"confirmationOfAccuracyByOwners": {
|
|
3342
3371
|
"confirmWillProvideAdditionalDocumentation": "boolean",
|
|
3343
|
-
"confirmInformationIsAccurate": "boolean"
|
|
3344
|
-
"sellerSignatures": [
|
|
3345
|
-
{
|
|
3346
|
-
"name": "string",
|
|
3347
|
-
"signedOn": "string"
|
|
3348
|
-
}
|
|
3349
|
-
]
|
|
3372
|
+
"confirmInformationIsAccurate": "boolean"
|
|
3350
3373
|
},
|
|
3351
3374
|
"saleReadyDeclarations": {
|
|
3352
3375
|
"authorisedToActOnBehalfOfAllSellers": "boolean",
|
|
@@ -165,6 +165,15 @@ describe("Extension Overlays", () => {
|
|
|
165
165
|
"sc",
|
|
166
166
|
"pc",
|
|
167
167
|
"ph", // SEF25
|
|
168
|
+
"dk",
|
|
169
|
+
"rw",
|
|
170
|
+
"sd",
|
|
171
|
+
"lc",
|
|
172
|
+
"wg",
|
|
173
|
+
"ic",
|
|
174
|
+
"nd",
|
|
175
|
+
"mi",
|
|
176
|
+
"tr", // SEF25 (new)
|
|
168
177
|
];
|
|
169
178
|
|
|
170
179
|
expect(Object.keys(extensionOverlays).sort()).toEqual(
|
|
@@ -486,9 +495,14 @@ describe("Extension Overlays", () => {
|
|
|
486
495
|
const cost = noBranch?.properties?.associatedCost;
|
|
487
496
|
expect(cost).toBeDefined();
|
|
488
497
|
expect(cost.sef25Ref).toBe("U1.1");
|
|
489
|
-
expect(cost.required).toEqual(["
|
|
490
|
-
expect(cost.properties.
|
|
491
|
-
expect(cost.
|
|
498
|
+
expect(cost.required).toEqual(["hasCost"]);
|
|
499
|
+
expect(cost.properties.hasCost.type).toBe("string");
|
|
500
|
+
expect(cost.oneOf).toHaveLength(2);
|
|
501
|
+
// Yes branch should have amount and frequency
|
|
502
|
+
const yesBranch = cost.oneOf[1];
|
|
503
|
+
expect(yesBranch.properties.amount.type).toBe("number");
|
|
504
|
+
expect(yesBranch.properties.frequency.type).toBe("string");
|
|
505
|
+
expect(yesBranch.required).toEqual(["amount", "frequency"]);
|
|
492
506
|
});
|
|
493
507
|
|
|
494
508
|
test("should merge supply costs extension into mainsFoulDrainage No/Not known branch", () => {
|
|
@@ -504,7 +518,7 @@ describe("Extension Overlays", () => {
|
|
|
504
518
|
const cost = noBranch?.properties?.associatedCost;
|
|
505
519
|
expect(cost).toBeDefined();
|
|
506
520
|
expect(cost.sef25Ref).toBe("U1.2");
|
|
507
|
-
expect(cost.required).toEqual(["
|
|
521
|
+
expect(cost.required).toEqual(["hasCost"]);
|
|
508
522
|
});
|
|
509
523
|
|
|
510
524
|
test("should merge parking permit cost and frequency into controlledParking Yes branch", () => {
|
|
@@ -634,6 +648,7 @@ describe("Extension Overlays", () => {
|
|
|
634
648
|
yesNo: "No",
|
|
635
649
|
details: "Private borehole",
|
|
636
650
|
associatedCost: {
|
|
651
|
+
hasCost: "Yes",
|
|
637
652
|
amount: 50,
|
|
638
653
|
frequency: "Per month",
|
|
639
654
|
},
|
|
@@ -642,6 +657,24 @@ describe("Extension Overlays", () => {
|
|
|
642
657
|
expect(result).toBe(true);
|
|
643
658
|
});
|
|
644
659
|
|
|
660
|
+
test("should validate private water with no associated costs", () => {
|
|
661
|
+
const validator = getSubschemaValidator(
|
|
662
|
+
"/propertyPack/waterAndDrainage/water/mainsWater",
|
|
663
|
+
schemaId,
|
|
664
|
+
overlays
|
|
665
|
+
);
|
|
666
|
+
|
|
667
|
+
const result = validator({
|
|
668
|
+
yesNo: "No",
|
|
669
|
+
details: "Private borehole",
|
|
670
|
+
associatedCost: {
|
|
671
|
+
hasCost: "No",
|
|
672
|
+
},
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
expect(result).toBe(true);
|
|
676
|
+
});
|
|
677
|
+
|
|
645
678
|
test("should require associated cost for private water supply", () => {
|
|
646
679
|
const validator = getSubschemaValidator(
|
|
647
680
|
"/propertyPack/waterAndDrainage/water/mainsWater",
|
|
@@ -669,6 +702,7 @@ describe("Extension Overlays", () => {
|
|
|
669
702
|
yesNo: "No",
|
|
670
703
|
details: "Borehole",
|
|
671
704
|
associatedCost: {
|
|
705
|
+
hasCost: "Yes",
|
|
672
706
|
amount: 100,
|
|
673
707
|
frequency: "Weekly",
|
|
674
708
|
},
|
|
@@ -688,6 +722,7 @@ describe("Extension Overlays", () => {
|
|
|
688
722
|
yesNo: "No",
|
|
689
723
|
details: "Borehole",
|
|
690
724
|
associatedCost: {
|
|
725
|
+
hasCost: "Yes",
|
|
691
726
|
amount: "fifty pounds",
|
|
692
727
|
frequency: "Per month",
|
|
693
728
|
},
|
|
@@ -707,6 +742,7 @@ describe("Extension Overlays", () => {
|
|
|
707
742
|
const result = validator({
|
|
708
743
|
yesNo: "No",
|
|
709
744
|
associatedCost: {
|
|
745
|
+
hasCost: "Yes",
|
|
710
746
|
amount: 200,
|
|
711
747
|
frequency: "Per year",
|
|
712
748
|
},
|
|
@@ -725,6 +761,7 @@ describe("Extension Overlays", () => {
|
|
|
725
761
|
const result = validator({
|
|
726
762
|
yesNo: "No",
|
|
727
763
|
associatedCost: {
|
|
764
|
+
hasCost: "Yes",
|
|
728
765
|
amount: 200,
|
|
729
766
|
frequency: "Quarterly",
|
|
730
767
|
},
|
|
@@ -957,5 +994,374 @@ describe("Extension Overlays", () => {
|
|
|
957
994
|
);
|
|
958
995
|
});
|
|
959
996
|
});
|
|
997
|
+
|
|
998
|
+
describe("Dropped kerb (dk)", () => {
|
|
999
|
+
test("should validate Yes answer", () => {
|
|
1000
|
+
const validator = getSubschemaValidator(
|
|
1001
|
+
"/propertyPack/parking/droppedKerbAccess",
|
|
1002
|
+
schemaId,
|
|
1003
|
+
["dk"]
|
|
1004
|
+
);
|
|
1005
|
+
expect(validator({ yesNo: "Yes" })).toBe(true);
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
test("should validate No answer", () => {
|
|
1009
|
+
const validator = getSubschemaValidator(
|
|
1010
|
+
"/propertyPack/parking/droppedKerbAccess",
|
|
1011
|
+
schemaId,
|
|
1012
|
+
["dk"]
|
|
1013
|
+
);
|
|
1014
|
+
expect(validator({ yesNo: "No" })).toBe(true);
|
|
1015
|
+
});
|
|
1016
|
+
|
|
1017
|
+
test("should reject invalid value", () => {
|
|
1018
|
+
const validator = getSubschemaValidator(
|
|
1019
|
+
"/propertyPack/parking/droppedKerbAccess",
|
|
1020
|
+
schemaId,
|
|
1021
|
+
["dk"]
|
|
1022
|
+
);
|
|
1023
|
+
expect(validator({ yesNo: "Maybe" })).toBe(false);
|
|
1024
|
+
});
|
|
1025
|
+
|
|
1026
|
+
test("should not be required without dk overlay", () => {
|
|
1027
|
+
const schema = getTransactionSchema(schemaId, ["baspiV5"]);
|
|
1028
|
+
const parking = schema.properties?.propertyPack?.properties?.parking;
|
|
1029
|
+
expect(parking?.required || []).not.toContain("droppedKerbAccess");
|
|
1030
|
+
});
|
|
1031
|
+
|
|
1032
|
+
test("should be required with dk overlay", () => {
|
|
1033
|
+
const schema = getTransactionSchema(schemaId, ["dk"]);
|
|
1034
|
+
const parking = schema.properties?.propertyPack?.properties?.parking;
|
|
1035
|
+
expect(parking?.required).toContain("droppedKerbAccess");
|
|
1036
|
+
});
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
describe("Private right of way (rw)", () => {
|
|
1040
|
+
test("should validate No answer", () => {
|
|
1041
|
+
const validator = getSubschemaValidator(
|
|
1042
|
+
"/propertyPack/rightsAndInformalArrangements/rightsOrArrangements/privateRightOfWay",
|
|
1043
|
+
schemaId,
|
|
1044
|
+
["rw"]
|
|
1045
|
+
);
|
|
1046
|
+
expect(validator({ yesNo: "No" })).toBe(true);
|
|
1047
|
+
});
|
|
1048
|
+
|
|
1049
|
+
test("should validate Yes with details", () => {
|
|
1050
|
+
const validator = getSubschemaValidator(
|
|
1051
|
+
"/propertyPack/rightsAndInformalArrangements/rightsOrArrangements/privateRightOfWay",
|
|
1052
|
+
schemaId,
|
|
1053
|
+
["rw"]
|
|
1054
|
+
);
|
|
1055
|
+
expect(validator({ yesNo: "Yes", details: "Neighbour has access through garden" })).toBe(true);
|
|
1056
|
+
});
|
|
1057
|
+
|
|
1058
|
+
test("should reject Yes without details", () => {
|
|
1059
|
+
const validator = getSubschemaValidator(
|
|
1060
|
+
"/propertyPack/rightsAndInformalArrangements/rightsOrArrangements/privateRightOfWay",
|
|
1061
|
+
schemaId,
|
|
1062
|
+
["rw"]
|
|
1063
|
+
);
|
|
1064
|
+
expect(validator({ yesNo: "Yes" })).toBe(false);
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
test("should reject Yes with empty details", () => {
|
|
1068
|
+
const validator = getSubschemaValidator(
|
|
1069
|
+
"/propertyPack/rightsAndInformalArrangements/rightsOrArrangements/privateRightOfWay",
|
|
1070
|
+
schemaId,
|
|
1071
|
+
["rw"]
|
|
1072
|
+
);
|
|
1073
|
+
expect(validator({ yesNo: "Yes", details: "" })).toBe(false);
|
|
1074
|
+
});
|
|
1075
|
+
|
|
1076
|
+
test("should not be required without rw overlay", () => {
|
|
1077
|
+
const schema = getTransactionSchema(schemaId, ["baspiV5"]);
|
|
1078
|
+
const rights = schema.properties?.propertyPack?.properties?.rightsAndInformalArrangements
|
|
1079
|
+
?.properties?.rightsOrArrangements;
|
|
1080
|
+
expect(rights?.required || []).not.toContain("privateRightOfWay");
|
|
1081
|
+
});
|
|
1082
|
+
|
|
1083
|
+
test("should be required with rw overlay", () => {
|
|
1084
|
+
const schema = getTransactionSchema(schemaId, ["rw"]);
|
|
1085
|
+
const rights = schema.properties?.propertyPack?.properties?.rightsAndInformalArrangements
|
|
1086
|
+
?.properties?.rightsOrArrangements;
|
|
1087
|
+
expect(rights?.required).toContain("privateRightOfWay");
|
|
1088
|
+
});
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
describe("Storm/fire/flood damage (sd)", () => {
|
|
1092
|
+
test("should validate No answer", () => {
|
|
1093
|
+
const validator = getSubschemaValidator(
|
|
1094
|
+
"/propertyPack/environmentalIssues/stormFireFloodDamage",
|
|
1095
|
+
schemaId,
|
|
1096
|
+
["sd"]
|
|
1097
|
+
);
|
|
1098
|
+
expect(validator({ yesNo: "No" })).toBe(true);
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
test("should validate Yes with details", () => {
|
|
1102
|
+
const validator = getSubschemaValidator(
|
|
1103
|
+
"/propertyPack/environmentalIssues/stormFireFloodDamage",
|
|
1104
|
+
schemaId,
|
|
1105
|
+
["sd"]
|
|
1106
|
+
);
|
|
1107
|
+
expect(validator({ yesNo: "Yes", details: "Flood damage in 2020" })).toBe(true);
|
|
1108
|
+
});
|
|
1109
|
+
|
|
1110
|
+
test("should reject Yes without details", () => {
|
|
1111
|
+
const validator = getSubschemaValidator(
|
|
1112
|
+
"/propertyPack/environmentalIssues/stormFireFloodDamage",
|
|
1113
|
+
schemaId,
|
|
1114
|
+
["sd"]
|
|
1115
|
+
);
|
|
1116
|
+
expect(validator({ yesNo: "Yes" })).toBe(false);
|
|
1117
|
+
});
|
|
1118
|
+
|
|
1119
|
+
test("should not be required without sd overlay", () => {
|
|
1120
|
+
const schema = getTransactionSchema(schemaId, ["baspiV5"]);
|
|
1121
|
+
const env = schema.properties?.propertyPack?.properties?.environmentalIssues;
|
|
1122
|
+
expect(env?.required || []).not.toContain("stormFireFloodDamage");
|
|
1123
|
+
});
|
|
1124
|
+
|
|
1125
|
+
test("should be required with sd overlay", () => {
|
|
1126
|
+
const schema = getTransactionSchema(schemaId, ["sd"]);
|
|
1127
|
+
const env = schema.properties?.propertyPack?.properties?.environmentalIssues;
|
|
1128
|
+
expect(env?.required).toContain("stormFireFloodDamage");
|
|
1129
|
+
});
|
|
1130
|
+
});
|
|
1131
|
+
|
|
1132
|
+
describe("Solar lease costs (lc)", () => {
|
|
1133
|
+
test("should validate No costs", () => {
|
|
1134
|
+
const validator = getSubschemaValidator(
|
|
1135
|
+
"/propertyPack/electricity/solarPanels/panelsOwnedOutright/associatedCost",
|
|
1136
|
+
schemaId,
|
|
1137
|
+
["lc"]
|
|
1138
|
+
);
|
|
1139
|
+
expect(validator({ hasCost: "No" })).toBe(true);
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1142
|
+
test("should validate Yes with amount and frequency", () => {
|
|
1143
|
+
const validator = getSubschemaValidator(
|
|
1144
|
+
"/propertyPack/electricity/solarPanels/panelsOwnedOutright/associatedCost",
|
|
1145
|
+
schemaId,
|
|
1146
|
+
["lc"]
|
|
1147
|
+
);
|
|
1148
|
+
expect(validator({ hasCost: "Yes", amount: 75, frequency: "Per month" })).toBe(true);
|
|
1149
|
+
});
|
|
1150
|
+
|
|
1151
|
+
test("should reject Yes without amount", () => {
|
|
1152
|
+
const validator = getSubschemaValidator(
|
|
1153
|
+
"/propertyPack/electricity/solarPanels/panelsOwnedOutright/associatedCost",
|
|
1154
|
+
schemaId,
|
|
1155
|
+
["lc"]
|
|
1156
|
+
);
|
|
1157
|
+
expect(validator({ hasCost: "Yes", frequency: "Per month" })).toBe(false);
|
|
1158
|
+
});
|
|
1159
|
+
|
|
1160
|
+
test("should reject Yes without frequency", () => {
|
|
1161
|
+
const validator = getSubschemaValidator(
|
|
1162
|
+
"/propertyPack/electricity/solarPanels/panelsOwnedOutright/associatedCost",
|
|
1163
|
+
schemaId,
|
|
1164
|
+
["lc"]
|
|
1165
|
+
);
|
|
1166
|
+
expect(validator({ hasCost: "Yes", amount: 75 })).toBe(false);
|
|
1167
|
+
});
|
|
1168
|
+
|
|
1169
|
+
test("should reject invalid frequency", () => {
|
|
1170
|
+
const validator = getSubschemaValidator(
|
|
1171
|
+
"/propertyPack/electricity/solarPanels/panelsOwnedOutright/associatedCost",
|
|
1172
|
+
schemaId,
|
|
1173
|
+
["lc"]
|
|
1174
|
+
);
|
|
1175
|
+
expect(validator({ hasCost: "Yes", amount: 75, frequency: "Weekly" })).toBe(false);
|
|
1176
|
+
});
|
|
1177
|
+
});
|
|
1178
|
+
|
|
1179
|
+
describe("Warranties and guarantees (wg)", () => {
|
|
1180
|
+
const warrantyCategoryPaths = [
|
|
1181
|
+
{ path: "newHomeWarranty", ref: "W1.1" },
|
|
1182
|
+
{ path: "roofingWork", ref: "W1.2" },
|
|
1183
|
+
{ path: "dampProofingTreatment", ref: "W1.3" },
|
|
1184
|
+
{ path: "centralHeatingAndorPlumbing", ref: "W1.4" },
|
|
1185
|
+
{ path: "electricalRepairOrInstallation", ref: "W1.5" },
|
|
1186
|
+
{ path: "subsidenceWork", ref: "W1.6" },
|
|
1187
|
+
{ path: "otherGuarantees", ref: "W1.7" },
|
|
1188
|
+
];
|
|
1189
|
+
|
|
1190
|
+
test("should have sef25Ref on all warranty categories in base schema", () => {
|
|
1191
|
+
const schema = getTransactionSchema(schemaId, ["baspiV5"]);
|
|
1192
|
+
const warranties =
|
|
1193
|
+
schema.properties?.propertyPack?.properties?.guaranteesWarrantiesAndIndemnityInsurances;
|
|
1194
|
+
|
|
1195
|
+
// Warranty fields are in oneOf[1] (hasValidGuaranteesOrWarranties = Yes)
|
|
1196
|
+
const yesBranch = warranties.oneOf[1];
|
|
1197
|
+
|
|
1198
|
+
warrantyCategoryPaths.forEach(({ path, ref }) => {
|
|
1199
|
+
expect(yesBranch.properties[path]?.sef25Ref).toBe(ref);
|
|
1200
|
+
});
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
test("should mark warranty categories as required when wg overlay loaded", () => {
|
|
1204
|
+
const schema = getTransactionSchema(schemaId, ["baspiV5", "wg"]);
|
|
1205
|
+
const warranties =
|
|
1206
|
+
schema.properties?.propertyPack?.properties?.guaranteesWarrantiesAndIndemnityInsurances;
|
|
1207
|
+
|
|
1208
|
+
const yesBranch = warranties.oneOf[1];
|
|
1209
|
+
warrantyCategoryPaths.forEach(({ path }) => {
|
|
1210
|
+
expect(yesBranch.required).toContain(path);
|
|
1211
|
+
});
|
|
1212
|
+
});
|
|
1213
|
+
|
|
1214
|
+
test("should not require warranty categories without any overlay", () => {
|
|
1215
|
+
const schema = getTransactionSchema(schemaId, []);
|
|
1216
|
+
const warranties =
|
|
1217
|
+
schema.properties?.propertyPack?.properties?.guaranteesWarrantiesAndIndemnityInsurances;
|
|
1218
|
+
|
|
1219
|
+
const yesBranch = warranties.oneOf[1];
|
|
1220
|
+
// Without any overlay, warranty categories should not be in required
|
|
1221
|
+
expect(yesBranch.required || []).not.toContain("newHomeWarranty");
|
|
1222
|
+
expect(yesBranch.required || []).not.toContain("electricalRepairOrInstallation");
|
|
1223
|
+
});
|
|
1224
|
+
});
|
|
1225
|
+
|
|
1226
|
+
describe("Insurance claims (ic)", () => {
|
|
1227
|
+
test("should mark insuranceClaims as required in isInsured=Yes branch", () => {
|
|
1228
|
+
const schema = getTransactionSchema(schemaId, ["ic"]);
|
|
1229
|
+
const insurance = schema.properties?.propertyPack?.properties?.insurance;
|
|
1230
|
+
// oneOf[1] is isInsured=Yes
|
|
1231
|
+
const yesBranch = insurance.oneOf[1];
|
|
1232
|
+
expect(yesBranch?.required).toContain("insuranceClaims");
|
|
1233
|
+
});
|
|
1234
|
+
|
|
1235
|
+
test("should validate insuranceClaims No answer", () => {
|
|
1236
|
+
const validator = getSubschemaValidator(
|
|
1237
|
+
"/propertyPack/insurance/insuranceClaims",
|
|
1238
|
+
schemaId,
|
|
1239
|
+
["baspiV5", "ic"]
|
|
1240
|
+
);
|
|
1241
|
+
expect(validator({ yesNo: "No" })).toBe(true);
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
test("should validate insuranceClaims Yes with details", () => {
|
|
1245
|
+
const validator = getSubschemaValidator(
|
|
1246
|
+
"/propertyPack/insurance/insuranceClaims",
|
|
1247
|
+
schemaId,
|
|
1248
|
+
["baspiV5", "ic"]
|
|
1249
|
+
);
|
|
1250
|
+
expect(validator({ yesNo: "Yes", details: "Storm damage claim in 2019" })).toBe(true);
|
|
1251
|
+
});
|
|
1252
|
+
});
|
|
1253
|
+
|
|
1254
|
+
describe("Neighbour development (nd)", () => {
|
|
1255
|
+
test("should add sef25Ref to neighbourDevelopment", () => {
|
|
1256
|
+
const schema = getTransactionSchema(schemaId, ["nd"]);
|
|
1257
|
+
const nd = schema.properties?.propertyPack?.properties?.notices
|
|
1258
|
+
?.properties?.neighbourDevelopment;
|
|
1259
|
+
expect(nd?.sef25Ref).toBe("N1.1");
|
|
1260
|
+
});
|
|
1261
|
+
|
|
1262
|
+
test("should add ntsRef via nd overlay", () => {
|
|
1263
|
+
const schema = getTransactionSchema(schemaId, ["nd"]);
|
|
1264
|
+
const notices = schema.properties?.propertyPack?.properties?.notices;
|
|
1265
|
+
expect(notices?.ntsRef).toBe("N1");
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
test("should validate No answer", () => {
|
|
1269
|
+
const validator = getSubschemaValidator(
|
|
1270
|
+
"/propertyPack/notices/neighbourDevelopment",
|
|
1271
|
+
schemaId,
|
|
1272
|
+
["baspiV5", "nd"]
|
|
1273
|
+
);
|
|
1274
|
+
expect(validator({ yesNo: "No" })).toBe(true);
|
|
1275
|
+
});
|
|
1276
|
+
});
|
|
1277
|
+
|
|
1278
|
+
describe("Other material issue (mi)", () => {
|
|
1279
|
+
test("should mark otherMaterialIssue as required", () => {
|
|
1280
|
+
const schema = getTransactionSchema(schemaId, ["mi"]);
|
|
1281
|
+
const additional = schema.properties?.propertyPack?.properties?.additionalInformation;
|
|
1282
|
+
expect(additional?.required).toContain("otherMaterialIssue");
|
|
1283
|
+
});
|
|
1284
|
+
|
|
1285
|
+
test("should not require otherMaterialIssue without mi overlay", () => {
|
|
1286
|
+
const schema = getTransactionSchema(schemaId, []);
|
|
1287
|
+
const additional = schema.properties?.propertyPack?.properties?.additionalInformation;
|
|
1288
|
+
expect(additional?.required || []).not.toContain("otherMaterialIssue");
|
|
1289
|
+
});
|
|
1290
|
+
|
|
1291
|
+
test("should validate No answer", () => {
|
|
1292
|
+
const validator = getSubschemaValidator(
|
|
1293
|
+
"/propertyPack/additionalInformation/otherMaterialIssue",
|
|
1294
|
+
schemaId,
|
|
1295
|
+
["baspiV5", "mi"]
|
|
1296
|
+
);
|
|
1297
|
+
expect(validator({ yesNo: "No" })).toBe(true);
|
|
1298
|
+
});
|
|
1299
|
+
|
|
1300
|
+
test("should validate Yes with details", () => {
|
|
1301
|
+
const validator = getSubschemaValidator(
|
|
1302
|
+
"/propertyPack/additionalInformation/otherMaterialIssue",
|
|
1303
|
+
schemaId,
|
|
1304
|
+
["baspiV5", "mi"]
|
|
1305
|
+
);
|
|
1306
|
+
expect(validator({ yesNo: "Yes", details: "Previous subsidence issues" })).toBe(true);
|
|
1307
|
+
});
|
|
1308
|
+
});
|
|
1309
|
+
|
|
1310
|
+
describe("Title restrictions (tr)", () => {
|
|
1311
|
+
test("should require titleRestrictions in freehold branch with tr overlay", () => {
|
|
1312
|
+
const schema = getTransactionSchema(schemaId, ["tr"]);
|
|
1313
|
+
const items = schema.properties?.propertyPack?.properties?.ownership
|
|
1314
|
+
?.properties?.ownershipsToBeTransferred?.items;
|
|
1315
|
+
// oneOf[0] is Freehold
|
|
1316
|
+
const freeholdBranch = items.oneOf[0];
|
|
1317
|
+
expect(freeholdBranch?.properties?.titleRestrictions).toBeDefined();
|
|
1318
|
+
expect(freeholdBranch?.required).toContain("titleRestrictions");
|
|
1319
|
+
});
|
|
1320
|
+
|
|
1321
|
+
test("should not require titleRestrictions without tr overlay", () => {
|
|
1322
|
+
const schema = getTransactionSchema(schemaId, ["baspiV5"]);
|
|
1323
|
+
const items = schema.properties?.propertyPack?.properties?.ownership
|
|
1324
|
+
?.properties?.ownershipsToBeTransferred?.items;
|
|
1325
|
+
const freeholdBranch = items.oneOf[0];
|
|
1326
|
+
expect(freeholdBranch?.required || []).not.toContain("titleRestrictions");
|
|
1327
|
+
});
|
|
1328
|
+
|
|
1329
|
+
test("should have correct sef25Ref", () => {
|
|
1330
|
+
const schema = getTransactionSchema(schemaId, ["tr"]);
|
|
1331
|
+
const items = schema.properties?.propertyPack?.properties?.ownership
|
|
1332
|
+
?.properties?.ownershipsToBeTransferred?.items;
|
|
1333
|
+
const freeholdBranch = items.oneOf[0];
|
|
1334
|
+
expect(freeholdBranch?.properties?.titleRestrictions?.ntsRef).toBe("T1.1");
|
|
1335
|
+
});
|
|
1336
|
+
});
|
|
1337
|
+
|
|
1338
|
+
describe("All SEF25 extensions combined", () => {
|
|
1339
|
+
const allSef25 = ["sc", "pc", "ph", "dk", "rw", "sd", "lc", "wg", "ic", "nd", "mi", "tr"];
|
|
1340
|
+
|
|
1341
|
+
test("should load all SEF25 extensions together without error", () => {
|
|
1342
|
+
const schema = getTransactionSchema(schemaId, ["baspiV5", ...allSef25]);
|
|
1343
|
+
expect(schema).toBeDefined();
|
|
1344
|
+
expect(schema.properties?.propertyPack).toBeDefined();
|
|
1345
|
+
});
|
|
1346
|
+
|
|
1347
|
+
test("should not interfere with existing NTS2 extensions when combined", () => {
|
|
1348
|
+
const schema = getTransactionSchema(schemaId, ["nts2025", ...allSef25]);
|
|
1349
|
+
|
|
1350
|
+
// NTS2 fields still work
|
|
1351
|
+
const si = schema.properties?.propertyPack?.properties?.specialistIssues;
|
|
1352
|
+
expect(si?.properties?.wellsDitchesShaft?.sef25Ref).toBe("H1.1");
|
|
1353
|
+
|
|
1354
|
+
// New SEF25 fields present
|
|
1355
|
+
const parking = schema.properties?.propertyPack?.properties?.parking?.properties;
|
|
1356
|
+
expect(parking?.droppedKerbAccess).toBeDefined();
|
|
1357
|
+
|
|
1358
|
+
const env = schema.properties?.propertyPack?.properties?.environmentalIssues?.properties;
|
|
1359
|
+
expect(env?.stormFireFloodDamage).toBeDefined();
|
|
1360
|
+
|
|
1361
|
+
const rights = schema.properties?.propertyPack?.properties?.rightsAndInformalArrangements
|
|
1362
|
+
?.properties?.rightsOrArrangements?.properties;
|
|
1363
|
+
expect(rights?.privateRightOfWay).toBeDefined();
|
|
1364
|
+
});
|
|
1365
|
+
});
|
|
960
1366
|
});
|
|
961
1367
|
});
|
|
@@ -1599,7 +1599,7 @@ describe("TA6 Edition 6 overlay", () => {
|
|
|
1599
1599
|
mainsFoulDrainage: {
|
|
1600
1600
|
yesNo: "No",
|
|
1601
1601
|
offMainsDrainageSystem: {
|
|
1602
|
-
offMainsDrainageSystemType: "
|
|
1602
|
+
offMainsDrainageSystemType: "Other",
|
|
1603
1603
|
otherConnectedProperties: { yesNo: "No" },
|
|
1604
1604
|
plantOnOtherLand: { yesNo: "No" },
|
|
1605
1605
|
plantRegistered: { yesNo: "No" },
|
|
@@ -2073,53 +2073,6 @@ describe("TA6 Edition 6 overlay", () => {
|
|
|
2073
2073
|
});
|
|
2074
2074
|
});
|
|
2075
2075
|
|
|
2076
|
-
describe("Seller signatures validation", () => {
|
|
2077
|
-
let validator;
|
|
2078
|
-
|
|
2079
|
-
beforeAll(() => {
|
|
2080
|
-
validator = getSubschemaValidator(
|
|
2081
|
-
"/propertyPack/confirmationOfAccuracyByOwners",
|
|
2082
|
-
schemaId,
|
|
2083
|
-
["ta6ed6"]
|
|
2084
|
-
);
|
|
2085
|
-
});
|
|
2086
|
-
|
|
2087
|
-
test("confirmation with sellerSignatures is valid", () => {
|
|
2088
|
-
const data = {
|
|
2089
|
-
confirmInformationIsAccurate: true,
|
|
2090
|
-
sellerSignatures: [
|
|
2091
|
-
{ name: "Jane Doe", signedOn: "2024-06-15" },
|
|
2092
|
-
{ name: "John Doe", signedOn: "2024-06-15" },
|
|
2093
|
-
],
|
|
2094
|
-
};
|
|
2095
|
-
expect(validator(data)).toBe(true);
|
|
2096
|
-
});
|
|
2097
|
-
|
|
2098
|
-
test("sellerSignatures with single seller is valid", () => {
|
|
2099
|
-
const data = {
|
|
2100
|
-
confirmInformationIsAccurate: true,
|
|
2101
|
-
sellerSignatures: [{ name: "Jane Doe", signedOn: "2024-06-15" }],
|
|
2102
|
-
};
|
|
2103
|
-
expect(validator(data)).toBe(true);
|
|
2104
|
-
});
|
|
2105
|
-
|
|
2106
|
-
test("empty sellerSignatures array is valid", () => {
|
|
2107
|
-
const data = {
|
|
2108
|
-
confirmInformationIsAccurate: true,
|
|
2109
|
-
sellerSignatures: [],
|
|
2110
|
-
};
|
|
2111
|
-
expect(validator(data)).toBe(true);
|
|
2112
|
-
});
|
|
2113
|
-
|
|
2114
|
-
test("sellerSignatures with invalid date format is invalid", () => {
|
|
2115
|
-
const data = {
|
|
2116
|
-
confirmInformationIsAccurate: true,
|
|
2117
|
-
sellerSignatures: [{ name: "Jane Doe", signedOn: "15/06/2024" }],
|
|
2118
|
-
};
|
|
2119
|
-
expect(validator(data)).toBe(false);
|
|
2120
|
-
});
|
|
2121
|
-
});
|
|
2122
|
-
|
|
2123
2076
|
describe("Previously broken discriminator sections now compile", () => {
|
|
2124
2077
|
// These sections previously failed AJV compilation because their
|
|
2125
2078
|
// discriminated properties were not in the required array of each
|