@pdtf/schemas 3.2.1-8 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,7 @@ const {
8
8
  getValidator,
9
9
  getSubschemaValidator,
10
10
  getTitleAtPath,
11
+ overlaysMap,
11
12
  } = require("../../../index.js");
12
13
 
13
14
  const exampleTransaction = require("../../examples/v3/exampleTransaction.json");
@@ -90,6 +91,18 @@ test("sample with missing dependent required fields is invalid", () => {
90
91
  expect(isValid).toBe(false);
91
92
  });
92
93
 
94
+ test("sample with missing dependent required fields with NTS overlay is invalid", () => {
95
+ // Previously a required field was missing from the NTS overlay
96
+ const clonedExampleTransaction = JSON.parse(
97
+ JSON.stringify(exampleTransaction)
98
+ );
99
+ clonedExampleTransaction.propertyPack.ownership.ownershipsToBeTransferred[0].leaseholdInformation =
100
+ undefined;
101
+ const validator = getValidator(schemaId, ["nts2023"]);
102
+ const isValid = validator(clonedExampleTransaction);
103
+ expect(isValid).toBe(false);
104
+ });
105
+
93
106
  test("correctly gets a top level subschema", () => {
94
107
  const subschema = getSubschema("/propertyPack");
95
108
  expect(subschema.title).toBe("Property Pack");
@@ -396,3 +409,234 @@ test("correctly gets titles across schemas, arrays and non-existient title prope
396
409
  )
397
410
  ).toBe("Please provide their full names and ages.");
398
411
  });
