diff --git a/src/types.py b/src/types.py new file mode 100644 index 0000000..8c383c8 --- /dev/null +++ b/src/types.py @@ -0,0 +1,46 @@ +from pydantic import BaseModel +from typing import Any, Dict, Literal + +Server_call_return = Dict[str, Any] +class Invoice(BaseModel): + name: str + format: Literal["XML", "JSON", "HTML", "PDF"] + source: Literal["url", "file_upload", "raw_data", "text"] + data: str + +class Location(BaseModel): + type: Literal["xpath", "line"] + xpath: str + line: int + column: int + +class Violation(BaseModel): + rule_id: str + is_fatal: bool + location: Location + test: str + message: str + suggestion: str + +class Evaluation(BaseModel): + aspect: Literal["wellformedness", "syntax", "peppol", "schema"] + is_valid: bool + num_rules_fired: int + num_rules_failed: int + num_violations: int + violations: list[Violation] + + +class Report(BaseModel): + report_id: int + score: int + date_generated: str + invoice_name: str + invoice_raw: str + invoice_hash: str + is_valid: bool + total_num_violations: int + wellformedness: Evaluation + schemaEvaluation: Evaluation + syntax: Evaluation + peppol: Evaluatio \ No newline at end of file diff --git a/tests/helpers.py b/tests/helpers.py index caaba75..06fc8d2 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -92,3 +92,10 @@ def invalidate_invoice(invoice_text, choice, tag_name, text, index): pass return etree.tostring(root).decode('utf-8') + + +def replace_part_of_string(string, start, end, replace): + return string[:start] + replace + string[end:] + +def squeeze_text_inbetween(string, cursor, txt): + return string[:cursor] + txt + string[cursor:] \ No newline at end of file diff --git a/tests/schema_test.py b/tests/schema_test.py new file mode 100644 index 0000000..423de0f --- /dev/null +++ b/tests/schema_test.py @@ -0,0 +1,117 @@ +from src.types import Invoice, Evaluation +from tests.server_calls import report_schemavalid_v1 +from tests.constants import VALID_INVOICE_TEXT +from tests.helpers import * + +""" +===================================== +/report/schemavalid/v1 TESTS +===================================== +""" +def test_UBL_VersionID_specified_twice_invalid(): + # Invalidating the date + data = squeeze_text_inbetween(VALID_INVOICE_TEXT, 530, 532, "20") + + invoice = Invoice(name="My Invoice", format="XML", source="text", data=data) + + schema_evaluation = report_schemavalid_v1(invoice) + schema_evaluation = Evaluation(**schema_evaluation) + + assert schema_evaluation.aspect == "schema" + + # We expect exactly 1 rule to fail due to the capitalised tag + assert schema_evaluation.num_rules_failed == 1 + + # We expect exactly 1 violation due to the capitalised tag + assert schema_evaluation.num_violations == 1 + + # Thus there should be exactly 1 violation in the violation list + assert len(schema_evaluation.violations) == 1 + + violation = schema_evaluation.violations[0] + + # Check that the violation is flagged as fatal + assert violation.is_fatal + + # Check that the violation has a non-empty message, test and suggestion + assert violation.message + assert violation.test + assert violation.suggestion + + assert violation.location.type == "line" + + # Check that the location line/column are were the violation is + assert violation.location.line == 1 + assert violation.location.column == 555 + +def test_schema_currency_id_invalid(): + # Invalidating the date + data = insert_into_string(VALID_INVOICE_TEXT, 6200, "D") + + invoice = Invoice(name="My Invoice", format="XML", source="text", data=data) + + schema_evaluation = report_schemavalid_v1(invoice) + schema_evaluation = Evaluation(**schema_evaluation) + + assert schema_evaluation.aspect == "schema" + + # We expect exactly 1 rule to fail due to the capitalised tag + assert schema_evaluation.num_rules_failed == 1 + + # We expect exactly 1 violation due to the capitalised tag + assert schema_evaluation.num_violations == 1 + + # Thus there should be exactly 1 violation in the violation list + assert len(schema_evaluation.violations) == 1 + + violation = schema_evaluation.violations[0] + + # Check that the violation is flagged as fatal + assert violation.is_fatal + + # Check that the violation has a non-empty message, test and suggestion + assert violation.message + assert violation.test + assert violation.suggestion + + assert violation.location.type == "line" + + # Check that the location line/column are were the violation is + assert violation.location.line == 1 + assert violation.location.column == 555 + +def test_schema_percent_invalid(): + # Invalidating the date + data = insert_into_string(VALID_INVOICE_TEXT, 6316, "0") + + invoice = Invoice(name="My Invoice", format="XML", source="text", data=data) + + schema_evaluation = report_schemavalid_v1(invoice) + schema_evaluation = Evaluation(**schema_evaluation) + + assert schema_evaluation.aspect == "schema" + + # We expect exactly 1 rule to fail due to the capitalised tag + assert schema_evaluation.num_rules_failed == 1 + + # We expect exactly 1 violation due to the capitalised tag + assert schema_evaluation.num_violations == 1 + + # Thus there should be exactly 1 violation in the violation list + assert len(schema_evaluation.violations) == 1 + + violation = schema_evaluation.violations[0] + + # Check that the violation is flagged as fatal + assert violation.is_fatal + + # Check that the violation has a non-empty message, test and suggestion + assert violation.message + assert violation.test + assert violation.suggestion + + assert violation.location.type == "line" + + # Check that the location line/column are were the violation is + assert violation.location.line == 1 + assert violation.location.column == 555 \ No newline at end of file