generated from ministryofjustice/opg-template-repository
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat/SSM-34: introduce lpc parser sanitizer & validator
- Loading branch information
Showing
8 changed files
with
246 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package lpc_parser | ||
|
||
import ( | ||
"github.com/ministryofjustice/opg-scanning/internal/parser" | ||
"github.com/ministryofjustice/opg-scanning/internal/types/lpc_types" | ||
) | ||
|
||
func Parse(data []byte) (interface{}, error) { | ||
doc := &lpc_types.LPCDocument{} | ||
return parser.DocumentParser(data, doc) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package lpc_parser | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/ministryofjustice/opg-scanning/internal/parser" | ||
"github.com/ministryofjustice/opg-scanning/internal/types/lpc_types" | ||
) | ||
|
||
type Sanitizer struct { | ||
doc *lpc_types.LPCDocument | ||
baseSanitizer *parser.BaseSanitizer | ||
} | ||
|
||
func NewSanitizer() *Sanitizer { | ||
return &Sanitizer{ | ||
doc: &lpc_types.LPCDocument{}, | ||
} | ||
} | ||
|
||
func (v *Sanitizer) Setup(doc interface{}) error { | ||
if doc == nil { | ||
return fmt.Errorf("document is nil") | ||
} | ||
|
||
v.doc = doc.(*lpc_types.LPCDocument) | ||
v.baseSanitizer = parser.NewBaseSanitizer(v.doc) | ||
|
||
return nil | ||
} | ||
|
||
func (s *Sanitizer) Sanitize() (interface{}, error) { | ||
if err := s.baseSanitizer.SanitizeStruct(s.doc); err != nil { | ||
return nil, err | ||
} | ||
|
||
return s.doc, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package lpc_parser | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/ministryofjustice/opg-scanning/internal/parser" | ||
"github.com/ministryofjustice/opg-scanning/internal/types/lpc_types" | ||
) | ||
|
||
type Validator struct { | ||
doc *lpc_types.LPCDocument | ||
baseValidator *parser.BaseValidator | ||
} | ||
|
||
func NewValidator() *Validator { | ||
return &Validator{ | ||
doc: &lpc_types.LPCDocument{}, | ||
} | ||
} | ||
|
||
func (v *Validator) Setup(doc interface{}) error { | ||
if doc == nil { | ||
return fmt.Errorf("document is nil") | ||
} | ||
|
||
v.doc = doc.(*lpc_types.LPCDocument) | ||
v.baseValidator = parser.NewBaseValidator(v.doc) | ||
|
||
return nil | ||
} | ||
|
||
func (v *Validator) Validate() error { | ||
// Common witness validations | ||
v.baseValidator.WitnessSignatureFullNameAddressValidator("Page10", "Section9") | ||
|
||
// Section validations | ||
v.baseValidator.ValidateSignatureDate("Page11", "Section10", "") | ||
|
||
// TODO add more validation for LPC | ||
|
||
// Return errors if any | ||
if messages := v.baseValidator.GetValidatorErrorMessages(); len(messages) > 0 { | ||
return fmt.Errorf("failed to validate LP1H document: %v", messages) | ||
} | ||
|
||
return nil | ||
} |
71 changes: 71 additions & 0 deletions
71
service-app/internal/parser/lpc_parser/lpc_validator_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package lpc_parser | ||
|
||
import ( | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/ministryofjustice/opg-scanning/internal/parser" | ||
"github.com/ministryofjustice/opg-scanning/internal/util" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestValidLPCXML(t *testing.T) { | ||
validator := getLPCValidator(t, "LPC-valid.xml") | ||
err := validator.Validate() | ||
require.NoError(t, err, "Expected no errors for valid LPC XML") | ||
} | ||
|
||
func TestInvalidLPCXML(t *testing.T) { | ||
validator := getLPCValidator(t, "LPC-invalid.xml") | ||
err := validator.Validate() | ||
require.Error(t, err, "Expected validation errors for invalid LPC XML, but got none") | ||
|
||
messages := validator.(*Validator).baseValidator.GetValidatorErrorMessages() | ||
|
||
expectedErrMsgs := []string{ | ||
"(?i)found only 1 attorney block; 2 required", // minOccurs=2 but only 1 present | ||
"(?i)missing Donor element in ContinuationSheet1", // required <Donor> is missing | ||
"(?i)invalid element BURNN instead of BURN", // if there is a typo in the element name | ||
"(?i)missing PhysicalPage element", // required element not found | ||
} | ||
|
||
t.Log("Actual messages from validation:") | ||
t.Log(messages) | ||
|
||
for _, pattern := range expectedErrMsgs { | ||
regex, compErr := regexp.Compile(pattern) | ||
require.NoError(t, compErr, "Failed to compile regex for pattern: %s", pattern) | ||
|
||
found := false | ||
for _, msg := range messages { | ||
if regex.MatchString(msg) { | ||
found = true | ||
break | ||
} | ||
} | ||
|
||
require.True(t, found, "Expected error message pattern not found: %s", pattern) | ||
} | ||
} | ||
|
||
func TestInvalidLPCDateOrderXML(t *testing.T) { | ||
validator := getLPCValidator(t, "LPC-invalid-dates.xml") | ||
err := validator.Validate() | ||
require.Error(t, err, "Expected validation errors due to date ordering but got none") | ||
|
||
messages := validator.(*Validator).baseValidator.GetValidatorErrorMessages() | ||
|
||
found := util.Contains(messages, "all form dates must be before the earliest applicant signature date") | ||
require.True(t, found, "Expected date ordering validation error not found in messages") | ||
} | ||
|
||
func getLPCValidator(t *testing.T, fileName string) parser.CommonValidator { | ||
xml := util.LoadXMLFileTesting(t, "../../../xml/"+fileName) | ||
|
||
doc, err := Parse(xml) | ||
require.NoError(t, err, "Failed to parse %s", fileName) | ||
|
||
validator := NewValidator() | ||
validator.Setup(doc) | ||
return validator | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<LPC xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:noNamespaceSchemaLocation="example.xsd"> | ||
<Page1> | ||
<ContinuationSheet1> | ||
<!-- Only ONE Attorney here, which violates minOccurs="2" --> | ||
<Attorney> | ||
<Attorney>true</Attorney> | ||
<ReplacementAttorney>false</ReplacementAttorney> | ||
<PersonToNotify>false</PersonToNotify> | ||
<Title>Mr</Title> | ||
<FirstName>Harry</FirstName> | ||
<LastName>Potter</LastName> | ||
<DOB>1980-07-31</DOB> | ||
<Address> | ||
<Address1>4 Privet Drive</Address1> | ||
<Address2>Little Whinging</Address2> | ||
<Address3>Surrey</Address3> | ||
<Postcode>HP1 1HP</Postcode> | ||
</Address> | ||
<Email>[email protected]</Email> | ||
</Attorney> | ||
|
||
<!-- Donor is missing entirely. The XSD requires <Donor> here. --> | ||
</ContinuationSheet1> | ||
|
||
<!-- BURN is present but spelled incorrectly: "BURNN" (typo) --> | ||
<BURNN>Typo in element name</BURNN> | ||
|
||
<!-- Missing <PhysicalPage> altogether --> | ||
</Page1> | ||
</LPC> |
29 changes: 0 additions & 29 deletions
29
service-app/xml/LPC-section4-replacement-attorney-trust-corp.xml
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<LPC xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:noNamespaceSchemaLocation="example.xsd"> | ||
<Page1> | ||
<ContinuationSheet1> | ||
<Attorney> | ||
<Attorney>true</Attorney> | ||
<ReplacementAttorney>false</ReplacementAttorney> | ||
<PersonToNotify>false</PersonToNotify> | ||
<Title>Mr</Title> | ||
<FirstName>John</FirstName> | ||
<LastName>Doe</LastName> | ||
<DOB>1970-01-01</DOB> | ||
<Address> | ||
<Address1>1 Example Road</Address1> | ||
<Address2>Example Town</Address2> | ||
<Address3>Example County</Address3> | ||
<Postcode>EX4 MPL</Postcode> | ||
</Address> | ||
<Email>[email protected]</Email> | ||
</Attorney> | ||
<Attorney> | ||
<Attorney>false</Attorney> | ||
<ReplacementAttorney>true</ReplacementAttorney> | ||
<PersonToNotify>false</PersonToNotify> | ||
<Title>Mrs</Title> | ||
<FirstName>Mary</FirstName> | ||
<LastName>Smith</LastName> | ||
<DOB>1975-05-05</DOB> | ||
<Address> | ||
<Address1>2 Example Avenue</Address1> | ||
<Address2>Example Town</Address2> | ||
<Address3>Example County</Address3> | ||
<Postcode>EX4 MPL</Postcode> | ||
</Address> | ||
<Email>[email protected]</Email> | ||
</Attorney> | ||
|
||
<!-- Required Donor block --> | ||
<Donor> | ||
<FullName>Jane Donor</FullName> | ||
<Signature>true</Signature> | ||
<Date>2025-01-29</Date> | ||
</Donor> | ||
</ContinuationSheet1> | ||
<BURN>Some text here</BURN> | ||
<PhysicalPage>1</PhysicalPage> | ||
</Page1> | ||
</LPC> |