@pdtf/schemas 3.6.0-dev.4 → 3.6.0-dev.6

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 (131) hide show
  1. package/compassionate-easley-bafb14/CLAUDE.md +101 -0
  2. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/README.md +166 -65
  3. package/compassionate-easley-bafb14/docs/branch-release-workflow.md +138 -0
  4. package/compassionate-easley-bafb14/docs/sef25-extensions-ui-spec.md +355 -0
  5. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/index.js +160 -63
  6. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/package-lock.json +13 -10
  7. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/package.json +7 -2
  8. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v3/exampleAddParticipantVouch.json +3 -0
  9. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v3/exampleDocumentedVouch.json +3 -0
  10. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v3/exampleElectronicRecord.json +3 -0
  11. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v3/exampleTransaction.json +7 -3
  12. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v3/exampleVouch.json +3 -0
  13. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/combined.json +8190 -1446
  14. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/compactSkeleton.txt +1208 -14
  15. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/baspi4.json +186 -28
  16. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/baspi5.json +191 -30
  17. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/ac.json +334 -0
  18. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/as.json +4 -2
  19. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/dk.json +33 -0
  20. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/dr.json +9 -9
  21. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/er.json +4 -2
  22. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/fd.json +6 -3
  23. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/hi.json +6 -3
  24. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/hs.json +4 -2
  25. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/ic.json +94 -0
  26. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/jk.json +28 -8
  27. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/la.json +4 -2
  28. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/lc.json +76 -0
  29. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/ma.json +6 -3
  30. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/mc.json +4 -2
  31. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/mi.json +70 -0
  32. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/nd.json +44 -0
  33. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/oa.json +4 -2
  34. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/oc.json +4 -2
  35. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/pc.json +38 -0
  36. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/ph.json +195 -0
  37. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/rw.json +69 -0
  38. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/sb.json +4 -2
  39. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/sc.json +133 -0
  40. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/sd.json +64 -0
  41. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/sf.json +4 -2
  42. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/sl.json +4 -2
  43. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/ta.json +204 -0
  44. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/extensions/tf.json +6 -3
  45. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/tr.json +74 -0
  46. package/compassionate-easley-bafb14/src/schemas/v3/overlays/extensions/wg.json +351 -0
  47. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/fme1.json +16 -14
  48. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/lpe1.json +61 -88
  49. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/nts.json +71 -2
  50. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/nts2.json +71 -5
  51. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/ntsl.json +71 -2
  52. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/ntsl2.json +71 -5
  53. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/piq.json +56 -8
  54. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/rds.json +128 -12
  55. package/compassionate-easley-bafb14/src/schemas/v3/overlays/sef25.json +1653 -0
  56. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/ta10.json +12 -9
  57. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/ta6.json +103 -32
  58. package/compassionate-easley-bafb14/src/schemas/v3/overlays/ta6ed6.json +6536 -0
  59. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/ta7.json +134 -32
  60. package/compassionate-easley-bafb14/src/schemas/v3/overlays/ta7ed5.json +1551 -0
  61. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/pdtf-transaction.json +4835 -490
  62. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/skeleton.json +1481 -37
  63. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/verifiedClaims/README.md +12 -3
  64. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/verifiedClaims/pdtf-verified-claims.json +16 -0
  65. package/compassionate-easley-bafb14/src/utils/extractExtensionOverlays.js +633 -0
  66. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/utils/extractOverlay.js +129 -38
  67. package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/utils/pathSkeleton.js +1 -1
  68. package/package.json +1 -1
  69. package/src/schemas/v3/combined.json +5 -1
  70. package/src/schemas/v3/overlays/extensions/ic.json +42 -8
  71. package/src/schemas/v3/overlays/sef25.json +16 -2
  72. package/src/utils/extractExtensionOverlays.js +1 -1
  73. package/keen-dewdney-6ae15b/src/tests/v3/caching.test.js +0 -591
  74. package/keen-dewdney-6ae15b/src/tests/v3/extensionOverlays.test.js +0 -525
  75. package/keen-dewdney-6ae15b/src/tests/v3/transactionSchema.test.js +0 -574
  76. package/keen-dewdney-6ae15b/src/tests/v3/verifiedClaimsValidator.test.js +0 -128
  77. package/keen-dewdney-6ae15b/src/utils/extractExtensionOverlays.js +0 -362
  78. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/LICENSE +0 -0
  79. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v1/exampleAddParticipantVouch.json +0 -0
  80. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v1/exampleDocumentedVouch.json +0 -0
  81. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v1/exampleElectronicRecord.json +0 -0
  82. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v1/exampleTransaction.json +0 -0
  83. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v1/exampleVouch.json +0 -0
  84. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v2/exampleTransaction.json +0 -0
  85. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v3/exampleCustomOverlay.json +0 -0
  86. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/examples/v3/exampleCustomOverlay2.json +0 -0
  87. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/mappings/SendPropertyDetailsRequestSchema.json +0 -0
  88. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/mappings/adf.js +0 -0
  89. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/GeoJSON.json +0 -0
  90. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/baspiNotes.html +0 -0
  91. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/energy-performance-certificate.json +0 -0
  92. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/freehold-information.json +0 -0
  93. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/leasehold-information.json +0 -0
  94. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/legal-information.json +0 -0
  95. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/material-facts.json +0 -0
  96. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/pdtf-transaction-search-results.json +0 -0
  97. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/pdtf-transaction.json +0 -0
  98. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/searches/drainage-and-water.json +0 -0
  99. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/searches/local-land-charges.json +0 -0
  100. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/searches/local-searches-required.json +0 -0
  101. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/searches.json +0 -0
  102. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v1/title-deed.json +0 -0
  103. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/baspiNotes.html +0 -0
  104. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/combined.json +0 -0
  105. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/baspi.json +0 -0
  106. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/con29DW.json +0 -0
  107. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/con29R.json +0 -0
  108. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/fme1.json +0 -0
  109. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/llc1.json +0 -0
  110. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/lpe1.json +0 -0
  111. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/nts.json +0 -0
  112. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/oc1.json +0 -0
  113. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/piq.json +0 -0
  114. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/rds.json +0 -0
  115. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/ta10.json +0 -0
  116. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/ta6.json +0 -0
  117. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/overlays/ta7.json +0 -0
  118. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/pdtf-transaction.json +0 -0
  119. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v2/skeleton.json +0 -0
  120. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/README.md +0 -0
  121. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/con29DW.json +0 -0
  122. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/con29R.json +0 -0
  123. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/llc1.json +0 -0
  124. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/oc1.json +0 -0
  125. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/schemas/v3/overlays/sr24.json +0 -0
  126. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/utils/compactSkeleton.js +0 -0
  127. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/utils/countTokens.js +0 -0
  128. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/utils/extractProperties.js +0 -0
  129. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/utils/listPathTitles.js +0 -0
  130. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/utils/minimalSkeleton.js +0 -0
  131. /package/{keen-dewdney-6ae15b → compassionate-easley-bafb14}/src/utils/pathList.csv +0 -0
