@pdtf/schemas 3.6.0-9 → 3.6.0-dev.3

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.
Files changed (191) hide show
  1. package/CLAUDE.md +101 -0
  2. package/README.md +57 -33
  3. package/docs/branch-release-workflow.md +138 -0
  4. package/docs/sef25-extensions-ui-spec.md +355 -0
  5. package/index.js +131 -75
  6. package/package.json +6 -2
  7. package/pensive-tesla-d0d355/CLAUDE.md +101 -0
  8. package/pensive-tesla-d0d355/LICENSE +21 -0
  9. package/pensive-tesla-d0d355/README.md +435 -0
  10. package/pensive-tesla-d0d355/docs/branch-release-workflow.md +138 -0
  11. package/pensive-tesla-d0d355/docs/sef25-extensions-ui-spec.md +355 -0
  12. package/pensive-tesla-d0d355/index.js +654 -0
  13. package/pensive-tesla-d0d355/package-lock.json +7297 -0
  14. package/pensive-tesla-d0d355/package.json +44 -0
  15. package/pensive-tesla-d0d355/src/examples/v1/exampleAddParticipantVouch.json +32 -0
  16. package/pensive-tesla-d0d355/src/examples/v1/exampleDocumentedVouch.json +40 -0
  17. package/pensive-tesla-d0d355/src/examples/v1/exampleElectronicRecord.json +30 -0
  18. package/pensive-tesla-d0d355/src/examples/v1/exampleTransaction.json +878 -0
  19. package/pensive-tesla-d0d355/src/examples/v1/exampleVouch.json +25 -0
  20. package/pensive-tesla-d0d355/src/examples/v2/exampleTransaction.json +901 -0
  21. package/pensive-tesla-d0d355/src/examples/v3/exampleAddParticipantVouch.json +38 -0
  22. package/pensive-tesla-d0d355/src/examples/v3/exampleCustomOverlay.json +55 -0
  23. package/pensive-tesla-d0d355/src/examples/v3/exampleCustomOverlay2.json +93 -0
  24. package/pensive-tesla-d0d355/src/examples/v3/exampleDocumentedVouch.json +47 -0
  25. package/pensive-tesla-d0d355/src/examples/v3/exampleElectronicRecord.json +36 -0
  26. package/pensive-tesla-d0d355/src/examples/v3/exampleTransaction.json +1038 -0
  27. package/pensive-tesla-d0d355/src/examples/v3/exampleVouch.json +32 -0
  28. package/pensive-tesla-d0d355/src/mappings/SendPropertyDetailsRequestSchema.json +1588 -0
  29. package/pensive-tesla-d0d355/src/mappings/adf.js +198 -0
  30. package/pensive-tesla-d0d355/src/schemas/v1/GeoJSON.json +1279 -0
  31. package/pensive-tesla-d0d355/src/schemas/v1/baspiNotes.html +102 -0
  32. package/pensive-tesla-d0d355/src/schemas/v1/energy-performance-certificate.json +124 -0
  33. package/pensive-tesla-d0d355/src/schemas/v1/freehold-information.json +2051 -0
  34. package/pensive-tesla-d0d355/src/schemas/v1/leasehold-information.json +2064 -0
  35. package/pensive-tesla-d0d355/src/schemas/v1/legal-information.json +1045 -0
  36. package/pensive-tesla-d0d355/src/schemas/v1/material-facts.json +2109 -0
  37. package/pensive-tesla-d0d355/src/schemas/v1/pdtf-transaction-search-results.json +40 -0
  38. package/pensive-tesla-d0d355/src/schemas/v1/pdtf-transaction.json +191 -0
  39. package/pensive-tesla-d0d355/src/schemas/v1/searches/drainage-and-water.json +261 -0
  40. package/pensive-tesla-d0d355/src/schemas/v1/searches/local-land-charges.json +69 -0
  41. package/pensive-tesla-d0d355/src/schemas/v1/searches/local-searches-required.json +857 -0
  42. package/pensive-tesla-d0d355/src/schemas/v1/searches.json +237 -0
  43. package/pensive-tesla-d0d355/src/schemas/v1/title-deed.json +841 -0
  44. package/pensive-tesla-d0d355/src/schemas/v2/baspiNotes.html +102 -0
  45. package/pensive-tesla-d0d355/src/schemas/v2/combined.json +37731 -0
  46. package/pensive-tesla-d0d355/src/schemas/v2/overlays/baspi.json +8132 -0
  47. package/pensive-tesla-d0d355/src/schemas/v2/overlays/con29DW.json +705 -0
  48. package/pensive-tesla-d0d355/src/schemas/v2/overlays/con29R.json +2956 -0
  49. package/pensive-tesla-d0d355/src/schemas/v2/overlays/fme1.json +1259 -0
  50. package/pensive-tesla-d0d355/src/schemas/v2/overlays/llc1.json +25 -0
  51. package/pensive-tesla-d0d355/src/schemas/v2/overlays/lpe1.json +2171 -0
  52. package/pensive-tesla-d0d355/src/schemas/v2/overlays/nts.json +326 -0
  53. package/pensive-tesla-d0d355/src/schemas/v2/overlays/oc1.json +2799 -0
  54. package/pensive-tesla-d0d355/src/schemas/v2/overlays/piq.json +3419 -0
  55. package/pensive-tesla-d0d355/src/schemas/v2/overlays/rds.json +3736 -0
  56. package/pensive-tesla-d0d355/src/schemas/v2/overlays/ta10.json +5306 -0
  57. package/pensive-tesla-d0d355/src/schemas/v2/overlays/ta6.json +4533 -0
  58. package/pensive-tesla-d0d355/src/schemas/v2/overlays/ta7.json +1045 -0
  59. package/pensive-tesla-d0d355/src/schemas/v2/pdtf-transaction.json +34351 -0
  60. package/pensive-tesla-d0d355/src/schemas/v2/skeleton.json +3973 -0
  61. package/pensive-tesla-d0d355/src/schemas/v3/combined.json +48469 -0
  62. package/pensive-tesla-d0d355/src/schemas/v3/compactSkeleton.txt +4519 -0
  63. package/pensive-tesla-d0d355/src/schemas/v3/overlays/README.md +299 -0
  64. package/pensive-tesla-d0d355/src/schemas/v3/overlays/baspi4.json +8025 -0
  65. package/pensive-tesla-d0d355/src/schemas/v3/overlays/baspi5.json +8175 -0
  66. package/pensive-tesla-d0d355/src/schemas/v3/overlays/con29DW.json +716 -0
  67. package/pensive-tesla-d0d355/src/schemas/v3/overlays/con29R.json +2981 -0
  68. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/ac.json +333 -0
  69. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/as.json +74 -0
  70. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/dk.json +32 -0
  71. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/dr.json +73 -0
  72. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/er.json +85 -0
  73. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/fd.json +75 -0
  74. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/hi.json +51 -0
  75. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/hs.json +73 -0
  76. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/ic.json +59 -0
  77. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/jk.json +96 -0
  78. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/la.json +85 -0
  79. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/lc.json +75 -0
  80. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/ma.json +90 -0
  81. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/mc.json +38 -0
  82. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/mi.json +69 -0
  83. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/nd.json +43 -0
  84. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/oa.json +24 -0
  85. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/oc.json +57 -0
  86. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/pc.json +37 -0
  87. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/ph.json +194 -0
  88. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/rw.json +68 -0
  89. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/sb.json +73 -0
  90. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/sc.json +129 -0
  91. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/sd.json +63 -0
  92. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/sf.json +74 -0
  93. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/sl.json +68 -0
  94. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/ta.json +252 -0
  95. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/tf.json +103 -0
  96. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/tr.json +73 -0
  97. package/pensive-tesla-d0d355/src/schemas/v3/overlays/extensions/wg.json +350 -0
  98. package/pensive-tesla-d0d355/src/schemas/v3/overlays/fme1.json +1266 -0
  99. package/pensive-tesla-d0d355/src/schemas/v3/overlays/llc1.json +25 -0
  100. package/pensive-tesla-d0d355/src/schemas/v3/overlays/lpe1.json +2199 -0
  101. package/pensive-tesla-d0d355/src/schemas/v3/overlays/nts.json +2157 -0
  102. package/pensive-tesla-d0d355/src/schemas/v3/overlays/nts2.json +2742 -0
  103. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ntsl.json +1813 -0
  104. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ntsl2.json +2217 -0
  105. package/pensive-tesla-d0d355/src/schemas/v3/overlays/oc1.json +2817 -0
  106. package/pensive-tesla-d0d355/src/schemas/v3/overlays/piq.json +3322 -0
  107. package/pensive-tesla-d0d355/src/schemas/v3/overlays/rds.json +3665 -0
  108. package/pensive-tesla-d0d355/src/schemas/v3/overlays/sef25.json +1639 -0
  109. package/pensive-tesla-d0d355/src/schemas/v3/overlays/sr24.json +38 -0
  110. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ta10.json +4654 -0
  111. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ta6.json +4568 -0
  112. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ta6ed6.json +6534 -0
  113. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ta7.json +1537 -0
  114. package/pensive-tesla-d0d355/src/schemas/v3/overlays/ta7ed5.json +1551 -0
  115. package/pensive-tesla-d0d355/src/schemas/v3/pdtf-transaction.json +41573 -0
  116. package/pensive-tesla-d0d355/src/schemas/v3/skeleton.json +5767 -0
  117. package/pensive-tesla-d0d355/src/schemas/verifiedClaims/README.md +21 -0
  118. package/pensive-tesla-d0d355/src/schemas/verifiedClaims/pdtf-verified-claims.json +447 -0
  119. package/pensive-tesla-d0d355/src/utils/compactSkeleton.js +84 -0
  120. package/pensive-tesla-d0d355/src/utils/countTokens.js +67 -0
  121. package/pensive-tesla-d0d355/src/utils/extractExtensionOverlays.js +624 -0
  122. package/pensive-tesla-d0d355/src/utils/extractOverlay.js +381 -0
  123. package/pensive-tesla-d0d355/src/utils/extractProperties.js +44 -0
  124. package/pensive-tesla-d0d355/src/utils/listPathTitles.js +36 -0
  125. package/pensive-tesla-d0d355/src/utils/minimalSkeleton.js +85 -0
  126. package/pensive-tesla-d0d355/src/utils/pathList.csv +903 -0
  127. package/pensive-tesla-d0d355/src/utils/pathSkeleton.js +181 -0
  128. package/src/examples/v3/exampleTransaction.json +3 -3
  129. package/src/schemas/v3/combined.json +8047 -1982
  130. package/src/schemas/v3/compactSkeleton.txt +379 -5
  131. package/src/schemas/v3/overlays/baspi4.json +164 -21
  132. package/src/schemas/v3/overlays/baspi5.json +169 -23
  133. package/src/schemas/v3/overlays/extensions/ac.json +333 -0
  134. package/src/schemas/v3/overlays/extensions/as.json +4 -2
  135. package/src/schemas/v3/overlays/extensions/dk.json +32 -0
  136. package/src/schemas/v3/overlays/extensions/dr.json +9 -9
  137. package/src/schemas/v3/overlays/extensions/er.json +4 -2
  138. package/src/schemas/v3/overlays/extensions/fd.json +6 -3
  139. package/src/schemas/v3/overlays/extensions/hi.json +6 -3
  140. package/src/schemas/v3/overlays/extensions/hs.json +4 -2
  141. package/src/schemas/v3/overlays/extensions/ic.json +59 -0
  142. package/src/schemas/v3/overlays/extensions/jk.json +28 -8
  143. package/src/schemas/v3/overlays/extensions/la.json +4 -2
  144. package/src/schemas/v3/overlays/extensions/lc.json +75 -0
  145. package/src/schemas/v3/overlays/extensions/ma.json +6 -3
  146. package/src/schemas/v3/overlays/extensions/mc.json +4 -2
  147. package/src/schemas/v3/overlays/extensions/mi.json +69 -0
  148. package/src/schemas/v3/overlays/extensions/nd.json +43 -0
  149. package/src/schemas/v3/overlays/extensions/oa.json +4 -2
  150. package/src/schemas/v3/overlays/extensions/oc.json +4 -2
  151. package/src/schemas/v3/overlays/extensions/pc.json +37 -0
  152. package/src/schemas/v3/overlays/extensions/ph.json +194 -0
  153. package/src/schemas/v3/overlays/extensions/rw.json +68 -0
  154. package/src/schemas/v3/overlays/extensions/sb.json +4 -2
  155. package/src/schemas/v3/overlays/extensions/sc.json +129 -0
  156. package/src/schemas/v3/overlays/extensions/sd.json +63 -0
  157. package/src/schemas/v3/overlays/extensions/sf.json +4 -2
  158. package/src/schemas/v3/overlays/extensions/sl.json +4 -2
  159. package/src/schemas/v3/overlays/extensions/ta.json +204 -0
  160. package/src/schemas/v3/overlays/extensions/tf.json +6 -3
  161. package/src/schemas/v3/overlays/extensions/tr.json +73 -0
  162. package/src/schemas/v3/overlays/extensions/wg.json +350 -0
  163. package/src/schemas/v3/overlays/fme1.json +16 -14
  164. package/src/schemas/v3/overlays/lpe1.json +60 -30
  165. package/src/schemas/v3/overlays/nts.json +68 -1
  166. package/src/schemas/v3/overlays/nts2.json +68 -4
  167. package/src/schemas/v3/overlays/ntsl.json +68 -1
  168. package/src/schemas/v3/overlays/ntsl2.json +68 -4
  169. package/src/schemas/v3/overlays/piq.json +39 -4
  170. package/src/schemas/v3/overlays/rds.json +117 -8
  171. package/src/schemas/v3/overlays/sef25.json +1639 -0
  172. package/src/schemas/v3/overlays/ta6.json +46 -16
  173. package/src/schemas/v3/overlays/ta6ed6.json +6534 -0
  174. package/src/schemas/v3/overlays/ta7.json +70 -6
  175. package/src/schemas/v3/overlays/ta7ed5.json +1551 -0
  176. package/src/schemas/v3/pdtf-transaction.json +4565 -1021
  177. package/src/schemas/v3/skeleton.json +510 -38
  178. package/src/utils/extractExtensionOverlays.js +293 -31
  179. package/src/utils/extractOverlay.js +94 -27
  180. package/src/utils/pathSkeleton.js +1 -1
  181. package/.claude/settings.local.json +0 -42
  182. package/.github/workflows/pages.yml +0 -50
  183. package/CNAME +0 -1
  184. package/_config.yml +0 -1
  185. package/src/tests/v3/caching.test.js +0 -591
  186. package/src/tests/v3/enquiries.test.js +0 -1096
  187. package/src/tests/v3/extensionOverlays.test.js +0 -525
  188. package/src/tests/v3/offers.test.js +0 -823
  189. package/src/tests/v3/patternProperties.test.js +0 -688
  190. package/src/tests/v3/transactionSchema.test.js +0 -615
  191. package/src/tests/v3/verifiedClaimsValidator.test.js +0 -195
