@pdtf/schemas 3.6.0-17 → 3.6.0-19
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/.claude/settings.local.json +2 -1
- package/docs/sef25-extensions-ui-spec.md +146 -0
- package/index.js +5 -0
- package/package.json +1 -1
- package/src/schemas/v3/combined.json +230 -19
- package/src/schemas/v3/compactSkeleton.txt +19 -0
- package/src/schemas/v3/overlays/extensions/jk.json +24 -6
- package/src/schemas/v3/overlays/extensions/pc.json +28 -0
- package/src/schemas/v3/overlays/extensions/ph.json +191 -0
- package/src/schemas/v3/overlays/extensions/sc.json +77 -0
- package/src/schemas/v3/overlays/lpe1.json +14 -2
- package/src/schemas/v3/overlays/ta7ed5.json +11 -7
- package/src/schemas/v3/pdtf-transaction.json +262 -3
- package/src/schemas/v3/skeleton.json +26 -1
- package/src/tests/v3/extensionOverlays.test.js +433 -0
- package/src/tests/v3/ta7ed5.test.js +10 -10
- package/src/utils/extractExtensionOverlays.js +92 -31
|
@@ -1222,7 +1222,8 @@
|
|
|
1222
1222
|
},
|
|
1223
1223
|
"controlledParking": {
|
|
1224
1224
|
"yesNo": "variant",
|
|
1225
|
-
"annualCostOfPermit": "number"
|
|
1225
|
+
"annualCostOfPermit": "number",
|
|
1226
|
+
"costOfPermitFrequency": "string"
|
|
1226
1227
|
},
|
|
1227
1228
|
"vehicleTypeRestriction": {
|
|
1228
1229
|
"yesNo": "variant",
|
|
@@ -1759,6 +1760,22 @@
|
|
|
1759
1760
|
"yesNo": "variant",
|
|
1760
1761
|
"details": "string",
|
|
1761
1762
|
"attachments": "string"
|
|
1763
|
+
},
|
|
1764
|
+
"wellsDitchesShaft": {
|
|
1765
|
+
"yesNo": "variant",
|
|
1766
|
+
"details": "string"
|
|
1767
|
+
},
|
|
1768
|
+
"damagedOrExposedElectrics": {
|
|
1769
|
+
"yesNo": "variant",
|
|
1770
|
+
"details": "string"
|
|
1771
|
+
},
|
|
1772
|
+
"damageToFlooringOrStaircases": {
|
|
1773
|
+
"yesNo": "variant",
|
|
1774
|
+
"details": "string"
|
|
1775
|
+
},
|
|
1776
|
+
"knownAreasInPoorCondition": {
|
|
1777
|
+
"yesNo": "variant",
|
|
1778
|
+
"details": "string"
|
|
1762
1779
|
}
|
|
1763
1780
|
},
|
|
1764
1781
|
"fixturesAndFittings": {
|
|
@@ -2431,6 +2448,10 @@
|
|
|
2431
2448
|
"mainsWater": {
|
|
2432
2449
|
"yesNo": "variant",
|
|
2433
2450
|
"details": "string",
|
|
2451
|
+
"associatedCost": {
|
|
2452
|
+
"amount": "number",
|
|
2453
|
+
"frequency": "string"
|
|
2454
|
+
},
|
|
2434
2455
|
"supplier": "string",
|
|
2435
2456
|
"stopcock": {
|
|
2436
2457
|
"location": "string",
|
|
@@ -2499,6 +2520,10 @@
|
|
|
2499
2520
|
"dateLastServiced": "string",
|
|
2500
2521
|
"attachments": "string",
|
|
2501
2522
|
"details": "string"
|
|
2523
|
+
},
|
|
2524
|
+
"associatedCost": {
|
|
2525
|
+
"amount": "number",
|
|
2526
|
+
"frequency": "string"
|
|
2502
2527
|
}
|
|
2503
2528
|
},
|
|
2504
2529
|
"surfaceDrainageCharge": {
|
|
@@ -2,6 +2,7 @@ const {
|
|
|
2
2
|
getTransactionSchema,
|
|
3
3
|
extensionOverlays,
|
|
4
4
|
getValidator,
|
|
5
|
+
getSubschemaValidator,
|
|
5
6
|
} = require("../../../index.js");
|
|
6
7
|
|
|
7
8
|
const schemaId =
|
|
@@ -161,6 +162,9 @@ describe("Extension Overlays", () => {
|
|
|
161
162
|
"hi",
|
|
162
163
|
"fd", // Utilities & Services
|
|
163
164
|
"oc", // Transaction
|
|
165
|
+
"sc",
|
|
166
|
+
"pc",
|
|
167
|
+
"ph", // SEF25
|
|
164
168
|
];
|
|
165
169
|
|
|
166
170
|
expect(Object.keys(extensionOverlays).sort()).toEqual(
|
|
@@ -469,6 +473,96 @@ describe("Extension Overlays", () => {
|
|
|
469
473
|
).toBeTruthy();
|
|
470
474
|
});
|
|
471
475
|
|
|
476
|
+
test("should merge supply costs extension into mainsWater No branch", () => {
|
|
477
|
+
const schema = getTransactionSchema(schemaId, ["sc"]);
|
|
478
|
+
const mainsWater =
|
|
479
|
+
schema.properties?.propertyPack?.properties?.waterAndDrainage
|
|
480
|
+
?.properties?.water?.properties?.mainsWater;
|
|
481
|
+
|
|
482
|
+
expect(mainsWater?.oneOf).toBeDefined();
|
|
483
|
+
|
|
484
|
+
// Branch 0 is yesNo="No" — should now contain associatedCost
|
|
485
|
+
const noBranch = mainsWater.oneOf[0];
|
|
486
|
+
const cost = noBranch?.properties?.associatedCost;
|
|
487
|
+
expect(cost).toBeDefined();
|
|
488
|
+
expect(cost.sef25Ref).toBe("U1.1");
|
|
489
|
+
expect(cost.required).toEqual(["amount", "frequency"]);
|
|
490
|
+
expect(cost.properties.amount.type).toBe("number");
|
|
491
|
+
expect(cost.properties.frequency.type).toBe("string");
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
test("should merge supply costs extension into mainsFoulDrainage No/Not known branch", () => {
|
|
495
|
+
const schema = getTransactionSchema(schemaId, ["sc"]);
|
|
496
|
+
const mainsFoul =
|
|
497
|
+
schema.properties?.propertyPack?.properties?.waterAndDrainage
|
|
498
|
+
?.properties?.drainage?.properties?.mainsFoulDrainage;
|
|
499
|
+
|
|
500
|
+
expect(mainsFoul?.oneOf).toBeDefined();
|
|
501
|
+
|
|
502
|
+
// Branch 2 is yesNo="No"/"Not known" — should now contain associatedCost
|
|
503
|
+
const noBranch = mainsFoul.oneOf[2];
|
|
504
|
+
const cost = noBranch?.properties?.associatedCost;
|
|
505
|
+
expect(cost).toBeDefined();
|
|
506
|
+
expect(cost.sef25Ref).toBe("U1.2");
|
|
507
|
+
expect(cost.required).toEqual(["amount", "frequency"]);
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
test("should merge parking permit frequency into controlledParking Yes branch", () => {
|
|
511
|
+
const schema = getTransactionSchema(schemaId, ["pc"]);
|
|
512
|
+
const controlled =
|
|
513
|
+
schema.properties?.propertyPack?.properties?.parking?.properties
|
|
514
|
+
?.controlledParking;
|
|
515
|
+
|
|
516
|
+
expect(controlled?.oneOf).toBeDefined();
|
|
517
|
+
|
|
518
|
+
// Branch 1 is yesNo="Yes"
|
|
519
|
+
const yesBranch = controlled.oneOf[1];
|
|
520
|
+
const freq = yesBranch?.properties?.costOfPermitFrequency;
|
|
521
|
+
expect(freq).toBeDefined();
|
|
522
|
+
expect(freq.sef25Ref).toBe("P1.1");
|
|
523
|
+
expect(freq.type).toBe("string");
|
|
524
|
+
|
|
525
|
+
// Existing annualCostOfPermit should still be present
|
|
526
|
+
expect(yesBranch.properties.annualCostOfPermit).toBeDefined();
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
test("should merge all 4 property hazard fields into specialistIssues", () => {
|
|
530
|
+
const schema = getTransactionSchema(schemaId, ["ph"]);
|
|
531
|
+
const si =
|
|
532
|
+
schema.properties?.propertyPack?.properties?.specialistIssues
|
|
533
|
+
?.properties;
|
|
534
|
+
|
|
535
|
+
const expectedFields = [
|
|
536
|
+
{ key: "wellsDitchesShaft", ref: "H1.1" },
|
|
537
|
+
{ key: "damagedOrExposedElectrics", ref: "H1.2" },
|
|
538
|
+
{ key: "damageToFlooringOrStaircases", ref: "H1.3" },
|
|
539
|
+
{ key: "knownAreasInPoorCondition", ref: "H1.4" },
|
|
540
|
+
];
|
|
541
|
+
|
|
542
|
+
expectedFields.forEach(({ key, ref }) => {
|
|
543
|
+
expect(si[key]).toBeDefined();
|
|
544
|
+
expect(si[key].sef25Ref).toBe(ref);
|
|
545
|
+
expect(si[key].required).toContain("yesNo");
|
|
546
|
+
expect(si[key].discriminator?.propertyName).toBe("yesNo");
|
|
547
|
+
expect(si[key].oneOf).toHaveLength(2);
|
|
548
|
+
|
|
549
|
+
// "No" branch should not require details
|
|
550
|
+
const noBranch = si[key].oneOf.find((b) =>
|
|
551
|
+
b.properties?.yesNo?.enum?.includes("No")
|
|
552
|
+
);
|
|
553
|
+
expect(noBranch).toBeDefined();
|
|
554
|
+
expect(noBranch.required).toBeUndefined();
|
|
555
|
+
|
|
556
|
+
// "Yes" branch should require details
|
|
557
|
+
const yesBranch = si[key].oneOf.find((b) =>
|
|
558
|
+
b.properties?.yesNo?.enum?.includes("Yes")
|
|
559
|
+
);
|
|
560
|
+
expect(yesBranch).toBeDefined();
|
|
561
|
+
expect(yesBranch.required).toContain("details");
|
|
562
|
+
expect(yesBranch.properties.details.minLength).toBe(1);
|
|
563
|
+
});
|
|
564
|
+
});
|
|
565
|
+
|
|
472
566
|
test("should not require additional fields when 'No' is selected in extension overlays", () => {
|
|
473
567
|
// Test the 'as' (additional searches) extension overlay
|
|
474
568
|
const schema = getTransactionSchema(schemaId, ["as"]);
|
|
@@ -522,4 +616,343 @@ describe("Extension Overlays", () => {
|
|
|
522
616
|
}
|
|
523
617
|
});
|
|
524
618
|
});
|
|
619
|
+
|
|
620
|
+
describe("SEF25 extension validation", () => {
|
|
621
|
+
describe("Supply costs (sc)", () => {
|
|
622
|
+
const overlays = ["baspiV5", "sc"];
|
|
623
|
+
|
|
624
|
+
test("should validate valid private water cost", () => {
|
|
625
|
+
const validator = getSubschemaValidator(
|
|
626
|
+
"/propertyPack/waterAndDrainage/water/mainsWater",
|
|
627
|
+
schemaId,
|
|
628
|
+
overlays
|
|
629
|
+
);
|
|
630
|
+
|
|
631
|
+
const result = validator({
|
|
632
|
+
yesNo: "No",
|
|
633
|
+
details: "Private borehole",
|
|
634
|
+
associatedCost: {
|
|
635
|
+
amount: 50,
|
|
636
|
+
frequency: "Per month",
|
|
637
|
+
},
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
expect(result).toBe(true);
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
test("should validate private water with no associated cost (cost is optional at schema level)", () => {
|
|
644
|
+
const validator = getSubschemaValidator(
|
|
645
|
+
"/propertyPack/waterAndDrainage/water/mainsWater",
|
|
646
|
+
schemaId,
|
|
647
|
+
overlays
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
const result = validator({
|
|
651
|
+
yesNo: "No",
|
|
652
|
+
details: "Private well",
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
expect(result).toBe(true);
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
test("should reject invalid frequency value for water cost", () => {
|
|
659
|
+
const validator = getSubschemaValidator(
|
|
660
|
+
"/propertyPack/waterAndDrainage/water/mainsWater",
|
|
661
|
+
schemaId,
|
|
662
|
+
overlays
|
|
663
|
+
);
|
|
664
|
+
|
|
665
|
+
const result = validator({
|
|
666
|
+
yesNo: "No",
|
|
667
|
+
details: "Borehole",
|
|
668
|
+
associatedCost: {
|
|
669
|
+
amount: 100,
|
|
670
|
+
frequency: "Weekly",
|
|
671
|
+
},
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
expect(result).toBe(false);
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
test("should reject non-numeric amount for water cost", () => {
|
|
678
|
+
const validator = getSubschemaValidator(
|
|
679
|
+
"/propertyPack/waterAndDrainage/water/mainsWater",
|
|
680
|
+
schemaId,
|
|
681
|
+
overlays
|
|
682
|
+
);
|
|
683
|
+
|
|
684
|
+
const result = validator({
|
|
685
|
+
yesNo: "No",
|
|
686
|
+
details: "Borehole",
|
|
687
|
+
associatedCost: {
|
|
688
|
+
amount: "fifty pounds",
|
|
689
|
+
frequency: "Per month",
|
|
690
|
+
},
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
expect(result).toBe(false);
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
test("should validate valid private sewerage cost", () => {
|
|
697
|
+
// Use sc without baspiV5 to avoid strict offMainsDrainageSystem requirements
|
|
698
|
+
const validator = getSubschemaValidator(
|
|
699
|
+
"/propertyPack/waterAndDrainage/drainage/mainsFoulDrainage",
|
|
700
|
+
schemaId,
|
|
701
|
+
["sc"]
|
|
702
|
+
);
|
|
703
|
+
|
|
704
|
+
const result = validator({
|
|
705
|
+
yesNo: "No",
|
|
706
|
+
associatedCost: {
|
|
707
|
+
amount: 200,
|
|
708
|
+
frequency: "Per year",
|
|
709
|
+
},
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
expect(result).toBe(true);
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
test("should reject invalid frequency for sewerage cost", () => {
|
|
716
|
+
const validator = getSubschemaValidator(
|
|
717
|
+
"/propertyPack/waterAndDrainage/drainage/mainsFoulDrainage",
|
|
718
|
+
schemaId,
|
|
719
|
+
["sc"]
|
|
720
|
+
);
|
|
721
|
+
|
|
722
|
+
const result = validator({
|
|
723
|
+
yesNo: "No",
|
|
724
|
+
associatedCost: {
|
|
725
|
+
amount: 200,
|
|
726
|
+
frequency: "Quarterly",
|
|
727
|
+
},
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
expect(result).toBe(false);
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
test("should not allow associated cost when mains water is Yes", () => {
|
|
734
|
+
const validator = getSubschemaValidator(
|
|
735
|
+
"/propertyPack/waterAndDrainage/water/mainsWater",
|
|
736
|
+
schemaId,
|
|
737
|
+
overlays
|
|
738
|
+
);
|
|
739
|
+
|
|
740
|
+
// When yesNo="Yes", associatedCost should cause validation failure
|
|
741
|
+
// because it's only defined in the "No" oneOf branch
|
|
742
|
+
const result = validator({
|
|
743
|
+
yesNo: "Yes",
|
|
744
|
+
supplier: "Thames Water",
|
|
745
|
+
associatedCost: {
|
|
746
|
+
amount: 50,
|
|
747
|
+
frequency: "Per month",
|
|
748
|
+
},
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
expect(result).toBe(false);
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
describe("Parking permit cost (pc)", () => {
|
|
756
|
+
const overlays = ["baspiV5", "pc"];
|
|
757
|
+
|
|
758
|
+
test("should validate valid parking permit with frequency", () => {
|
|
759
|
+
const validator = getSubschemaValidator(
|
|
760
|
+
"/propertyPack/parking/controlledParking",
|
|
761
|
+
schemaId,
|
|
762
|
+
overlays
|
|
763
|
+
);
|
|
764
|
+
|
|
765
|
+
const result = validator({
|
|
766
|
+
yesNo: "Yes",
|
|
767
|
+
annualCostOfPermit: 150,
|
|
768
|
+
costOfPermitFrequency: "Per year",
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
expect(result).toBe(true);
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
test("should validate parking permit with monthly frequency", () => {
|
|
775
|
+
const validator = getSubschemaValidator(
|
|
776
|
+
"/propertyPack/parking/controlledParking",
|
|
777
|
+
schemaId,
|
|
778
|
+
overlays
|
|
779
|
+
);
|
|
780
|
+
|
|
781
|
+
const result = validator({
|
|
782
|
+
yesNo: "Yes",
|
|
783
|
+
annualCostOfPermit: 12.50,
|
|
784
|
+
costOfPermitFrequency: "Per month",
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
expect(result).toBe(true);
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
test("should reject invalid frequency for parking permit", () => {
|
|
791
|
+
const validator = getSubschemaValidator(
|
|
792
|
+
"/propertyPack/parking/controlledParking",
|
|
793
|
+
schemaId,
|
|
794
|
+
overlays
|
|
795
|
+
);
|
|
796
|
+
|
|
797
|
+
const result = validator({
|
|
798
|
+
yesNo: "Yes",
|
|
799
|
+
annualCostOfPermit: 150,
|
|
800
|
+
costOfPermitFrequency: "Per quarter",
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
expect(result).toBe(false);
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
test("should validate No answer without cost fields", () => {
|
|
807
|
+
const validator = getSubschemaValidator(
|
|
808
|
+
"/propertyPack/parking/controlledParking",
|
|
809
|
+
schemaId,
|
|
810
|
+
overlays
|
|
811
|
+
);
|
|
812
|
+
|
|
813
|
+
const result = validator({
|
|
814
|
+
yesNo: "No",
|
|
815
|
+
});
|
|
816
|
+
|
|
817
|
+
expect(result).toBe(true);
|
|
818
|
+
});
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
describe("Property hazards (ph)", () => {
|
|
822
|
+
const overlays = ["ph"];
|
|
823
|
+
const hazardFields = [
|
|
824
|
+
"wellsDitchesShaft",
|
|
825
|
+
"damagedOrExposedElectrics",
|
|
826
|
+
"damageToFlooringOrStaircases",
|
|
827
|
+
"knownAreasInPoorCondition",
|
|
828
|
+
];
|
|
829
|
+
|
|
830
|
+
hazardFields.forEach((field) => {
|
|
831
|
+
test(`${field}: should validate "No" answer`, () => {
|
|
832
|
+
const validator = getSubschemaValidator(
|
|
833
|
+
`/propertyPack/specialistIssues/${field}`,
|
|
834
|
+
schemaId,
|
|
835
|
+
overlays
|
|
836
|
+
);
|
|
837
|
+
|
|
838
|
+
const result = validator({ yesNo: "No" });
|
|
839
|
+
expect(result).toBe(true);
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
test(`${field}: should validate "Yes" with details`, () => {
|
|
843
|
+
const validator = getSubschemaValidator(
|
|
844
|
+
`/propertyPack/specialistIssues/${field}`,
|
|
845
|
+
schemaId,
|
|
846
|
+
overlays
|
|
847
|
+
);
|
|
848
|
+
|
|
849
|
+
const result = validator({
|
|
850
|
+
yesNo: "Yes",
|
|
851
|
+
details: "Some description of the issue",
|
|
852
|
+
});
|
|
853
|
+
expect(result).toBe(true);
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
test(`${field}: should reject "Yes" without details`, () => {
|
|
857
|
+
const validator = getSubschemaValidator(
|
|
858
|
+
`/propertyPack/specialistIssues/${field}`,
|
|
859
|
+
schemaId,
|
|
860
|
+
overlays
|
|
861
|
+
);
|
|
862
|
+
|
|
863
|
+
const result = validator({ yesNo: "Yes" });
|
|
864
|
+
expect(result).toBe(false);
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
test(`${field}: should reject "Yes" with empty details`, () => {
|
|
868
|
+
const validator = getSubschemaValidator(
|
|
869
|
+
`/propertyPack/specialistIssues/${field}`,
|
|
870
|
+
schemaId,
|
|
871
|
+
overlays
|
|
872
|
+
);
|
|
873
|
+
|
|
874
|
+
const result = validator({ yesNo: "Yes", details: "" });
|
|
875
|
+
expect(result).toBe(false);
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
test(`${field}: should reject invalid yesNo value`, () => {
|
|
879
|
+
const validator = getSubschemaValidator(
|
|
880
|
+
`/propertyPack/specialistIssues/${field}`,
|
|
881
|
+
schemaId,
|
|
882
|
+
overlays
|
|
883
|
+
);
|
|
884
|
+
|
|
885
|
+
const result = validator({ yesNo: "Maybe" });
|
|
886
|
+
expect(result).toBe(false);
|
|
887
|
+
});
|
|
888
|
+
});
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
describe("Combined SEF25 extensions", () => {
|
|
892
|
+
test("should load all three SEF25 extensions together", () => {
|
|
893
|
+
const schema = getTransactionSchema(schemaId, [
|
|
894
|
+
"baspiV5",
|
|
895
|
+
"sc",
|
|
896
|
+
"pc",
|
|
897
|
+
"ph",
|
|
898
|
+
]);
|
|
899
|
+
|
|
900
|
+
// Supply costs
|
|
901
|
+
const waterCost =
|
|
902
|
+
schema.properties?.propertyPack?.properties?.waterAndDrainage
|
|
903
|
+
?.properties?.water?.properties?.mainsWater?.oneOf?.[0]?.properties
|
|
904
|
+
?.associatedCost;
|
|
905
|
+
expect(waterCost).toBeDefined();
|
|
906
|
+
|
|
907
|
+
const sewerageCost =
|
|
908
|
+
schema.properties?.propertyPack?.properties?.waterAndDrainage
|
|
909
|
+
?.properties?.drainage?.properties?.mainsFoulDrainage?.oneOf?.[2]
|
|
910
|
+
?.properties?.associatedCost;
|
|
911
|
+
expect(sewerageCost).toBeDefined();
|
|
912
|
+
|
|
913
|
+
// Parking
|
|
914
|
+
const parkingFreq =
|
|
915
|
+
schema.properties?.propertyPack?.properties?.parking?.properties
|
|
916
|
+
?.controlledParking?.oneOf?.[1]?.properties?.costOfPermitFrequency;
|
|
917
|
+
expect(parkingFreq).toBeDefined();
|
|
918
|
+
|
|
919
|
+
// Hazards
|
|
920
|
+
const si =
|
|
921
|
+
schema.properties?.propertyPack?.properties?.specialistIssues
|
|
922
|
+
?.properties;
|
|
923
|
+
expect(si?.wellsDitchesShaft).toBeDefined();
|
|
924
|
+
expect(si?.damagedOrExposedElectrics).toBeDefined();
|
|
925
|
+
expect(si?.damageToFlooringOrStaircases).toBeDefined();
|
|
926
|
+
expect(si?.knownAreasInPoorCondition).toBeDefined();
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
test("should not interfere with existing NTS2 extensions", () => {
|
|
930
|
+
const schema = getTransactionSchema(schemaId, [
|
|
931
|
+
"nts2023",
|
|
932
|
+
"jk",
|
|
933
|
+
"hs",
|
|
934
|
+
"sc",
|
|
935
|
+
"pc",
|
|
936
|
+
"ph",
|
|
937
|
+
]);
|
|
938
|
+
|
|
939
|
+
const si =
|
|
940
|
+
schema.properties?.propertyPack?.properties?.specialistIssues;
|
|
941
|
+
|
|
942
|
+
// Existing NTS2 extensions still work
|
|
943
|
+
expect(si?.properties?.japaneseKnotweed?.ntsRef).toBe("A5.3");
|
|
944
|
+
expect(si?.properties?.ongoingHealthOrSafetyIssue?.ntsRef).toBe(
|
|
945
|
+
"A5.5"
|
|
946
|
+
);
|
|
947
|
+
expect(si?.required).toContain("japaneseKnotweed");
|
|
948
|
+
expect(si?.required).toContain("ongoingHealthOrSafetyIssue");
|
|
949
|
+
|
|
950
|
+
// SEF25 hazards also present
|
|
951
|
+
expect(si?.properties?.wellsDitchesShaft?.sef25Ref).toBe("H1.1");
|
|
952
|
+
expect(si?.properties?.knownAreasInPoorCondition?.sef25Ref).toBe(
|
|
953
|
+
"H1.4"
|
|
954
|
+
);
|
|
955
|
+
});
|
|
956
|
+
});
|
|
957
|
+
});
|
|
525
958
|
});
|
|
@@ -237,9 +237,9 @@ describe("TA7 5th edition overlay", () => {
|
|
|
237
237
|
expect(validator({ collector: "Landlord" })).toBe(true);
|
|
238
238
|
});
|
|
239
239
|
|
|
240
|
-
test("valid with Management
|
|
240
|
+
test("valid with Management Company (no otherCollector needed)", () => {
|
|
241
241
|
const validator = getSubschemaValidator(path, schemaId, overlays);
|
|
242
|
-
expect(validator({ collector: "Management
|
|
242
|
+
expect(validator({ collector: "Management Company" })).toBe(true);
|
|
243
243
|
});
|
|
244
244
|
|
|
245
245
|
test("invalid with Other when otherCollector is missing", () => {
|
|
@@ -290,7 +290,7 @@ describe("TA7 5th edition overlay", () => {
|
|
|
290
290
|
?.collectsGroundRent?.properties?.collector;
|
|
291
291
|
expect(collector?.enum).toEqual([
|
|
292
292
|
"Landlord",
|
|
293
|
-
"Management
|
|
293
|
+
"Management Company",
|
|
294
294
|
"Other",
|
|
295
295
|
]);
|
|
296
296
|
});
|
|
@@ -324,8 +324,8 @@ describe("TA7 5th edition overlay", () => {
|
|
|
324
324
|
for (const value of [
|
|
325
325
|
"Freeholder",
|
|
326
326
|
"Landlord",
|
|
327
|
-
"Management
|
|
328
|
-
"Head
|
|
327
|
+
"Management Company",
|
|
328
|
+
"Head Leaseholder",
|
|
329
329
|
"Seller",
|
|
330
330
|
]) {
|
|
331
331
|
expect(validator({ collector: value })).toBe(true);
|
|
@@ -379,8 +379,8 @@ describe("TA7 5th edition overlay", () => {
|
|
|
379
379
|
expect(collector?.enum).toEqual([
|
|
380
380
|
"Freeholder",
|
|
381
381
|
"Landlord",
|
|
382
|
-
"Management
|
|
383
|
-
"Head
|
|
382
|
+
"Management Company",
|
|
383
|
+
"Head Leaseholder",
|
|
384
384
|
"Seller",
|
|
385
385
|
"Other",
|
|
386
386
|
]);
|
|
@@ -411,7 +411,7 @@ describe("TA7 5th edition overlay", () => {
|
|
|
411
411
|
expect(
|
|
412
412
|
validator({
|
|
413
413
|
collectsGroundRent: { collector: "Landlord" },
|
|
414
|
-
collectsbuildingInsurancePremiums: { collector: "Management
|
|
414
|
+
collectsbuildingInsurancePremiums: { collector: "Management Company" },
|
|
415
415
|
})
|
|
416
416
|
).toBe(true);
|
|
417
417
|
});
|
|
@@ -552,10 +552,10 @@ describe("TA7 5th edition overlay", () => {
|
|
|
552
552
|
});
|
|
553
553
|
expect(collectsInsurance.oneOf).toHaveLength(2);
|
|
554
554
|
|
|
555
|
-
// Branch 1: non-Other values (
|
|
555
|
+
// Branch 1: non-Other values (superset of all overlay values)
|
|
556
556
|
const branch1Enum =
|
|
557
557
|
collectsInsurance.oneOf[0].properties.collector.enum;
|
|
558
|
-
expect(branch1Enum).toHaveLength(
|
|
558
|
+
expect(branch1Enum).toHaveLength(7);
|
|
559
559
|
expect(branch1Enum).not.toContain("Other");
|
|
560
560
|
|
|
561
561
|
// Branch 2: Other + required otherCollector
|