@@ -1,574 +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(path, exampleTransaction.$schema, [
318
- "ta6ed4",
319
- ]);
320
- let isValid = validator(data);
321
- expect(isValid).toBe(true);
322
- });
323
-
324
- test("correctly gets a subschema validator for a TA6 overlay which validates with non-TA6 section missing", () => {
325
- const path = "/propertyPack";
326
- const clonedExampleTransaction = JSON.parse(
327
- JSON.stringify(exampleTransaction)
328
- );
329
- const data = jp.get(clonedExampleTransaction, path);
330
- data.smartHomeSystems = undefined;
331
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
332
- "ta6ed4",
333
- ]);
334
- let isValid = validator(data);
335
- expect(isValid).toBe(true);
336
- });
337
-
338
- test("correctly gets a subschema validator for a TA6 overlay which fails to validate with BASPI/TA6 section missing", () => {
339
- const path = "/propertyPack";
340
- const clonedExampleTransaction = JSON.parse(
341
- JSON.stringify(exampleTransaction)
342
- );
343
- const data = jp.get(clonedExampleTransaction, path);
344
- data.waterAndDrainage = {};
345
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
346
- "ta6ed4",
347
- ]);
348
- let isValid = validator(data);
349
- expect(isValid).toBe(false);
350
- });
351
-
352
- test("correctly gets a subschema validator for an NTS overlay", () => {
353
- const path = "/propertyPack";
354
- const clonedExampleTransaction = JSON.parse(
355
- JSON.stringify(exampleTransaction)
356
- );
357
- const data = jp.get(clonedExampleTransaction, path);
358
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
359
- "nts2023",
360
- ]);
361
- let isValid = validator(data);
362
- expect(isValid).toBe(true);
363
- });
364
-
365
- test("correctly gets a subschema validator for an TA7 overlay", () => {
366
- const path = "/propertyPack";
367
- const clonedExampleTransaction = JSON.parse(
368
- JSON.stringify(exampleTransaction)
369
- );
370
- const data = jp.get(clonedExampleTransaction, path);
371
- const validator = getSubschemaValidator(path, exampleTransaction.$schema, [
372
- "ta7ed3",
373
- ]);
374
- let isValid = validator(data);
375
- expect(isValid).toBe(false);
376
- });
377
-
378
- test("correctly gets a subschema validator which validates", () => {
379
- const path = "/propertyPack/notices";
380
- const validator = getSubschemaValidator(path);
381
- const data = jp.get(exampleTransaction, path);
382
- expect(data.neighbourDevelopment.yesNo).toBe("No");
383
- let isValid = validator(data);
384
- expect(isValid).toBe(true);
385
- data.neighbourDevelopment.yesNo = "Invalid string";
386
- isValid = validator(data);
387
- expect(isValid).toBe(false);
388
- });
389
-
390
- test("correctly gets titles across schemas, arrays and non-existient title properties", () => {
391
- expect(
392
- getTitleAtPath(
393
- v3TransactionSchema,
394
- "/propertyPack/ownership/ownershipsToBeTransferred/0/ownershipType"
395
- )
396
- ).toBe("What type of ownership is the property?");
397
-
398
- expect(
399
- getTitleAtPath(
400
- v3TransactionSchema,
401
- "/propertyPack/ownership/ownershipsToBeTransferred/0/leaseholdInformation/leaseTerm/lengthOfLeaseInYears"
402
- )
403
- ).toBe("Length of lease (years)");
404
-
405
- expect(getTitleAtPath(v3TransactionSchema, "/propertyPack/invalidPath")).toBe(
406
- undefined
407
- );
408
-
409
- expect(
410
- getTitleAtPath(
411
- v3TransactionSchema,
412
- "/propertyPack/titlesToBeSold/0/registerExtract"
413
- )
414
- ).toBe("HMLR Official Copy Register Extract");
415
-
416
- expect(
417
- getTitleAtPath(
418
- v3TransactionSchema,
419
- "/propertyPack/titlesToBeSold/0/registerExtract/ocSummaryData/propertyAddress"
420
- )
421
- ).toBe("Property address");
422
-
423
- expect(
424
- getTitleAtPath(
425
- v3TransactionSchema,
426
- "/propertyPack/titlesToBeSold/0/registerExtract/ocSummaryData/invalidProp"
427
- )
428
- ).toBe(undefined);
429
-
430
- expect(
431
- getTitleAtPath(
432
- v3TransactionSchema,
433
- "/propertyPack/energyEfficiency/certificate/currentEnergyRating"
434
- )
435
- ).toBe("Current energy efficiency rating");
436
-
437
- expect(
438
- getTitleAtPath(
439
- v3TransactionSchema,
440
- "/propertyPack/occupiers/othersAged17OrOver/aged17OrOverNames"
441
- )
442
- ).toBe("Please provide their full names and ages.");
443
- });
444
- test("validates a valid contract", () => {
445
- const path = "/contracts";
446
- const data = jp.get(exampleTransaction, path);
447
- const validator = getSubschemaValidator(path, exampleTransaction.$schema);
448
- const isValid = validator(data);
449
- expect(isValid).toBe(true);
450
- });
451
-
452
- test("ntsl2025 requires parking and listingAndConservation fields", () => {
453
- // This test validates that the ntsl2025 overlay correctly enforces required fields
454
- // for the parking and listingAndConservation sections.
455
- // It should fail validation when these fields are missing.
456
- // NOTE: This test will fail until overlays are regenerated from combined.json
457
- const validator = getValidator(schemaId, ["ntsl2025"]);
458
- const clonedExampleTransaction = JSON.parse(
459
- JSON.stringify(exampleTransaction)
460
- );
461
-
462
- // Set up lettings-specific fields
463
- clonedExampleTransaction.propertyPack.lettingInformation = {
464
- rent: 3500,
465
- rentFrequency: "Monthly",
466
- securityDeposit: 5000,
467
- };
468
- delete clonedExampleTransaction.propertyPack.priceInformation;
469
- delete clonedExampleTransaction.propertyPack.ownership;
470
-
471
- // Remove ALL parking fields - this should make validation fail
472
- delete clonedExampleTransaction.propertyPack.parking.parkingArrangements;
473
- delete clonedExampleTransaction.propertyPack.parking.disabledParking;
474
- delete clonedExampleTransaction.propertyPack.parking.controlledParking;
475
- delete clonedExampleTransaction.propertyPack.parking.electricVehicleChargingPoint;
476
-
477
- // Remove ALL listingAndConservation fields - this should make validation fail
478
- delete clonedExampleTransaction.propertyPack.listingAndConservation.isListed;
479
- delete clonedExampleTransaction.propertyPack.listingAndConservation.isConservationArea;
480
- delete clonedExampleTransaction.propertyPack.listingAndConservation.hasTreePreservationOrder;
481
-
482
- const isValid = validator(clonedExampleTransaction);
483
-
484
- // The data should be INVALID because required fields are missing
485
- expect(isValid).toBe(false);
486
-
487
- // Specifically check that parking and listingAndConservation fields are reported as missing
488
- const errorMessages = validator.errors.map(e => e.message);
489
- expect(errorMessages).toContain("must have required property 'parkingArrangements'");
490
- expect(errorMessages).toContain("must have required property 'disabledParking'");
491
- expect(errorMessages).toContain("must have required property 'controlledParking'");
492
- expect(errorMessages).toContain("must have required property 'electricVehicleChargingPoint'");
493
- expect(errorMessages).toContain("must have required property 'isListed'");
494
- expect(errorMessages).toContain("must have required property 'isConservationArea'");
495
- expect(errorMessages).toContain("must have required property 'hasTreePreservationOrder'");
496
- });
497
-
498
- test("waterAndDrainage state is invalid under nts2023 overlay when mainsFoulDrainage yesNo is Not known", () => {
499
- const validator = getValidator(schemaId, ["nts2023"]);
500
- const clonedExampleTransaction = JSON.parse(
501
- JSON.stringify(exampleTransaction)
502
- );
503
-
504
- // Set the waterAndDrainage to an actually invalid state for nts2023
505
- // The nts overlay restricts mainsFoulDrainage.yesNo to only "Yes" or "No"
506
- // (not "Not known" like the base schema allows)
507
- clonedExampleTransaction.propertyPack.waterAndDrainage = {
508
- "water": {
509
- "mainsWater": {
510
- "yesNo": "Yes",
511
- "waterMeter": {
512
- "isSupplyMetered": "No"
513
- }
514
- }
515
- },
516
- "drainage": {
517
- "mainsSurfaceWaterDrainage": {
518
- "yesNo": "Yes"
519
- },
520
- "mainsFoulDrainage": {
521
- "yesNo": "Not known" // This is invalid under nts2023 overlay
522
- }
523
- }
524
- };
525
-
526
- const isValid = validator(clonedExampleTransaction);
527
- expect(isValid).toBe(false);
528
-
529
- // Check that the validation error is about the invalid enum value
530
- const relevantError = validator.errors.find(error =>
531
- error.instancePath.includes('mainsFoulDrainage') &&
532
- error.message.includes('must be equal to one of the allowed values')
533
- );
534
- expect(relevantError).toBeDefined();
535
- });
536
-
537
- test("waterAndDrainage state with mainsFoulDrainage No missing offMainsDrainageSystem is now invalid under nts2023 overlay", () => {
538
- const validator = getValidator(schemaId, ["nts2023"]);
539
- const clonedExampleTransaction = JSON.parse(
540
- JSON.stringify(exampleTransaction)
541
- );
542
-
543
- // Set the waterAndDrainage to the state from the user request
544
- // This SHOULD be invalid because offMainsDrainageSystem is required when mainsFoulDrainage.yesNo is "No"
545
- clonedExampleTransaction.propertyPack.waterAndDrainage = {
546
- "water": {
547
- "mainsWater": {
548
- "yesNo": "Yes",
549
- "waterMeter": {
550
- "isSupplyMetered": "No"
551
- }
552
- }
553
- },
554
- "drainage": {
555
- "mainsSurfaceWaterDrainage": {
556
- "yesNo": "Yes"
557
- },
558
- "mainsFoulDrainage": {
559
- "yesNo": "No"
560
- // Missing offMainsDrainageSystem - this should make validation fail
561
- }
562
- }
563
- };
564
-
565
- const isValid = validator(clonedExampleTransaction);
566
- expect(isValid).toBe(false);
567
-
568
- // Check that the validation error is about missing offMainsDrainageSystem
569
- const relevantError = validator.errors.find(error =>
570
- error.instancePath.includes('mainsFoulDrainage') &&
571
- error.message.includes('offMainsDrainageSystem')
572
- );
573
- expect(relevantError).toBeDefined();
574
- });
@@ -1,128 +0,0 @@
1
- const { validateVerifiedClaims } = require("../../../index.js");
2
-
3
- const exampleVouch = require("../../examples/v3/exampleVouch.json");
4
- const exampleDocumentedVouch = require("../../examples/v3/exampleDocumentedVouch.json");
5
- const v3SchemaId =
6
- "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json";
7
-
8
- test("returns an empty array for a valid claim", () => {
9
- expect(validateVerifiedClaims([exampleVouch])).toEqual([]);
10
- });
11
-
12
- test("returns an empty array for a valid array of claims", () => {
13
- const claimsArray = [exampleVouch, exampleDocumentedVouch];
14
- expect(validateVerifiedClaims(claimsArray)).toEqual([]);
15
- });
16
-
17
- test("returns an array with an error stating if path is incorrect", () => {
18
- const clonedVouch = JSON.parse(JSON.stringify(exampleVouch));
19
- const originalPath = Object.keys(clonedVouch.claims)[0];
20
- const data = clonedVouch.claims[originalPath];
21
- clonedVouch.claims = {
22
- "/propertyPack/INVALID/councilTax": data,
23
- };
24
- // v3 schema, no overlay
25
- expect(validateVerifiedClaims([clonedVouch], v3SchemaId, null)).toEqual([
26
- "Path /propertyPack/INVALID/councilTax is not a valid PDTF schema path",
27
- ]);
28
- });
29
-
30
- test("returns errors if BASPI requirements are not met and BASPI overlay is specified", () => {
31
- const clonedVouch = JSON.parse(JSON.stringify(exampleVouch));
32
- clonedVouch.claims = {
33
- "/propertyPack/delayFactors": {
34
- hasDelayFactors: { yesNo: "Yes" },
35
- },
36
- };
37
- const errors = validateVerifiedClaims([clonedVouch], v3SchemaId, ["baspiV4"]);
38
- expect(errors).toEqual([
39
- {
40
- instancePath: "/hasDelayFactors",
41
- schemaPath: "#/properties/hasDelayFactors/oneOf/1/required",
42
- keyword: "required",
43
- params: { missingProperty: "details" },
44
- message: "must have required property 'details'",
45
- },
46
- {
47
- instancePath: "/hasDelayFactors",
48
- schemaPath: "#/properties/hasDelayFactors/oneOf/1/required",
49
- keyword: "required",
50
- params: { missingProperty: "attachments" },
51
- message: "must have required property 'attachments'",
52
- },
53
- ]);
54
- });
55
-
56
- test("returns no errors if BASPI requirements are not met and null overlay is specified", () => {
57
- const clonedVouch = JSON.parse(JSON.stringify(exampleVouch));
58
- clonedVouch.claims = {
59
- "/propertyPack/delayFactors": {
60
- hasDelayFactors: { yesNo: "Yes" },
61
- },
62
- };
63
- const errors = validateVerifiedClaims([clonedVouch], v3SchemaId, null);
64
- expect(errors).toEqual([]);
65
- });
66
-
67
- test("returns errors for invalid fields even if null overlay is specified", () => {
68
- const clonedVouch = JSON.parse(JSON.stringify(exampleVouch));
69
- clonedVouch.claims = {
70
- "/propertyPack/delayFactors": {
71
- hasDelayFactors: { yesNo: "Maybe" },
72
- },
73
- };
74
- const errors = validateVerifiedClaims([clonedVouch], v3SchemaId, null);
75
- expect(errors).toHaveLength(4);
76
- });
77
-
78
- test("returns an array of errors for verified claim with multiple paths", () => {
79
- const clonedVouch = JSON.parse(JSON.stringify(exampleVouch));
80
- clonedVouch.claims = {
81
- "/propertyPack/cousncilTaxBad": {
82
- councilTaxBand: "D",
83
- councilTaxAffectingAlterations: {
84
- yesNo: "Yes",
85
- details:
86
- "Extension added in 2005 to add bedroom with ensuite shower room. Certificate of Compliance issued 17th Feb 2006 and council tax updated",
87
- },
88
- },
89
- "/propertyPack/councilTaxBadTwo": {
90
- councilTaxBand: "D",
91
- councilTaxAffectingAlterations: {
92
- yesNo: "Yes",
93
- details:
94
- "Extension added in 2005 to add bedroom with ensuite shower room. Certificate of Compliance issued 17th Feb 2006 and council tax updated",
95
- },
96
- },
97
- };
98
- expect(validateVerifiedClaims([clonedVouch], v3SchemaId, null)).toEqual([
99
- "Path /propertyPack/cousncilTaxBad is not a valid PDTF schema path",
100
- "Path /propertyPack/councilTaxBadTwo is not a valid PDTF schema path",
101
- ]);
102
- });
103
-
104
- test("returns an empty array of errors for verified claim with multiple valid paths", () => {
105
- const clonedVouch = JSON.parse(
106
- JSON.stringify(exampleVouch),
107
- v3SchemaId,
108
- null
109
- );
110
- clonedVouch.claims = {
111
- "/propertyPack/councilTax": {
112
- councilTaxBand: "D",
113
- councilTaxAffectingAlterations: {
114
- yesNo: "Yes",
115
- details:
116
- "Extension added in 2005 to add bedroom with ensuite shower room. Certificate of Compliance issued 17th Feb 2006 and council tax updated",
117
- },
118
- },
119
- "/propertyPack/address": {
120
- line1: "property.line1",
121
- line2: "property.line2",
122
- town: "property.city",
123
- county: "property.province",
124
- postcode: "property.postcode",
125
- },
126
- };
127
- expect(validateVerifiedClaims([clonedVouch], v3SchemaId, null)).toEqual([]);
128
- });