@@ -1,615 +0,0 @@
1
- const jp = require("jsonpointer");
2
- const fs = require("fs");
3
-
4
- const {
5
- getTransactionSchema,
6
- getSubschema,
7
- isPathValid,
8
- getValidator,
9
- getSubschemaValidator,
10
- getTitleAtPath,
11
- } = require("../../../index.js");
12
-
13
- const exampleTransaction = require("../../examples/v3/exampleTransaction.json");
14
-
15
- const schemaId =
16
- "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json";
17
- // const validator = getValidator(schemaId);
18
- const v3TransactionSchema = getTransactionSchema(schemaId);
19
-
20
- test("exports a property pack schema, v3 with no overlay by default", () => {
21
- const testSchema = getTransactionSchema(schemaId);
22
- // expect(testSchema.$id).toEqual(
23
- // "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json"
24
- // );
25
- expect(testSchema.properties.propertyPack.properties.baspi5Ref).toEqual(
26
- undefined
27
- );
28
- });
29
-
30
- test("sample is valid BASPI", () => {
31
- const testSchema = getTransactionSchema(schemaId, ["baspiV4"]);
32
- expect(testSchema.properties.propertyPack.baspi4Ref).toEqual("0");
33
- const validator = getValidator(schemaId, ["baspiV4"]);
34
- const isValid = validator(exampleTransaction);
35
- expect(isValid).toBe(true);
36
- });
37
-
38
- test("sample is valid NTS", () => {
39
- const validator = getValidator(schemaId, ["nts2023"]);
40
- const isValid = validator(exampleTransaction);
41
- expect(isValid).toBe(true);
42
- });
43
-
44
- test("sample is not valid nts2025 out of the box", () => {
45
- const validator = getValidator(schemaId, ["nts2025"]);
46
- const isValid = validator(exampleTransaction);
47
- expect(isValid).toBe(false);
48
- expect(validator.errors.length).toBe(3);
49
- expect(validator.errors.map((e) => e.message)).toEqual([
50
- "must have required property 'transferFees'",
51
- "must have required property 'constructionType'",
52
- "must have required property 'floodDefences'",
53
- ]);
54
- });
55
-
56
- test("sample is valid nts2025 with some additions", () => {
57
- const validator = getValidator(schemaId, ["nts2025"]);
58
- const clonedExampleTransaction = JSON.parse(
59
- JSON.stringify(exampleTransaction)
60
- );
61
- clonedExampleTransaction.propertyPack.ownership.ownershipsToBeTransferred[0].leaseholdInformation.serviceCharge.transferFees =
62
- {
63
- yesNo: "Yes",
64
- details: "Transfer fees exist",
65
- };
66
- clonedExampleTransaction.propertyPack.typeOfConstruction.isStandardForm = {
67
- yesNo: "Yes",
68
- constructionType: "Timber frame",
69
- };
70
- clonedExampleTransaction.propertyPack.environmentalIssues.flooding.floodDefences =
71
- {
72
- hasFloodDefences: "Yes",
73
- details: "Flood defences exist",
74
- };
75
-
76
- const isValid = validator(clonedExampleTransaction);
77
- expect(isValid).toBe(true);
78
- });
79
-
80
- test("sample is not valid NTSL (lettings)", () => {
81
- const validator = getValidator(schemaId, ["ntsl2023"]);
82
- const isValid = validator(exampleTransaction);
83
- expect(isValid).toBe(false);
84
- expect(validator.errors[0].message).toBe(
85
- "must have required property 'lettingInformation'"
86
- );
87
- });
88
-
89
- test("sample is valid NTSL if we change it accordingly", () => {
90
- const validator = getValidator(schemaId, ["ntsl2023"]);
91
- const clonedExampleTransaction = JSON.parse(
92
- JSON.stringify(exampleTransaction)
93
- );
94
- clonedExampleTransaction.propertyPack.lettingInformation = {
95
- rent: 3500,
96
- rentFrequency: "Monthly",
97
- securityDeposit: 5000,
98
- };
99
- delete clonedExampleTransaction.propertyPack.priceInformation;
100
- delete clonedExampleTransaction.propertyPack.ownership;
101
- const isValid = validator(clonedExampleTransaction);
102
- expect(isValid).toBe(true);
103
- });
104
-
105
- test("invalid sample is invalid", () => {
106
- const clonedExampleTransaction = JSON.parse(
107
- JSON.stringify(exampleTransaction)
108
- );
109
- delete clonedExampleTransaction.propertyPack.notices;
110
- const validator = getValidator(schemaId, ["baspiV4"]);
111
- const isValid = validator(clonedExampleTransaction);
112
- expect(isValid).toBe(false);
113
- });
114
-
115
- test("sample with missing dependent required fields is invalid", () => {
116
- const clonedExampleTransaction = JSON.parse(
117
- JSON.stringify(exampleTransaction)
118
- );
119
- clonedExampleTransaction.propertyPack.ownership.ownershipsToBeTransferred[0].ownershipType =
120
- "leasehold";
121
- const validator = getValidator(schemaId);
122
- const isValid = validator(clonedExampleTransaction);
123
- expect(isValid).toBe(false);
124
- });
125
-
126
- test("sample with missing dependent required fields with NTS overlay is invalid", () => {
127
- // Previously a required field was missing from the NTS overlay
128
- const clonedExampleTransaction = JSON.parse(
129
- JSON.stringify(exampleTransaction)
130
- );
131
- clonedExampleTransaction.propertyPack.ownership.ownershipsToBeTransferred[0].leaseholdInformation =
132
- undefined;
133
- const validator = getValidator(schemaId, ["nts2023"]);
134
- const isValid = validator(clonedExampleTransaction);
135
- expect(isValid).toBe(false);
136
- });
137
-
138
- test("correctly gets a top level subschema", () => {
139
- const subschema = getSubschema("/propertyPack");
140
- expect(subschema.title).toBe("Property Pack");
141
- });
142
-
143
- test("correctly identifies a valid path", () => {
144
- const isValid = isPathValid("/propertyPack");
145
- expect(isValid).toBe(true);
146
- });
147
-
148
- test("correctly identifies an undefined invalid path", () => {
149
- const isValid = isPathValid("/propertyPack/materialItems");
150
- expect(isValid).toBe(false);
151
- });
152
-
153
- test("correctly identifies an error generating invalid path", () => {
154
- const isValid = isPathValid(
155
- "/propertyPack/materialItems/someProperty/item",
156
- schemaId
157
- );
158
- expect(isValid).toBe(false);
159
- });
160
-
161
- test("correctly identifies an array invalid path", () => {
162
- const isValid = isPathValid("/propertyPack/1/item");
163
- expect(isValid).toBe(false);
164
- });
165
-
166
- test("correctly gets a subschema", () => {
167
- const subschema = getSubschema("/propertyPack/notices", schemaId);
168
- expect(subschema.title).toBe("Notices which Affect the Property");
169
- });
170
-
171
- test("correctly gets a subschema through an arrays element", () => {
172
- const subschema = getSubschema(
173
- "/propertyPack/titlesToBeSold/0/registerExtract",
174
- schemaId
175
- );
176
- expect(Object.keys(subschema.properties)).toEqual([
177
- "ocSummaryData",
178
- "ocRegisterData",
179
- ]);
180
- });
181
-
182
- test("correctly gets a subschema through a dependency", () => {
183
- const subschema = getSubschema(
184
- "/propertyPack/delayFactors/hasDelayFactors/details",
185
- schemaId
186
- );
187
- expect(subschema.title).toBe(
188
- "Provide details and likely timescale for delay"
189
- );
190
- });
191
-
192
- test("correctly gets another subschema through a dependency", () => {
193
- const subschema = getSubschema(
194
- "/propertyPack/ownership/ownershipsToBeTransferred/0/leaseholdInformation/leaseTerm/lengthOfLeaseInYears",
195
- schemaId
196
- );
197
- expect(subschema.title).toBe("Length of lease (years)");
198
- });
199
-
200
- test("correctly gets yet another subschema through a dependency", () => {
201
- const subschema = getSubschema(
202
- "/propertyPack/ownership/ownershipsToBeTransferred/0/leaseholdInformation/groundRent/rentSubjectToIncrease/rentIncreaseCalculated"
203
- );
204
- expect(subschema.title).toBe("How is the increase calculated?");
205
- });
206
-
207
- test("correctly gets yet, yet another subschema through a dependency", () => {
208
- const subschema = getSubschema(
209
- "/propertyPack/listingAndConservation/isConservationArea/yesNo"
210
- );
211
- expect(subschema.type).toBe("string");
212
- expect(subschema.enum).toStrictEqual(["Yes", "No", "Not known"]);
213
- });
214
-
215
- test("correctly gets yet, yet, yet another subschema through a second item dependency", () => {
216
- const subschema = getSubschema(
217
- "/propertyPack/environmentalIssues/flooding/historicalFlooding/typeOfFlooding"
218
- );
219
- expect(subschema.type).toBe("array");
220
- });
221
-
222
- test("correctly gets yes another subschema but through a non-baspi oneOf structure", () => {
223
- const subschema = getSubschema(
224
- "/propertyPack/titlesToBeSold/0/registerExtract/ocSummaryData/restrictionDetails/restrictionEntry/chargeRestriction/entryDetails/entryText"
225
- );
226
- expect(subschema).toEqual({ type: "string" });
227
- });
228
-
229
- test("correctly gets yes another subschema but through a non-baspi oneOf structure with array option", () => {
230
- const subschema = getSubschema(
231
- "/propertyPack/titlesToBeSold/0/registerExtract/ocSummaryData/restrictionDetails/restrictionEntry/0/chargeRestriction/entryDetails/entryText"
232
- );
233
- expect(subschema).toEqual({ type: "string" });
234
- });
235
-
236
- test("correctly gets an overlaid enum in a subschema", () => {
237
- const subschema = getSubschema(
238
- "/propertyPack/electricity/mainsElectricity/yesNo",
239
- schemaId,
240
- ["nts2023"]
241
- );
242
- expect(subschema.enum).toEqual(["Yes", "No"]);
243
- });
244
-
245
- test("correctly gets a subschema with multiple overlays", () => {
246
- const subschema = getSubschema(
247
- "/propertyPack/parking/parkingArrangements",
248
- schemaId,
249
- ["baspiV5", "ta6ed4"]
250
- );
251
- expect(subschema.baspi5Ref).toBe("A1.6.0");
252
- expect(subschema.ta6Ref).toBe("9.1");
253
- });
254
-
255
- test("correctly gets a subschema validator which is already cached", () => {
256
- const validator = getSubschemaValidator(
257
- "/propertyPack/energyEfficiency/certificate"
258
- );
259
- expect(validator).not.toBeNull();
260
- const anotherValidator = getSubschemaValidator(
261
- "/propertyPack/energyEfficiency/certificate"
262
- );
263
- expect(anotherValidator).not.toBeNull();
264
- });
265
-
266
- test("correctly gets a subschema validator for a TA6 overlay", () => {
267
- const path = "/propertyPack";
268
- const data = jp.get(exampleTransaction, path);
269
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
270
- "ta6ed4",
271
- ]);
272
- let isValid = validator(data);
273
- expect(isValid).toBe(true);
274
- });
275
-
276
- test("correctly gets a subschema validator for a TA7 overlay", () => {
277
- const path = "/propertyPack";
278
- const data = jp.get(exampleTransaction, path);
279
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
280
- "ta7ed3",
281
- ]);
282
- let isValid = validator(data);
283
- expect(isValid).toBe(false);
284
- });
285
-
286
- test("correctly gets a subschema validator for a TA10 overlay", () => {
287
- const path = "/propertyPack";
288
- const data = jp.get(exampleTransaction, path);
289
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
290
- "ta10ed3",
291
- ]);
292
- let isValid = validator(data);
293
- expect(isValid).toBe(false);
294
- });
295
-
296
- test("correctly gets a subschema validator for a TA6 overlay which validates", () => {
297
- const path =
298
- "/propertyPack/guaranteesWarrantiesAndIndemnityInsurances/subsidenceWork";
299
- const data = { yesNo: "Yes" };
300
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
301
- "ta6ed4",
302
- ]);
303
- let isValid = validator(data);
304
- expect(isValid).toBe(false);
305
- expect(validator.errors[0].message).toBe(
306
- "must have required property 'attachments'"
307
- );
308
- });
309
-
310
- test("correctly gets a subschema validator for a TA6 overlay which validates with non-TA6 field missing", () => {
311
- const path = "/propertyPack";
312
- const clonedExampleTransaction = JSON.parse(
313
- JSON.stringify(exampleTransaction)
314
- );
315
- const data = jp.get(exampleTransaction, path);
316
- data.uprn = undefined;
317
- const validator = getSubschemaValidator(
318
- path,
319
- clonedExampleTransaction.$schema,
320
- ["ta6ed4"]
321
- );
322
- let isValid = validator(data);
323
- expect(isValid).toBe(true);
324
- });
325
-
326
- test("correctly gets a subschema validator for a TA6 overlay which validates with non-TA6 section missing", () => {
327
- const path = "/propertyPack";
328
- const clonedExampleTransaction = JSON.parse(
329
- JSON.stringify(exampleTransaction)
330
- );
331
- const data = jp.get(clonedExampleTransaction, path);
332
- data.smartHomeSystems = undefined;
333
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
334
- "ta6ed4",
335
- ]);
336
- let isValid = validator(data);
337
- expect(isValid).toBe(true);
338
- });
339
-
340
- test("correctly gets a subschema validator for a TA6 overlay which fails to validate with BASPI/TA6 section missing", () => {
341
- const path = "/propertyPack";
342
- const clonedExampleTransaction = JSON.parse(
343
- JSON.stringify(exampleTransaction)
344
- );
345
- const data = jp.get(clonedExampleTransaction, path);
346
- data.waterAndDrainage = {};
347
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
348
- "ta6ed4",
349
- ]);
350
- let isValid = validator(data);
351
- expect(isValid).toBe(false);
352
- });
353
-
354
- test("correctly gets a subschema validator for an NTS overlay", () => {
355
- const path = "/propertyPack";
356
- const clonedExampleTransaction = JSON.parse(
357
- JSON.stringify(exampleTransaction)
358
- );
359
- const data = jp.get(clonedExampleTransaction, path);
360
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
361
- "nts2023",
362
- ]);
363
- let isValid = validator(data);
364
- expect(isValid).toBe(true);
365
- });
366
-
367
- test("correctly gets a subschema validator for an TA7 overlay", () => {
368
- const path = "/propertyPack";
369
- const clonedExampleTransaction = JSON.parse(
370
- JSON.stringify(exampleTransaction)
371
- );
372
- const data = jp.get(clonedExampleTransaction, path);
373
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
374
- "ta7ed3",
375
- ]);
376
- let isValid = validator(data);
377
- expect(isValid).toBe(false);
378
- });
379
-
380
- test("correctly gets a subschema validator which validates", () => {
381
- const path = "/propertyPack/notices";
382
- const validator = getSubschemaValidator(path);
383
- const data = jp.get(exampleTransaction, path);
384
- expect(data.neighbourDevelopment.yesNo).toBe("No");
385
- let isValid = validator(data);
386
- expect(isValid).toBe(true);
387
- data.neighbourDevelopment.yesNo = "Invalid string";
388
- isValid = validator(data);
389
- expect(isValid).toBe(false);
390
- });
391
-
392
- test("correctly gets titles across schemas, arrays and non-existient title properties", () => {
393
- expect(
394
- getTitleAtPath(
395
- v3TransactionSchema,
396
- "/propertyPack/ownership/ownershipsToBeTransferred/0/ownershipType"
397
- )
398
- ).toBe("What type of ownership is the property?");
399
-
400
- expect(
401
- getTitleAtPath(
402
- v3TransactionSchema,
403
- "/propertyPack/ownership/ownershipsToBeTransferred/0/leaseholdInformation/leaseTerm/lengthOfLeaseInYears"
404
- )
405
- ).toBe("Length of lease (years)");
406
-
407
- expect(getTitleAtPath(v3TransactionSchema, "/propertyPack/invalidPath")).toBe(
408
- undefined
409
- );
410
-
411
- expect(
412
- getTitleAtPath(
413
- v3TransactionSchema,
414
- "/propertyPack/titlesToBeSold/0/registerExtract"
415
- )
416
- ).toBe("HMLR Official Copy Register Extract");
417
-
418
- expect(
419
- getTitleAtPath(
420
- v3TransactionSchema,
421
- "/propertyPack/titlesToBeSold/0/registerExtract/ocSummaryData/propertyAddress"
422
- )
423
- ).toBe("Property address");
424
-
425
- expect(
426
- getTitleAtPath(
427
- v3TransactionSchema,
428
- "/propertyPack/titlesToBeSold/0/registerExtract/ocSummaryData/invalidProp"
429
- )
430
- ).toBe(undefined);
431
-
432
- expect(
433
- getTitleAtPath(
434
- v3TransactionSchema,
435
- "/propertyPack/energyEfficiency/certificate/currentEnergyRating"
436
- )
437
- ).toBe("Current energy efficiency rating");
438
-
439
- expect(
440
- getTitleAtPath(
441
- v3TransactionSchema,
442
- "/propertyPack/occupiers/othersAged17OrOver/aged17OrOverNames"
443
- )
444
- ).toBe("Please provide their full names and ages.");
445
- });
446
- test("validates a valid contract", () => {
447
- const path = "/contracts";
448
- const data = jp.get(exampleTransaction, path);
449
- const validator = getSubschemaValidator(path, exampleTransaction.$schema);
450
- const isValid = validator(data);
451
- expect(isValid).toBe(true);
452
- });
453
-
454
- test("ntsl2025 requires parking and listingAndConservation fields", () => {
455
- // This test validates that the ntsl2025 overlay correctly enforces required fields
456
- // for the parking and listingAndConservation sections.
457
- // It should fail validation when these fields are missing.
458
- // NOTE: This test will fail until overlays are regenerated from combined.json
459
- const validator = getValidator(schemaId, ["ntsl2025"]);
460
- const clonedExampleTransaction = JSON.parse(
461
- JSON.stringify(exampleTransaction)
462
- );
463
-
464
- // Set up lettings-specific fields
465
- clonedExampleTransaction.propertyPack.lettingInformation = {
466
- rent: 3500,
467
- rentFrequency: "Monthly",
468
- securityDeposit: 5000,
469
- };
470
- delete clonedExampleTransaction.propertyPack.priceInformation;
471
- delete clonedExampleTransaction.propertyPack.ownership;
472
-
473
- // Remove ALL parking fields - this should make validation fail
474
- delete clonedExampleTransaction.propertyPack.parking.parkingArrangements;
475
- delete clonedExampleTransaction.propertyPack.parking.disabledParking;
476
- delete clonedExampleTransaction.propertyPack.parking.controlledParking;
477
- delete clonedExampleTransaction.propertyPack.parking
478
- .electricVehicleChargingPoint;
479
-
480
- // Remove ALL listingAndConservation fields - this should make validation fail
481
- delete clonedExampleTransaction.propertyPack.listingAndConservation.isListed;
482
- delete clonedExampleTransaction.propertyPack.listingAndConservation
483
- .isConservationArea;
484
- delete clonedExampleTransaction.propertyPack.listingAndConservation
485
- .hasTreePreservationOrder;
486
-
487
- const isValid = validator(clonedExampleTransaction);
488
-
489
- // The data should be INVALID because required fields are missing
490
- expect(isValid).toBe(false);
491
-
492
- // Specifically check that parking and listingAndConservation fields are reported as missing
493
- const errorMessages = validator.errors.map((e) => e.message);
494
- expect(errorMessages).toContain(
495
- "must have required property 'parkingArrangements'"
496
- );
497
- expect(errorMessages).toContain(
498
- "must have required property 'disabledParking'"
499
- );
500
- expect(errorMessages).toContain(
501
- "must have required property 'controlledParking'"
502
- );
503
- expect(errorMessages).toContain(
504
- "must have required property 'electricVehicleChargingPoint'"
505
- );
506
- expect(errorMessages).toContain("must have required property 'isListed'");
507
- expect(errorMessages).toContain(
508
- "must have required property 'isConservationArea'"
509
- );
510
- expect(errorMessages).toContain(
511
- "must have required property 'hasTreePreservationOrder'"
512
- );
513
- });
514
-
515
- test("waterAndDrainage state is invalid under nts2023 overlay when mainsFoulDrainage yesNo is Not known", () => {
516
- const validator = getValidator(schemaId, ["nts2023"]);
517
- const clonedExampleTransaction = JSON.parse(
518
- JSON.stringify(exampleTransaction)
519
- );
520
-
521
- // Set the waterAndDrainage to an actually invalid state for nts2023
522
- // The nts overlay restricts mainsFoulDrainage.yesNo to only "Yes" or "No"
523
- // (not "Not known" like the base schema allows)
524
- clonedExampleTransaction.propertyPack.waterAndDrainage = {
525
- water: {
526
- mainsWater: {
527
- yesNo: "Yes",
528
- waterMeter: {
529
- isSupplyMetered: "No",
530
- },
531
- },
532
- },
533
- drainage: {
534
- mainsSurfaceWaterDrainage: {
535
- yesNo: "Yes",
536
- },
537
- mainsFoulDrainage: {
538
- yesNo: "Not known", // This is invalid under nts2023 overlay
539
- },
540
- },
541
- };
542
-
543
- const isValid = validator(clonedExampleTransaction);
544
- expect(isValid).toBe(false);
545
-
546
- // Check that the validation error is about the invalid enum value
547
- const relevantError = validator.errors.find(
548
- (error) =>
549
- error.instancePath.includes("mainsFoulDrainage") &&
550
- error.message.includes("must be equal to one of the allowed values")
551
- );
552
- expect(relevantError).toBeDefined();
553
- });
554
-
555
- test("waterAndDrainage state with mainsFoulDrainage No missing offMainsDrainageSystem is now invalid under nts2023 overlay", () => {
556
- const validator = getValidator(schemaId, ["nts2023"]);
557
- const clonedExampleTransaction = JSON.parse(
558
- JSON.stringify(exampleTransaction)
559
- );
560
-
561
- // Set the waterAndDrainage to the state from the user request
562
- // This SHOULD be invalid because offMainsDrainageSystem is required when mainsFoulDrainage.yesNo is "No"
563
- clonedExampleTransaction.propertyPack.waterAndDrainage = {
564
- water: {
565
- mainsWater: {
566
- yesNo: "Yes",
567
- waterMeter: {
568
- isSupplyMetered: "No",
569
- },
570
- },
571
- },
572
- drainage: {
573
- mainsSurfaceWaterDrainage: {
574
- yesNo: "Yes",
575
- },
576
- mainsFoulDrainage: {
577
- yesNo: "No",
578
- // Missing offMainsDrainageSystem - this should make validation fail
579
- },
580
- },
581
- };
582
-
583
- const isValid = validator(clonedExampleTransaction);
584
- expect(isValid).toBe(false);
585
-
586
- // Check that the validation error is about missing offMainsDrainageSystem
587
- const relevantError = validator.errors.find(
588
- (error) =>
589
- error.instancePath.includes("mainsFoulDrainage") &&
590
- error.message.includes("offMainsDrainageSystem")
591
- );
592
- expect(relevantError).toBeDefined();
593
- });
594
-
595
- test("TA7 overlay organisesBuildingInsurance enum has exactly three items", () => {
596
- const schema = getTransactionSchema(schemaId, ["ta7ed3"]);
597
-
598
- // Navigate to the organisesBuildingInsurance property in the merged schema
599
- const organisesBuildingInsurance =
600
- schema.properties?.propertyPack?.properties?.ownership?.properties
601
- ?.ownershipsToBeTransferred?.items?.oneOf?.[2]?.properties
602
- ?.leaseholdInformation?.properties?.contactDetails?.properties
603
- ?.serviceContactAssignments?.properties?.organisesBuildingInsurance;
604
-
605
- expect(organisesBuildingInsurance).toBeDefined();
606
- expect(organisesBuildingInsurance.enum).toBeDefined();
607
-
608
- // The TA7 overlay defines exactly 3 enum values, which should replace the base schema's 6 values
609
- expect(organisesBuildingInsurance.enum).toHaveLength(3);
610
- expect(organisesBuildingInsurance.enum).toEqual([
611
- "the Lessees",
612
- "Management Company",
613
- "Landlord",
614
- ]);
615
- });