412
+ test("validates a valid contract", () => {
413
+ const path = "/contracts";
414
+ const data = jp.get(exampleTransaction, path);
415
+ const validator = getSubschemaValidator(path, exampleTransaction.$schema);
416
+ const isValid = validator(data);
417
+ expect(isValid).toBe(true);
418
+ });
419
+
420
+ test("overlay as key and as object produce identical results", () => {
421
+ // Get the NTS overlay object directly from the overlays map
422
+ const ntsOverlayObject = { ...overlaysMap[schemaId]["nts2023"] };
423
+ // Remove the $id to prevent schema registration conflicts
424
+ ntsOverlayObject.$id =
425
+ "https://trust.propdata.org.uk/schemas/v3/overlays/nts2024.json";
426
+
427
+ // Get schema using the key
428
+ const schemaWithKey = getTransactionSchema(schemaId, ["nts2023"]);
429
+
430
+ // Get schema using the object
431
+ const schemaWithObject = getTransactionSchema(schemaId, [ntsOverlayObject]);
432
+
433
+ // Create copies without $id for comparison
434
+ const schemaWithKeyNoId = { ...schemaWithKey };
435
+ const schemaWithObjectNoId = { ...schemaWithObject };
436
+ delete schemaWithKeyNoId.$id;
437
+ delete schemaWithObjectNoId.$id;
438
+
439
+ // Deep compare the results (excluding $id)
440
+ expect(schemaWithObjectNoId).toEqual(schemaWithKeyNoId);
441
+
442
+ // Test that validation produces the same errors
443
+ const validatorWithKey = getValidator(schemaId, ["nts2023"]);
444
+ const validatorWithObject = getValidator(schemaId, [ntsOverlayObject]);
445
+
446
+ validatorWithKey(exampleTransaction);
447
+ validatorWithObject(exampleTransaction);
448
+
449
+ // Compare validation errors
450
+ expect(validatorWithObject.errors).toEqual(validatorWithKey.errors);
451
+ });
452
+
453
+ test("correctly merges custom Japanese Knotweed overlay with base schema", () => {
454
+ // Load the custom overlay
455
+ const customOverlay = require("../../examples/v3/exampleCustomOverlay.json");
456
+
457
+ // Get base schema and schema with overlay
458
+ const baseSchema = getTransactionSchema(schemaId);
459
+ const schemaWithOverlay = getTransactionSchema(schemaId, [customOverlay]);
460
+
461
+ // Verify that other properties in propertyPack are preserved
462
+ expect(
463
+ Object.keys(schemaWithOverlay.properties.propertyPack.properties)
464
+ ).toEqual(Object.keys(baseSchema.properties.propertyPack.properties));
465
+
466
+ // Verify that other properties in specialistIssues are preserved
467
+ const baseSpecialistIssues =
468
+ baseSchema.properties.propertyPack.properties.specialistIssues;
469
+ const overlaidSpecialistIssues =
470
+ schemaWithOverlay.properties.propertyPack.properties.specialistIssues;
471
+ expect(Object.keys(overlaidSpecialistIssues.properties)).toEqual(
472
+ Object.keys(baseSpecialistIssues.properties)
473
+ );
474
+
475
+ // Verify that Japanese Knotweed section is updated
476
+ const japaneseKnotweed = overlaidSpecialistIssues.properties.japaneseKnotweed;
477
+ expect(japaneseKnotweed.title).toBe(
478
+ "Is the property affected by Japanese knotweed?"
479
+ );
480
+ expect(japaneseKnotweed.required).toEqual(["yesNo"]);
481
+
482
+ // Verify the oneOf conditions are updated
483
+ expect(japaneseKnotweed.oneOf).toHaveLength(2);
484
+ expect(japaneseKnotweed.oneOf[0].properties.yesNo.enum).toEqual([
485
+ "No",
486
+ "Not known",
487
+ ]);
488
+ expect(japaneseKnotweed.oneOf[1].properties.yesNo.enum).toEqual(["Yes"]);
489
+ expect(japaneseKnotweed.oneOf[1].required).toEqual([
490
+ "managementPlanInPlace",
491
+ "attachments",
492
+ ]);
493
+ });
494
+
495
+ test("correctly merges multiple overlays using both key and object references", () => {
496
+ // Load the custom overlay
497
+ const customOverlay = require("../../examples/v3/exampleCustomOverlay.json");
498
+
499
+ // Get schema with both overlays
500
+ const schemaWithOverlays = getTransactionSchema(schemaId, [
501
+ "nts2023",
502
+ customOverlay,
503
+ ]);
504
+
505
+ // Get individual overlay schemas for comparison
506
+ const ntsSchema = getTransactionSchema(schemaId, ["nts2023"]);
507
+ const customSchema = getTransactionSchema(schemaId, [customOverlay]);
508
+
509
+ // Verify propertyPack structure is preserved
510
+ const propertyPack = schemaWithOverlays.properties.propertyPack;
511
+ expect(Object.keys(propertyPack.properties)).toEqual(
512
+ expect.arrayContaining(
513
+ Object.keys(ntsSchema.properties.propertyPack.properties)
514
+ )
515
+ );
516
+
517
+ // Verify Japanese Knotweed changes from custom overlay are present
518
+ const japaneseKnotweed =
519
+ propertyPack.properties.specialistIssues.properties.japaneseKnotweed;
520
+ expect(japaneseKnotweed.title).toBe(
521
+ "Is the property affected by Japanese knotweed?"
522
+ );
523
+ expect(japaneseKnotweed.oneOf[1].required).toEqual([
524
+ "managementPlanInPlace",
525
+ "attachments",
526
+ ]);
527
+
528
+ // Verify customRef properties are correctly merged
529
+ expect(propertyPack.customRef).toBe("JKW");
530
+ expect(propertyPack.properties.specialistIssues.customRef).toBe("JKW.7");
531
+ expect(japaneseKnotweed.customRef).toBe("JKW.7.8");
532
+ expect(
533
+ japaneseKnotweed.oneOf[1].properties.managementPlanInPlace.customRef
534
+ ).toBe("JKW.7.8.2");
535
+ expect(japaneseKnotweed.oneOf[1].properties.attachments.customRef).toBe(
536
+ "JKW.7.8.3"
537
+ );
538
+ expect(japaneseKnotweed.properties.yesNo.customRef).toBe("JKW.7.8.1");
539
+
540
+ // Verify NTS specific changes are present (e.g., simplified enums)
541
+ const mainsElectricity =
542
+ propertyPack.properties.electricity.properties.mainsElectricity;
543
+ expect(mainsElectricity.properties.yesNo.enum).toEqual(["Yes", "No"]);
544
+
545
+ // Verify required fields from both overlays are merged
546
+ expect(propertyPack.required).toEqual(
547
+ expect.arrayContaining([
548
+ ...ntsSchema.properties.propertyPack.required,
549
+ ...customSchema.properties.propertyPack.required,
550
+ ])
551
+ );
552
+ });
553
+
554
+ test("correctly merges NTS and both custom overlays with proper required fields", () => {
555
+ // Load both custom overlays
556
+ const japaneseKnoweedOverlay = require("../../examples/v3/exampleCustomOverlay.json");
557
+ const managingAgentOverlay = require("../../examples/v3/exampleCustomOverlay2.json");
558
+
559
+ // Get schema with all overlays
560
+ const schemaWithOverlays = getTransactionSchema(schemaId, [
561
+ "nts2023",
562
+ japaneseKnoweedOverlay,
563
+ managingAgentOverlay,
564
+ ]);
565
+
566
+ // Navigate to the leasehold section in the oneOf array
567
+ const leaseholdSchema =
568
+ schemaWithOverlays.properties.propertyPack.properties.ownership.properties.ownershipsToBeTransferred.items.oneOf.find(
569
+ (schema) => schema.properties.ownershipType.enum[0] === "Leasehold"
570
+ );
571
+
572
+ // Verify the leasehold information structure
573
+ const leaseholdInfo = leaseholdSchema.properties.leaseholdInformation;
574
+
575
+ // Check required fields - should include both NTS and custom overlay requirements
576
+ expect(leaseholdInfo.required).toContain("contactDetails");
577
+ expect(leaseholdInfo.required).toContain("leaseTerm"); // from NTS
578
+ expect(leaseholdInfo.required).toContain("groundRent"); // from NTS
579
+
580
+ // Verify managing agent contact structure and refs
581
+ const managingAgent =
582
+ leaseholdInfo.properties.contactDetails.properties.contacts.properties
583
+ .managingAgent;
584
+ expect(managingAgent.macRef).toBe("MAC.4.1c");
585
+
586
+ // Verify contact details structure
587
+ const contact = managingAgent.properties.contact;
588
+ expect(contact.properties.nameOrOrganisation.macRef).toBe("MAC.4.1c.1");
589
+ expect(contact.properties.address.macRef).toBe("MAC.4.1c.0");
590
+ expect(contact.properties.telephone.macRef).toBe("MAC.4.1c.7");
591
+ expect(contact.properties.emailAddress.macRef).toBe("MAC.4.1c.8");
592
+
593
+ // Verify Japanese Knotweed section is still present and correct
594
+ const japaneseKnotweed =
595
+ schemaWithOverlays.properties.propertyPack.properties.specialistIssues
596
+ .properties.japaneseKnotweed;
597
+ expect(japaneseKnotweed.customRef).toBe("JKW.7.8");
598
+
599
+ // Verify NTS changes are still present
600
+ const mainsElectricity =
601
+ schemaWithOverlays.properties.propertyPack.properties.electricity.properties
602
+ .mainsElectricity;
603
+ expect(mainsElectricity.properties.yesNo.enum).toEqual(["Yes", "No"]);
604
+ });
605
+
606
+ test("ta7 overlay as key and as object produce identical results at leasehold info level", () => {
607
+ // Get the TA7 overlay object directly from the overlays map
608
+ const ta7OverlayObject = { ...overlaysMap[schemaId]["ta7ed3"] };
609
+ // Remove the $id to prevent schema registration conflicts
610
+ ta7OverlayObject.$id =
611
+ "https://trust.propdata.org.uk/schemas/v3/overlays/ta7ed3-copy.json";
612
+
613
+ // Get schemas using both methods
614
+ const schemaWithKey = getTransactionSchema(schemaId, ["ta7ed3"]);
615
+ const schemaWithObject = getTransactionSchema(schemaId, [ta7OverlayObject]);
616
+
617
+ // Navigate to the leasehold information section in both schemas
618
+ const getLeaseholdInfo = (schema) => {
619
+ const ownershipsToBeTransferred =
620
+ schema.properties.propertyPack.properties.ownership.properties
621
+ .ownershipsToBeTransferred;
622
+ const leaseholdSchema = ownershipsToBeTransferred.items.oneOf.find(
623
+ (schema) => schema.properties.ownershipType.enum[0] === "Leasehold"
624
+ );
625
+ return leaseholdSchema.properties.leaseholdInformation;
626
+ };
627
+
628
+ const leaseholdInfoWithKey = getLeaseholdInfo(schemaWithKey);
629
+ const leaseholdInfoWithObject = getLeaseholdInfo(schemaWithObject);
630
+
631
+ // Deep compare the leasehold information sections
632
+ expect(leaseholdInfoWithObject).toEqual(leaseholdInfoWithKey);
633
+
634
+ // Verify specific TA7 requirements are present in both
635
+ expect(leaseholdInfoWithKey.required).toContain("contactDetails");
636
+ expect(leaseholdInfoWithObject.required).toContain("contactDetails");
637
+
638
+ // Verify TA7 refs are present and identical
639
+ const contactDetails = leaseholdInfoWithKey.properties.contactDetails;
640
+ expect(contactDetails.ta7Ref).toBe("4.1");
641
+ expect(leaseholdInfoWithObject.properties.contactDetails.ta7Ref).toBe("4.1");
642
+ });